web-dev-qa-db-fra.com

Pourquoi n'aurais-je pas besoin d'un ORM dans un langage fonctionnel comme Scala?

Je me demande si je peux passer de Java à Scala dans un projet Spring + Hibernate pour profiter de certains Scala = des fonctionnalités telles que la correspondance de motifs, Option et ce qui me semble être une syntaxe plus propre en général. Je cherchais l'ORM par défaut dans l'écosystème Scala et j'ai trouvé des idées comme Activer (mais surtout j'essaie de trouver si Hibernate peut être utilisé avec Scala). En cherchant cela, j'ai lu ceci dans la Play documentation à propos de JPA + Scala.

Mais le point le plus important est: avez-vous vraiment besoin d'un mappeur Relationnal to Objects lorsque vous avez la puissance d'un langage fonctionnel? Probablement pas. JPA est un moyen pratique de résumer le manque de puissance de Java dans la transformation des données, mais il se sent vraiment mal quand vous commencez à l'utiliser à partir de Scala.

Je n'ai pas une compréhension approfondie de la façon d'utiliser la programmation fonctionnelle pour créer une application complète (c'est pourquoi j'ai l'intention d'utiliser Scala pour que je puisse comprendre cela progressivement, car il combine OO + Functional), donc je ne peux pas comprendre pourquoi je n'aurais pas besoin d'un ORM avec un langage fonctionnel et quelle serait l'approche fonctionnelle pour lutter contre la persistance du modèle de domaine.

Une approche DDD pour la logique métier a toujours du sens avec Scala, n'est-ce pas?

30
gabrielgiussi

Eh bien, une chose qui est importante à faire chaque fois que nous avons une discussion comme celle-ci est de distinguer clairement entre les mappeurs relationnels d'objets ("ORM") et couches d'abstraction de base de données . Un ORM est une sorte de couche d'abstraction de base de données, mais toutes les couches d'abstraction de base de données ne sont pas des ORM. Un bon outil à étudier pour comprendre cela est la populaire bibliothèque Python SQLAlchemy , qui se présente comme une "boîte à outils SQL et Object Relational Mapper "(mon gras), avec l'idée que ce sont des choses différentes. Comme ils l'ont mis dans leur page des fonctionnalités clés :

Aucun ORM requis

SQLAlchemy se compose de deux composants distincts, appelés Core et [~ # ~] orm [~ # ~ ] . Le Core est lui-même une boîte à outils d'abstraction SQL complète, fournissant une couche d'abstraction fluide sur une grande variété d'implémentations et de comportements DBAPI, ainsi qu'un langage d'expression SQL qui permet l'expression du langage SQL via le générateur Python expressions. Un système de représentation de schéma qui peut à la fois émettre des instructions DDL et introspecter les schémas existants, et un système de types qui permet tout mappage de types Python aux types de base de données, complète le système Le mappeur relationnel objet est alors un package facultatif qui s'appuie sur le noyau.

La première page décrit l'ORM comme ceci:

SQLAlchemy est surtout connu pour son mappeur objet-relationnel (ORM), un composant facultatif qui fournit le modèle de mappeur de données, où les classes peuvent être mappées à la base de données de manière ouverte et multiple - permettant au modèle objet et au schéma de base de données de se développer dans un manière découplée proprement depuis le début.

L'idée clé d'un ORM est d'essayer de combler le fameux décalage d'impédance relationnelle objet . Cela signifie définir des relations entre classes définies par l'utilisateur aux tables dans un schéma de base de données et fournir des opérations "d'enregistrement" et de "chargement" automatiques pour les classes de votre application.

En revanche, les couches d'abstraction de base de données non ORM ont tendance à être plus engagées dans le modèle de données relationnelles et dans SQL, et pas du tout à l'orientation objet. Ainsi, au lieu de présenter des "mappages" entre les tables et les classes et de cacher le schéma de la base de données au programmeur, ils ont tendance à exposer la base de données au programmeur mais avec de meilleures API et abstractions. Par exemple, les constructeurs de requêtes SQL vous permettent de générer des requêtes SQL complexes par programme, sans manipulation de chaîne, comme ceci ( n exemple de la bibliothèque jOOQ pour Java ):

// Typesafely execute the SQL statement directly with jOOQ
Result<Record3<String, String, String>> result =
    create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
          .from(BOOK)
          .join(AUTHOR)
          .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID))
          .where(BOOK.PUBLISHED_IN.equal(1948))
          .fetch();

Maintenant, le framework Play ne semble pas être à 100% en accord avec ce que je viens de décrire , mais leur argument semble être dans cet espace général: travailler directement avec le modèle relationnel au lieu de le traduire en cours et retour d'eux.

La bibliothèque jOOQ mérite d'être étudiée comme contrepoint aux ORM. Ils ont également quelques entrées de blog pertinentes qui valent la peine d'être lues:

30
sacundim

C'est un peu difficile à expliquer jusqu'à ce que vous ayez fait beaucoup de programmation fonctionnelle. Dans la programmation orientée objet, vos données sont en quelque sorte coincées dans un objet et y restent. Cet objet est transmis un peu et modifié un peu, mais vous travaillez généralement fondamentalement avec la même "identité" pendant la durée de vie de ces données.

Les ORM sont généralement conçus autour de ce paradigme. Vous récupérez certaines données de la base de données, les fusionnez dans un objet, éventuellement les modifiez en groupe, et lorsque vous avez terminé, vous avez toujours le même objet que vous pouvez réécrire dans la base de données.

La programmation fonctionnelle fonctionne différemment. Vos données ne conservent pas une seule identité au cours de leur durée de vie. Il est divisé, copié, partagé et transformé. Il s'écoule en quelque sorte à travers un tas de fonctions, puis est finalement réassemblé dans le formulaire de sortie dont vous avez besoin. Pour que toute API de base de données semble naturelle dans un langage fonctionnel, elle doit en tenir compte, contrairement à JPA.

20
Karl Bielefeldt

Dans scala il est toujours utile de mapper des tables de base de données à des objets, et il existe plusieurs façons de le faire.

Un framework populaire dans le monde de Scala est slick . Ce n'est pas un ORM, car il en fait moins (à savoir, il ne récupère pas les relations sans qu'on lui dise de ne joint explicitement).

Donc, vous mappez toujours des objets aux lignes de la base de données, mais vos objets sont immuables (donc pas de vidage d'état) et vous exécutez explicitement des requêtes à l'aide d'un DSL monadique. Le résultat est que vous obtenez beaucoup des "bonnes" parties d'un ORM sans les problèmes de mutabilité et les problèmes N + 1 imprévisibles.

Il convient de noter que les gens ont obtenu un grand succès en utilisant des bibliothèques beaucoup plus minces, comme anorm ou JDBC simple aussi, en utilisant des techniques fonctionnelles pour garder le code beau.

Une bibliothèque fantastique qui applique des techniques fonctionnelles au-dessus de JDBC est également doobie .

Vous avez donc beaucoup de choix pour l'accès à la base de données, mais Hibernate (qui semble être l'ORM de facto) n'est pas l'un des meilleurs, car il est biaisé vers la mutabilité.

10
triggerNZ

Vous n'avez pas besoin d'un ORM même dans les langages orientés objet.

Tout d'abord, qui a dit que vos données devaient être physiquement copiées de votre stockage persistant vers votre objet? Alan Kay , un homme derrière Smalltalk, voulait des objets pour se débarrasser des données . Il a suggéré qu'un objet ne peut avoir qu'une référence à une zone où ses données sont stockées.

Deuxièmement - quelle est la meilleure façon d'y parvenir? Je recommande identifier vos objets par leurs responsabilités , et ne pas penser aux données qu'ils possèdent. Si vous avez entendu parler de l'approche des cartes CRC, elle est utilisée exactement pour cela.

Et, enfin, juste au cas où vous retourneriez jamais au champ OO, voici un moyen de l'implémenter .

0
Zapadlo