.NET et les ORM

Qu’est-ce qu’un ORM ?

Un mapping objet-relationnel (en anglais object-relational mapping ou ORM) est une technique de programmation informatique qui crée l’illusion d’une base de données orientée objet à partir d’une base de données relationnelle en définissant des correspondances (mapping) entre cette base de données et les objets du langage utilisé. On pourrait le désigner par « correspondance entre monde objet et monde relationnel ». (source : Wikipedia)

Ces solutions ont notamment pour objet de générer une couche de persistance robuste, pérenne et évolutive.

Quelle est la situation dans le monde .NET ?

Comme souvent pour les sujets d’industrialisation et de best pratices, le monde .NET connait un retard d’adoption par rapport au monde Java. Ce retard est en bonne partie imputable au retard pris par l’arrivée de solutions matures et exploitables proposées par Microsoft. Le corollaire de cette constatation est une hétérogénéité dans les modes d’accès aux données par l’applicatif. On retrouve notamment :

  • Microsoft ADO.NET : querystrings, procédures stockées
  • Microsoft Enterprise Library
  • ORM custom
  • ORM du marché

Quels sont les principaux freins à l’adoption d’un ORM ?

Il existe 5 raisons principales, d’ordre techniques, managériales et même organisationnelles :

  • La peur de la perte de contrôle sur les données : performances, non-maîtrise des requêtes générées automatiquement… C’est l’effet boîte noire.
  • De mauvais réflexes consistant à penser qu’un ORM n’est utile que pour les gros projets.
  • Une courbe d’apprentissage plus ou moins élevée selon le framework choisi.
  • Les ressources compétentes en SQL sont nombreuses.
  • Clivage possible entre les équipes études et les équipes DBA / Production

Bien que chacune de ces raisons puisse être justifiée, aucun de ces points n’est fondamentalement bloquant et des solutions de contournement peuvent être adoptées.

Pourquoi il faut tout de même y aller ?

La réponse à cette question est un simple calcul de retour sur investissement. Voici les paramètres essentiels d’évaluation de ce ROI :

  • Gain en productivité des développeurs : combien de temps est passé à réinventer la roue ?
  • Diminution du risque de dérapage et d’accumulation de dette technique par l’utilisation de best practices. Le coût de maintenance à moyen-long terme peut s’en retrouver sensiblement diminué.
  • Customisation possible avec les ORM modernes. Chaque organisation et chaque besoin étant unique, il est fondamental de pouvoir adapter ce type d’outil au contexte.
  • Flexibilité : développement « data driven » ou « class driven ». Tous les ORM permettent de partir de la base de données pour générer le modèle objet. Mais certains permettent de partir d’un modèle objet existant pour redescendre vers la base de données et d’en générer un script de création.

Toutefois, ne pas perdre de vue que…

… il y a toujours une base de données sur laquelle repose le stockage, et qu’il est nécessaire de connaître ses mécanismes et les concepts inhérents. En effet, une des principales dérives possibles est l’abstraction pure et simple pour les développeurs de la base de données. Or la base de données est, et restera, un point clé de la performance applicative. L’optimisation de requêtes, la gestion des concurrences d’accès, la maintien de l’intégrité des données resteront des éléments de réflexion et des points d’attention essentiels.

Comme pour tout framework, l’utilisation d’un ORM génère une courbe d’apprentissage. Il est important de le comprendre et d’assimiler ses concepts et les design patterns utilisés (Active Record, DataMapper…). Il faut voir cet état de fait comme un investissement.

Où se trouve la vérité ?

Comme souvent, dans le compromis.
Entre tout développer à la main et confier l’intégralité des interactions avec la BDD à un outil, il existe un juste milieu !
Il est possible de concilier le meilleur des deux mondes.

Notre expérience sur le sujet nous conduit à estimer :

  • 95% des requêtes simples et non-critiques sont confiées à l’outil, générant un gain en productivité.
  • 5% des requêtes critiques et nécessitant un tuning SQL feront l’objet de procédures stockées exécutées par l’ORM, permettant de garder le contrôle sur l’accès aux données et les performances.

Panorama des solutions

A- L’historique : NHibernate

Avantages

  • Maturité
  • Robustesse
  • Fort degré de customisation

Inconvénients

  • Paramétrage fastidieux (XML)
  • Performances
  • Difficulté au débuggage
  • Courbe d’apprentissage très forte
  • Pas de support de Linq
  • Dépendance à un projet open-source

B- La première solution Microsoft : Linq To Sql

Avantages

  • Intégré au framework .NET et au designer de Visual Studio
  • Customisation (procédures stockées, lazy load…)
  • Simplicité d’utilisation (Linq…)
  • Rapidité de mise en œuvre
  • Performances

Inconvénients

  • Limité à SqlServer
  • Mapping limité  1 table = 1 classe
  • Nécessite .NET 3.5+

C- La grosse artillerie Microsoft : Entity Framework

Avantages

  • Solution privilégiée par MS, sorte de Linq To Sql v2.0
  • Simplicité d’utilisation
  • Simplicité de mise en œuvre
  • Customisation très poussée : lazy load, héritage de tables, développement « class driven » ou « data driven »

Inconvénients

  • Performances légèrement en deça de Linq To Sql
  • Nécessite .NET 3.5+
  • Complexité parfois masquée par une interface simple (comme souvent avec les outils Microsoft)

D- L’outsider: Subsonic

Avantages

  • Légèreté
  • Compatibilité avec Linq depuis la v3
  • Simplicité de mise en œuvre

Inconvénients

  • Dépendance d’un éditeur tiers
  • Fonctionne par convention plutôt que par configuration, d’où une customisation moins poussée
  • Utilisation limitée des procédures stockées

E- Mais aussi…

Des projets plus marginaux existent, parfois fournis en open-source :

  • Microsoft DataSet typés
  • BL Toolkit
  • DataObjects.NET
  • LinqConnect
  • Telerik OpenAccess

Comment choisir ?

Le choix d’un ORM, s’il est bien choisi et correctement implémenté, n’est ni irrémédiable ni définitif. Il est toutefois très structurant. Parfois pour des raisons techniques (un ORM basé sur le design pattern ActiveRecord), mais le plus souvent pour des raisons d’impact sur la productivité de l’équipe et de réinvestissement.

Il est donc important de se poser un certain nombre de questions avant de se lancer :

  • Taille du projet (j-h) :  10j, 30j, 100+j ?
  • Politique DT/DSI : full Microsoft ou intégration d’outils tiers ?
  • Base de données : SQL Server ou autre ?
  • Class driven design ?
  • Temps alloué pour la prise en mains ?
  • L’équipe est-elle familière avec  Linq ?
  • Quelles sont les contraintes de performances ?
  • Quelles sont les contraintes liées à l’infrastructure, la production et l’administration des bases de données ?

Pour les « petits » projets SqlServer « from scratch » : Linq To Sql

  • Rapidité de mise en œuvre : designer
  • Robustesse
  • Performances / évolutivité

Pour les « gros » projets / « grands » projets : Entity Framework

  • Pérennité de la solution, support à long terme
  • Evolution rapide (déjà en v4)
  • Customisation poussée
  • Mise en œuvre facilitée par le designer

Conclusion : Peut-on se passer des solutions Microsoft ?

C’est difficile. Ces dernières solutions sont matures, pérennes et bénéficient de leur forte intégration au Framework .NET et à Visual Studio. Un autre élément à prendre en compte est que si les solutions tierces existent, c’est principalement parce que Microsoft a pris son temps pour développer les siennes. Depuis l’apparition de Linq To Sql et surtout Entity Framework, le marché s’est brutalement tassé. Le nombre d’ORM pour .NET était auparavant bien plus élevé. Aujourd’hui, beaucoup sont abandonnés, et peu demeurent.

Mais il faut garder à l’esprit que de vraies solutions tierces existent.

Sources :

Wikipedia FR / Wikipedia EN

ActiveRecord et DataMapper par Martin Fowler

Pourquoi utiliser des ORM en .NET par Philippe Vialatte

6 Commentaires Laisser un commentaire

Alexandre Victoor
mai 3, 2011 21:05

Merci pour cet article
A propos de nhibernate, j’avoue que je suis un peu surpris par le point « dépendance à un projet open-source » dans les inconvénients.
Microsoft a rendu open source le code de stylecop, faut-il cesser de l’utiliser ?
Plus sérieusement, que ce soit open-source ou commercial, l’important est que le produit soit toujours maintenu, qu’il soit possible ou non d’obtenir du support.
Voilà, sinon à propos de la conf XML de nhibernate, il y a une alternative : http://fluentnhibernate.org/

Répondre

De rien !
Pour revenir sur ce point sur la dépendance à un projet open source, c’est plus un point de vigilance qu’autre chose. La grande majorité des ORM open source ont été progressivement abandonnés ces dernières années. Tu me répondras que c’est le lot pour tous les projets, open source ou non. Ils ne sont pas destinés à vivre éternellement. Cependant, le choix d’un ORM étant un élément structurant, ça me parait important que la pérennité du projet soit un point d’attention.
Concernant StyleCop, il est toujours maintenu par MS, qui rythme les releases et décide des builds officiels.

Et tu as parfaitement raison de signaler FluentNHibernate, que j’aurais sans doute dû au moins évoquer. Je ne l’ai jamais essayé, mais ça a l’air de gommer un des principaux défauts de NHibernate, sans pour autant atteindre la facilité de configuration des solutions MS.

Répondre

Bonjour,

Un bon article qui explique bien certains enjeux de l’ORM et notamment le fait qu’il ne faut jamais oublier qu’il y a toujours une base de données
derrière.

A mon sens, c’est justement là où le bât blesse avec une approche ORM, car les développeurs font tout pour essayer de l’ignorer. J’ai même vu des projets où l’on commence à coder avant même d’avoir conçu la base de données. C’est très joli sur le papier, mais cela se passe souvent mal – indépendamment du surcoût – au moment où l’on branche la vraie base de données.

Là où je ne partage pas complètement la vision de l’article :

1. Je ne suis pas sûr que la situation de l’ORM dans le monde .NET traduise réellement un retard de Microsoft. Depuis 10 ans, des milliers de projets .NET ont été mis en production sans avoir besoin de recourir à l’ORM, c’est un fait, et ça marche.

Si Microsoft est « obligé » de s’y mettre, c’est plutôt une contrainte de la communauté qui vient de la transposition des approches populaires sous Java (comme Hibernate) vers le monde .NET. Je connais bien le point, j’ai eu la responsabilité de l’équipe des évangélistes développeurs pendant près de 5 ans. Donc Microsoft se trouve obligé de proposer sa propre solution d’ORM pour garder un minimum de contrôle sur une couche fondamentale des applications… d’où l’avénement d’Entity Framework.

Mais rien ne dit que dans 10 ans, une majorité des applications .NET tournera avec un ORM. Je suis même persuadé du contraire car il y a tout un tas de points techniques sur lesquelles les ORM ne sont pas satisfaisants. Vous pouvez lire par exemple les pages 16 à 18 de notre document de positionnement par rapport à Entity Framework
http://www.codefluententities.com/downloads/documents/CodeFluent%20Entities%20and%20Entity%20Framework.pdf. De nombreux besoins techniques critiques restent sans réponse.

2. Sur le « Pourquoi il faut quand même y aller ? », les arguments sont légitimes (et c’est d’ailleurs pour cela que nous avons créé le produit CodeFluent Entities !) mais l’ORM n’est pas la seule façon d’y répondre. Il me semble que vous devriez au moins mentionner l’existence de ces alternatives du monde « model-driven » car :

– Elles constituent une réponse aux enjeux que vous mentionnez
– Elles apportent d’autres bénéfices encore plus impactants comme la possibilité d’évoluer avec les technologies futures sans réécriture.

En tout cas, merci de cet article qui permet de poser le débat.

Mes 0,02 Euros,

Daniel COHEN-ZARDI
SoftFluent

Répondre

Bonjour,

On est bien d’accord sur l’importance de rester conscient de l’existence de la base de données « cachée » derrière l’ORM. Une chose que j’entends régulièrement est « avec un ORM, c’est pratique, on n’a pas à se soucier de la base et les développeurs peuvent se concentrer uniquement sur le code ». C’est le meilleur moyen de courir droit dans le mur.

A mon sens, il faut prendre l’ORM pour ce qu’il est : un accélérateur de développement, un moyen de standardiser l’accès aux données et de ne pas réinventer la roue en permanence. En aucun cas, il ne doit servir à « masquer la misère ». Si les développeurs partent dans cette optique, là encore, c’est le mur. Et bon courage pour redresser la barre une fois qu’ils se seront confrontés aux limites qu’ils se seront eux-mêmes imposées.

Là où je n’ai peut-être pas été suffisamment clair dans l’article, c’est que pour moi, le plus naturel est de partir de la base de données pour remonter vers le modèle objet. L’inverse est possible, mais pas forcément préférable. D’ailleurs, on a beau coupler les couches aussi faiblement qu’on le souhaite, au final, les projets qui consistent à prendre une application existante, la débrancher de sa base de données pour la rebrancher sur une autre sont somme toute bien rares.
S’il y a fatalement des contre-exemples à ce que je viens de dire, je reste persuadé que c’est vrai en règle générale.

1. Évidemment, on s’est passé d’ORM pendant des années. On s’est aussi passé de tout un tas d’autres outils sans lesquels on peut vivre mais qui sont pourtant bien pratiques.
A mon sens, quand la communauté réclame à corps et à cris une brique logicielle, il y a de bonnes chances que cette demande soit légitime. Et dans ce cas précis, je pense qu’elle l’est.
En ce qui concerne les contraintes techniques d’EF4, il y en a pas de doute. Comme avec tous les outils du monde. Ceci dit, MS va vite. Et j’ai entendu parler d’une date courant 2011 pour EF5.

2. Le sujet de cet article étant les ORM, je me suis naturellement cantonné à ces derniers. Je ne connaissais pas CodeFluent Entities. Je vais y jeter un oeil pour me faire une idée.

Merci pour votre commentaire !
En parallèle, je vais lire votre document.

Répondre

Un article intéressant sur le sujet http://seldo.com/weblog/2011/06/15/orm_is_an_antipattern

Le diagnostic est assez bon.
La conclusion est un peu radicale car elle tend à rejeter l’objet.

De notre côté, la solution est décrite par cette démonstration
http://blog.codefluententities.com/2011/06/16/codefluent-entities-webinar-june-15th-2011/

Daniel

Répondre

Bonjour,

Article interessant. J’en profite pour signaler deux choses. Premièrement, une petite erreur sur l’orthographe de Philippe Vialatte (un seul « i »). Et un test de performance sur plusieurs fournisseurs de données (SQL Natif, Linq to SQL et Entity Framework): http://immobilis.developpez.com/tutoriels/dotnet/test-performance-acces-donnees-linq-vs-sql-vs-entity-framework/

Cordialement

Immobilis

Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *