La quadrature du cercle nécessite en effet la construction à la règle et au compas de la racine carrée de π, ce qui est impossible en raison de la transcendance de π : les nombres constructibles sont les rationnels et les racines de certains polynômes de degré 2n à coefficients entiers, ce sont des nombres algébriques ce qui n'est pas le cas de π. (source wikipedia).
L'ORM est un problème classique de l'industrie logicielle, qui consiste à faire cohabiter un modèle relationnel et un modèle objet. Il est issu de l'omniprésence des bases de données relationnelles, et de l'approche orientée objet, communément pratiquée dans le monde du développement. Pourtant ces 2 mondes reposent sur des approches différentes. Le modèle relationnel est fondé sur la théorie des ensembles, l'algèbre relationnelle, et la logique formelle. Il permet d'appliquer des processus de normalisation qui garantissent la non-redondance des données. Le modèle objet est fondé essentiellement sur les concepts d'Identité, d'Etat, de Comportement et d'Encapsulation.
Les principales zones de frottement sont notamment les suivantes:
-
inadéquation de la relation d'association: dans une base de données, une relation est bidirectionnelle et s'implémente par une Foreign Key, une colonne qui pointe vers une l'identifiant d'une autre Entité; dans un modèle objet, elle n'est pas nécessairement bi-directionnelle et s'implémente par un pointeur vers une autre structure fortement typée.
-
inadéquation de l'héritage avec la logique relationnelle.
-
inadéquation entre l'identité de l'objet et l'identité en base.
L'objectif des 2 modèles est pourtant bien le même: représenter les informations du monde réel, l'un pour le stockage, l'autre pour les traitements et l'affichage. Mais leur différence d'approche fait que la friction entre les 2 modèles ne peut se faire sans heurts: de la même manière que la transcendance de π démontre l'impossibilité d'une solution pour le problème de la quadrature du cercle, "l'Impedence Mismatch" rend impossible la cohabitation. L'usage d'un ORM sera aussi compliqué qu'approximatif; il suffit de lire
Ted Neward et de regarder les nombreuses tentatives vaines de Microsoft sur le sujet (
Object Spaces, Active Recordsets, LINQ to SQL et Entity Framework) pour s'en convaincre. Et tous les spécialistes d'NHibernate vous le diront, "c'est une affaire de spécialistes !" et on ne peut pas mettre cet outil entre toutes les mains.
Alors que faire ? Il n'y a pas moultes solutions, il faut faire des sacrifices d'un côté ou de l'autre.
Solution 1: utiliser une base de données orientées objet, afin de rendre compatible l'approche utilisée par le développement et l'approche utilisée par le stockage. Mais l'histoire a montré que les bases de données orientées objet présentaient une complexité d'usage que n'ont pas les SGBDR, tandis que ceux-ci offraient au même moment une facilité de compréhension des concepts et des performances bien meilleures.
Solution 2: abandonner les concepts de l'approche objet qui sont en conflit avec l'approche relationnelle et garder dans son développement la logique relationnelle. On va bien sur utiliser des objets fortement typés dans leur déclaration pour faciliter la programmation, le langage et l'outil de développement sont bien adaptés pour le faire, mais on va préférer
-
une approche Entiés/Relations où les Entités sont indépendantes les unes des autres, et la relation qui joue le rôle de lien entre les Entités. Le frottement n'en sera que moins douloureux. Une Entité en mémoire ne connait pas la structure des Entités avec lesquelles elle est reliée. C'est la relation qui lui permet d'accéder a ses entités reliées, et qui garantit le caractère bi-directionnel de l'association entre les entités. Cela permet également d'avoir une implémentation invariante de la cardinalité et de faciliter la gestion du cycle de vie des entités, avec un contrôle total sur le LazyLoading.
-
abandonner purement et simplement l'Héritage (et indépendamment du sujet ORM, vous ne vous en porterez que mieux pour maintenir votre système !) Une approche de la conception par composition sera bien plus efficace à long terme.
-
ne pas mettre de comportement dans les Entités, et préférer une approche Service StateLess; la notion d'identité de l'instance perd alors son importance.
-
avoir des identifiants uniques sur les Entités, de type Guid. C'est l'identifiant technique qui jouera le rôle de clé primaire dans la base. Et ne surtout pas prendre des Int autoincrémenté, qui mettent une dépendance forte entre le stockége physique et l'allocation d'un nouvel identifiant.
Bien entendu, cette deuxième approche n'est pas immédiate, et elle remet en cause beaucoup de choses que les architectes/développeurs ont l'habitude de pratiquer. C'est néanmoins les choix que nous avons faits pour notre couche d'accès aux données. En prenant cette approche, nous avons résolu et facilité un bon nombre de problèmes posés par l'incompatibilité des 2 mondes et nous disposons d'un ORM facile à utiliser et puissant.
Nous y reviendrons dans les prochains jours, quand la bête sera disponible...