Deuxième journée en compagnie d’Eric Evans, pour suivre la formation DDD (Domain Driven Design) chez Zenika. Je vous ai raconté hier dans le premier article, comment DDD était une philosophie, nous allons voir aujourd’hui la suite de l’aventure.
Nous avons débuté la journée autour de quelques patterns utiles pour DDD. Finalement, nous en connaissons un certain nombre, mais ici il s’agit de complément un peu différent des designs patterns des Gang of Four (GoF). Nous travaillons sur notre modèle, et sur nos éditeurs Javas toute la matinée, le tout entrecoupé de discussions et de séances de travail sur tableau blanc.
Eric nous présente les Entities et les Value-Objects. Ces marqueurs permettent de décrire rapidement les caractéristiques des objets de son modèle. J’utilise les termes anglais autant que possible, ne soyez pas étonné de lire « Entité » ou « Entity ».
Définition d’une Entity
Une Entité est un objet qui possède une Identité. Celle-ci est unique dans votre système, et aucun autre objet n’est identique à votre objet si son identité n’est pas identique à l’identité de votre objet.
L’identité d’un objet peut être un champ numérique (CargoID), un GUID, une clé primaire assignée par votre ORM, bref c’est un identifiant unique. Des exemples d’entités : un client, un conteneur, un véhicule ou une place de théâtre.
Pour comparer des Entités, il suffit donc de comparer leurs Identités et pas leurs attributs.
Définition d’un Value Object
Un VO est un objet caractérisé par ses attributs, qui ne possède pas d’identité. Si deux ValueObjets ont les mêmes attributs, ils sont identiques. Pour cette raison, il s’agit en général d’objets immuables, ce qui rend votre modèle plus simple. Par exemple mon Addresse postale est un ValueObject, qui sera peut-être utilisée par les autres habitants de mon immeuble. Mais dans mon système, je n’aurai finalement besoin que d’une seule instance de cette Addresse. Vous connaissez un Value Objet en Java, c’est la class String. Une String est immuable, et c’est bien sa valeur qui en fait en quelques sortes son identité. Un value object est comparé par valeur, il peut y avoir 2 instances de VO « identique », cela ne pose pas de problèmes, puisque l’objet est immuable.
Ce qui est intéressant, c’est que cela nous amène à reprendre du code et à le simplifier. Rapidement notre application s’allège, nos méthodes pour ajouter ou retirer des itinéraires à notre envoi de conteneur sont refactorisées. Puisque nos VO sont immuables, la synchronisation est inutile.
Il est intéressant de regarder comment rendre « immuable » une classe en Java. Je vois très bien cela comme une question à poser lors d’un entretien d’embauche. Peu de gens connaissent toutes les techniques, c’est un sujet pour Olivier du Coder’s Breakfast je pense.
Et c’est tout ?
Là où DDD prend tout son sens, c’est que vos objets de base vont être améliorés afin de gérer votre domaine. Nous avions hier une class Itinerary qui n’était qu’une class anémique constitué d’une liste d’étapes. Après refactoring, ce Value Object est capable de retourner de nouveaux objets Itinerary, de se valider afin de s’assurer qu’un itinéraire est valide. Il est capable de se tronquer et de retourner un segment… Bref ce que nous avons fait pendant la matinée, remet en question la modélisation objet « anémique » composé d’une Class d’une part, d’un DAO et d’un Service. En retravaillant sur la modélisation DDD, vous redonnez un rôle complet à vos objets.
Certains patterns ne sont-ils pas uniquement technique comme les DAOs ?
Je ne suis pas plus emballé pour l’instant. Difficile de restituer nos discussions. Nous travaillons ensuite sur l’importance de la bonne utilisation du couple equals/hashCode pour les Values Objects et les Entités, de l’importance pour les VO dont l’égalité est basée sur les attributs, et pas sur une clé technique.
Aggregate
Eric Evans présente ensuite un concept intéressant : la notion d’Aggregate. Il s’agit de prendre notre modèle objet simple composé de quelques classes, et de reconnaître les zones d’agrégation. Jusqu’ici vous ne comprenez rien, c’est normal. Si vous avez travaillé avec Hibernate, vous avez certainement configuré l’effacement en cascade non ? Par exemple, si j’efface un client de mon application je veux aussi effacer toutes les réservations qu’il a effectué. Par contre je ne veux pas effacer les Hôtels et les Avions qu’il a associé à ses voyages. Imaginez sur un tableau blanc les différents objets dont je viens de parler. Prenez un marqueur, et dessinez des boîtes autour des grappes d’objets qui doivent vivre ensemble. C’est pas si simple non ?
Technique d’Eric : dessinez le modèle physique en indiquant les instances. Et en effet, si je dessine un utilisateur « Nicolas » et que je dessine ensuite deux « Voyages », l’un est lié à « Hôtel Djerba » et l’autre à « Avion New-York », que j’ajoute la compagnie aérienne pour l’avion, là il devient facile d’identifier les instances.
En décomposant des Aggregates, vous venez de faire quelque chose de très intéressant. Que nos copains du NoSQL et du Cloud computing écoutent un peu. Il s’avère que chaque aggregat en DDD permet d’ajouter de l’Inconsistance entre les aggrégats. C’est un partitionnement du système.
Pour en savoir plus et peut-être mieux comprendre, je vous conseille « Aggregates and Aggregates Roots«
The Ubiquitous Language
Après un repas très sympa, nous nous retrouvons pour parler de l’importance de la communication entre les développeurs et les gens du métier. Pour illustrer cela, Eric Evans nous montre une série de vidéo où un développeur travaille avec une personne du métier. Quelques scènes cocasses, nous retrouvons des situations vécues. Dans l’une des vidéos, la personne du métier harcèle de questions le développeurs. Et celui-ci met fin à la discussion en disant « …de toutes les façons c’est dans les specs…« .
Le développeur vient de Mars, les clients viennent de Vénus. Je tenterai bien l’analogie avec ce best seller de John Gray mais je pense que quelqu’un aura l’idée en lisant ces lignes… Il y a un gouffre entre le développeur et le client. Ajoutez un mur de spécifications écrit pour « clarifier les choses » et pour « aider le développeur », saupoudrez d’une dose de cycle en V, et vous devriez arriver à du vécu.
DDD met en avant l’importance du Domaine. Une leçon d’Eric est qu’il est vital de définir ce que l’on appelle « The Ubiquitous Language ». C’est un vocabulaire définit par les gens du métier, appuyé par des exemples concrets. Ce n’est pas un espace pour que le développeur se lâche avec des mots comme « Classe », « Instance », « Objet » ou même « Partition ». On parlera plutôt de « Credit », « IntérêtCumules », « Echeancier ».
Lorsque j’étais en mission l’an passé, je garde un excellent souvenir d’une matinée de formation par une personne de la maîtrise d’ouvrage sur les stratégies de couverture et de calculs du risque financier sur les contrats dérivés.
Si vous êtes client, allez voir les développeurs et demandez-leur de vous expliquer ce qu’ils font. Si les termes sont trop techniques, allez chercher le livre d’Eric Evans. Il fait 590 pages. Mettez un grand coup sur la tête du développeur, et ensuite commencez à reprendre le pouvoir. Ce n’est pas à vous d’apprendre la langue des Geeks. C’est au développeur d’apprendre votre langue.
Si vous êtes développeur, j’espère que vous êtes humble. Allez chercher le livre d’Eric Evans, il fait 590 pages et il est lourd. Allez ensuite voir le client, et lorsque vous êtes devant lui, flanquez-vous un coup de livre sur la tête. Une fois le reboot effectué, écoutez humblement le client. Et repartez avec 2 choses : une liste de mots clés du projet agrémentés de définition. Et un bleu sur le crâne, preuve de votre rédemption.
Eric nous donne quelques pistes comme celle de ne pas restreindre la conversation à ce que le logiciel doit faire, à ce que le projet est censé faire. Vous devez parler de votre métier. Il est pour travailler de manière itérative sur le modèle. C’est une notion très importante.
Le modèle doit être itératif
Qui a déjà déclaré des « DummyCustomer » ou des « FakeProduct » dans son code ? A quoi cela vous a-t-il servi ? Dans l’exemple étudié, le développeur utilise un objet au sens Java, pour pouvoir appeler un service de routage. Or comme le montre Eric, c’est complètement absurde. Le développeur n’a pas voulu revoir son modèle. Ce genre de code indique que votre modèle n’est pas adapté. Il montre aussi le cas d’un calcul d’emprunt. Pour gérer le remboursement anticipé, le développeur « bidouille » et crée de faux versements techniques pour que son algo de calcul de taux s’en sorte… Evidemment c’est le signe d’un cancer grave de l’application, et il faut revoir le modèle.
Pour éviter ces cas, il nous invite à écrire des scénarii complets idéaux et des cas limites avec les personnes du métier, en utilisant les mots des clients, pas votre jargon technique. Dans une autre vidéo, nous voyons comment le développeur écoute et met en oeuvre les nouvelles techniques pour apprendre de la part de la personne du métier comment faire.
Je constate la chose suivante : plus les gens du métier sont loins de votre clavier, plus la bonne réalisation du projet sera dure.
Une structure où l’on fait reposer à une jeune maîtrise d’ouvrage la responsabilité de « capturer » la sacro-sainte connaissance des « gens du métier » ira dans le mur. C’est un principe de base du développement logiciel. Si ton client n’est pas disponible, alors ne fait pas le projet. Si tu ne rencontres pas d’utilisateurs finaux et que ton seul interlocuteur est un document Word, alors refuse le projet.
Conclusion
Nous avons ensuite travaillé d’autres concepts, comme l’idée d’historise les changements d’états de certains objets clés dans des objets, le pattern « Domain Events », ce fut intéressant. Sur le rythme de la formation, ce fut parfois un peu lent et pas toujours assez rythmé.
Entity, Value Object et Aggregator sont des patterns où les objets mélangent un état (State) et des comportements (Behaviors). Après cette deuxième journée, on comprend que les patterns classiques s’adaptent à la philosophie DDD. Il semble aussi qu’il existe des anti-patterns DDD comme les objets Anémiques, les multiplications de couches avec des DAO sans valeur ajoutée… Bref je pense qu’à l’issue de la formation j’aurai acquis non pas une nouvelle langue, mais une nouvelle culture.
La suite demain. Et n’oubliez pas que ce mercredi 17 février il y aura une présentation de DDD par Eric Evans.
A noter que les « Entity » sont des « Class » en UML, et les « Value Object » des « Datatype »… L’aggregation y est présente mais il ne font pas mélanger avec la composition.
J’irais quand même lire le livre mais finalement on dirait juste qu’il faut s’abstraire du code avant de programmer, non ?
Tout comme utiliser le vocabulaire client doit être la recommandation la plus enseignée (certes aussi la moins appliquée)…
Je recommanderai le livre « Requirements Engineering » qui expose une méthode permettant de décrire le modèle client avant de dériver le modèle du code.
Au sujet des agrégations, je me demande si ce concept est différent du concept d’association cher aux merisiens.
En tout cas, merci de l’article et de nous faire partager ces informations sur le DDD.
Intéressant… Je me pose une question : est-ce qu’on dispose en Java de classes de listes/map immuables ? Je ne parle pas de Collections.unmodifiableList, mais plutôt des listes / maps telles que présentées à la conf sur Clojure, sur lequelles les opérations de modifications retournent une liste prenant en compte la modification.
D’autres part, à votre avis est-ce qu’il serait facile de vérifier programmatiquement qu’une classe est immuable ? C’est une question ouverte…
Concernant l’aspect technique: si vous voulez ‘jouer’ avec ces notions, alors je vous conseille ce formidable framework, trop méconnu: Fornax Sculptor.