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

30

Je me demande si je peux passer de Java à Scala dans un projet Spring + Hibernate pour profiter de certaines fonctionnalités de Scala telles que la correspondance de modèles, Option et ce qui me semble 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 Activate (mais j'essaye surtout de savoir si Hibernate peut être utilisé avec Scala). En cherchant cela, j'ai lu ceci dans la documentation Play sur JPA + Scala.

Mais le point le plus important est: avez-vous vraiment besoin d'un mappeur relationnel aux objets 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 afin de pouvoir 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?

gabrielgiussi
la source
3
C'est une question d'opinion. Scala n'est pas purement fonctionnel, c'est aussi un langage OO, ce qui expliquerait pourquoi vous souhaitez toujours utiliser un outil ORM. Pour le mappage DB, voir par exemple: Slick , SORM , Anorm .
Jesper
Je ne cherche pas une opinion, je demande à quelque chose avec une compréhension profonde du paradigme fonctionnel quel est le moyen d'atteindre la persistance. Je sais que Scala est un hybride et je veux utiliser sa partie OO pour DDD. Vous dites donc que si j'adopte une approche DDD même avec Scala, un ORM est le chemin à parcourir?
gabrielgiussi
Dans les langages fonctionnels, vous traitez principalement des valeurs qui n'ont pas d'identité comme les objets. Par conséquent, vous n'avez pas besoin du suivi des modifications qui est l'un des principaux travaux d'un ORM.
Lee
2
Vous aimerez peut-être cette conférence: Du fonctionnel au réactif - Modèles de modélisation de domaine
Jesper
5
Vous n'avez pas besoin d' un ORM dans n'importe quelle langue principale.
GrandmasterB

Réponses:

30

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 les 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 SQLAlchemy de Python , qui se présente comme une "boîte à outils SQL et mappeur relationnel d'objet" (mon gras), avec l'idée que ce sont des choses différentes. Comme ils l'ont mis dans leur page de 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 des expressions Python génératives. 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 des 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 les relations entre les classes définies par l'utilisateur et les 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 programmation, sans manipulation de chaîne, comme ceci ( un 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 classes et inversement.

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:

sacundim
la source
19

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 un tas, 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 circule 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, et JPA ne le fait pas.

Karl Bielefeldt
la source
1
+1000 Les gens qui insistent pour utiliser Scala comme s'il s'agissait de Java ++ me font peur pour l'avenir du langage :(
Andres F.
9

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 cadre populaire dans le monde de Scala est lisse . Ce n'est pas un ORM, car il en fait moins (c'est-à-dire qu'il ne récupère pas les relations sans qu'on lui dise de faire explicitement les jointures).

Ainsi, 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 faut noter que les gens ont obtenu un grand succès en utilisant des bibliothèques beaucoup plus fines, comme anorm ou JDBC droit 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é en faveur de la mutabilité.

triggerNZ
la source
0

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 que les objets se débarrassent 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 d' identifier vos objets par leurs responsabilités , et de 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 reviendriez jamais sur OO-field, voici un moyen de l'implémenter .

Zapadlo
la source