Domain Driven Design, DDD pour les intimes

Préface d’une Lightning Talk en demi teinte.

Dernièrement j’ai accepté un défi fou : celui de parler de Domain Driven Design lors d’une conférence (PHP Tour 2012 organisé par l’AFUP) de…. 5 minutes. Vraiment fou, et pas une franche réussite. A trop vouloir insister sur l’importance des concepts sous-jacents, j’ai épuisé mon temps avant d’avoir pu faire passer tous les messages que je voulais. Pour me faire pardonner, voici tout ce que je souhaitais dire en 5 minutes.

Vous avez donc dit DDD ?

A la lecture du titre, vous pouvez penser « encore un acronyme à la signification abstraite ».

Pourtant, passé cette première réaction, il s’avère que DDD porte de nombreuses valeurs, sauf celle de se compliquer le quotidien. Je vais essayer de détailler rapidement l’essence du « Domain Driven Design », en utilisant un brin de mon expérience sur le sujet.

KISS

Un des crédos auquel j’accorde de plus en plus d’importance au fur et à mesure de ma carrière professionnelle est « Si c’est compliqué, cela ne fonctionnera pas ». En d’autres termes : « Faites simples ».

Lorsque je m’applique à utiliser mon clavier pour écrire du code, j’aime comprendre le code que j’écris sur le moment, comprendre le code que j’ai écrit la veille, comprendre le code que j’ai écrit il y a six mois. Plus que tout, j’aime que les autres développeurs comprennent le code que j’ai écrit.

Mon meilleur souvenir récent sur le sujet remonte à quelques semaines, en entendant « Mais… c’était aussi simple que ça de faire cette demande d’évolution ? » alors qu’une développeuse de l’équipe (au demeurant talentueuse) découvrait que le modèle objet de l’application réagissait… comme il le disait !

Domain Driven Design, c’est un peu ça. DDD vous rappelle des règles de bon sens et vous propose un ensemble de patterns pour y arriver.

Et la programmation objet fut

Il y a maintenant quelques années, alors que je foulais les bancs de l’école (et que mes principales réalisations se matérialisaient sous la forme de manipulations du mode 13h), j’étais sous le charme du langage C, amoureux fou de la manipulation des pointeurs, de pointeurs… de pointeurs…

Autant dire que ma vision de la programmation était limitée à l’exploit technique que cela induisait et à l’amusement qu’il y avait derrière tout cela : le défi, la satisfaction d’avoir résolu « l’énigme ».

J’étais presque incrédule devant la possibilité qu’un tel jeu puisse un jour devenir mon métier.

On m’a alors inculqué les bases de la programmation objet grâce à un exemple que tout développeur à du un jour croiser :

  • « Une voiture tourne, avance », « Un bateau tourne, avance » => encapsulation
  • « Un véhicule tourne, avance » => classe abstraite
  • « Un bateau est une sorte de véhicule » => Héritage
  • « J’ai besoin d’un véhicule pour avancer » => Polymorphisme

Bizarrement, j’ai compris l’évidence de ce que l’on m’expliquait sans pour autant l’intégrer dans mon esprit.

Et pourtant j’ai fait de la programmation objet durant les deux années qui ont suivi, plus pour satisfaire aux contraintes que l’on m’imposait (en deuxième année on fait du C++, « c’est mieux c’est objet »), que par conviction (mes projets personnels de petits jeux vidéos étaient toujours en bon vieux C procédural).

En stage de fin d’étude, alors que je développais (sous Delphi) un programme de génération et d’analyses d’enquêtes, que j’écrivais mon 100ème objet…. D’un coup… le déclic.

« C’est ça l’objet ! »

Enfin, j’avais compris l’objet. Toute la magie de ce mode de programmation m’était apparue. Cette révolution intellectuelle fut si forte que je me souviens encore de ce moment avec émotion, presque 15 ans plus tard.

La cohérence d’ensemble, l’abstraction du monde réel

J’ai à ce moment réalisé un point essentiel, à savoir que l’intérêt de la programmation objet ne réside pas dans l’encapsulation d’un objet unique, mais dans la modélisation globale d’un ensemble d’objets qui collaborent.

Notre métier, c’est de modéliser un sous ensemble du monde qui nous entoure… c’est de modéliser une problématique issue de la « vraie vie ».

Une lois pour faire appliquer les lois

DDD, c’est finalement un principe qui rappelle un principe de base : Modélisez la problématique, inscrivez dans votre modélisation l’intelligence métier associée.

Et la vie continue…

Mes premiers projets en tant qu’informaticien ont étés orientés vers la technique, très peu vers le métier. Ainsi, alors que j’arrivais dans le monde merveilleux de la SSII, confronté à mon premier projet d’entreprise, j’ai commis une grave erreur : J’ai modélisé les données du client, je n’ai pas modélisé sa problématique.

Non au pilotage par les données

Ce que l’on ne veut surtout pas avoir dans DDD, c’est une approche des développements pilotée par les données : Les données changent tout le temps, en tous les cas bien plus que les processus.

Un exemple simple pour vous en convaincre ? Un disque peut du jour au lendemain avoir de nouveaux attributs : un caractère collector, une durée différente, un code de téléchargement… mais son processus de vente reste globalement le même.

Au secours, mon modèle est anémique

Mes développements, pilotés par les données, affichaient un terrible défaut : ils n’étaient pas ou très peu réutilisables. Moi, champion de l’objet que je pensais être, fier de ma compréhension du concept, j’étais incapable d’obtenir une modélisation réutilisable des problématiques qui m’étaient confiées. Mes objets étaient creux, manipulés par des services tiers… ils n’étaient qu’une bête conversion Objets / Enregistrements.

Le signe annonciateur du désastre

Si vous pouvez transformer la plupart de vos objets en tableaux (en réalité en hashmap), c’est que votre intelligence métier ne réside pas dans vos objets, c’est donc probablement que votre modèle objet n’est pas aussi réutilisable qu’il pourrait l’être, pas aussi explicite qu’il devrait être. Vous souffrez probablement du mal dont j’ai longtemps souffert, la programmation objet orientée procédurale….

Cette méthode de programmation, en plus d’être mauvaise, regorge d’autres pièges dont les « classes de services statiques » ou, pire, les « fat controller ».

Objets, Patterns, MVC…. Mais tout faux.

Bizarrement, alors que ma pratique de la programmation objet coté métier était un véritable échec (les projets étaient tout de même livrés en temps et en heure), je produisais des modélisations objets satisfaisantes dès lors que le problème à résoudre se situait dans les couches techniques.

WHY ? WHY ?

Je comprenais la technique, je comprenais le problème à résoudre, donc je modélisais convenablement. En ce qui concerne le métier ma connaissance était insuffisante, mon intérêt n’était pas assez focalisé… mes solutions étaient donc mauvaises.

Il faut comprendre pour proposer une bonne solution

Voilà un autre enseignement prôné par DDD : Apprenez le métier de votre client. Interviewez votre client, discutez avec les experts du domaine, impliquez les utilisateurs tout au long du cycle de développement.

Si vous ne comprenez rien au métier de bibliothécaire, jamais vous ne ferez une bonne application pour aider le bibliothécaire. Il faut comprendre pour proposer une bonne solution.

Modélisez avec le client

Durant l’interview de votre client, dessinez avec lui les use cases, dessinez le modèle objet de votre application. Ici, je vous encourage surtout à user les feutres d’un paper board afin de dessiner de gros carrés reliés avec quelques traits et verbes, pas à dessiner un diagramme UML académique. Restez concentré sur l’objectif : faire participer le client.

Cette analyse devrait se faire directement avec l’équipe de développement, pas juste l’architecte, l’analyse ou le chef de projet. L’équipe de développement entière profitera de cette participation, le projet y gagnera par la suite en temps et en implication.

DDD, certifié compatible avec les méthodes Agiles

DDD est particulièrement compatible avec les méthodes agile en ce sens qu’il encourage le dialogue.
Pour encourager et maintenir ce dialogue tout au long de la vie du projet, le deuxième crédo de DDD est « définissez un langage omniprésent ».

Un chat est un chat

Si votre client parle d’un Bus pour désigner une rame de train, faites que dans votre code on parle aussi de Bus pour designer cette notion. Pas une RameBus, pas un Wagon, pas un TRDT_Bus ou un ITransportMarchandise…. Non, un « Bus ».
Aussi simple que cela puisse paraitre, c’est une idée fondamentale. Ne cherchez pas au début à produire une abstraction réutilisable de concepts que vous ne maîtrisez encore pas (et c’est normal), abstraction qui introduirait un vocabulaire que personne n’utilise coté métier. Restez simple, utilisez les mots du métier pour modéliser le domaine.

Si votre logiciel est écrit dans le même langage que le métier du client, n’importe quel nouveau développeur peut appendre le métier du client simplement en lisant le code. Les demandes d’évolution seront rédigées dans le même langage, et rien de plus agréable que de trouver dans le code le même vocabulaire que dans la demande client.

A l’inverse, rien de pire que d’avoir un objet Devis dans le code qui représente une notion de projet personnalisé pour le client…. Et que d’ailleurs la notion de devis dans la tête de votre client soit en réalité une notion de tarification. Arriver dans cette situation peut être une impasse et générer beaucoup d’incompréhensions.

Il n’y a pas que les objets dans la vie

Ce langage s’applique aux objets, mais bien sûr aussi au nommage de vos méthodes. Si on tag du contenu, ayez une méthode taguer, si on taponne ou si on check, utilisez les méthodes tamponne et check. C’est idiot, c’est évident, mais si on manque de vigilance le langage utilisé dans le code peut s’éloigner du langage client, et les dialogues entre équipe de développement et équipe clients seront plus difficiles.

Ce n’est plus de la magie noire

Certains développeurs, en agissant ainsi, ont l’impression de perdre leurs supers-pouvoirs et vocabulaires mystiques spécifiques. Parler dans la même langue que le client leur fait pour ainsi dire perdre l’illusion que seuls « nous, les informaticiens » pouvons comprendre une belle conception.

Toutefois notre valeur ne se cache pas dans notre capacité à transformer un vocabulaire existant en jargon technique, mais bel et bien dans notre capacité à modéliser simplement un problème complexe, tout en faisant cohabiter ce modèle avec des contraintes techniques diverses (persistance, droits, caches, performances, …)

Soyez transparents, aimez faire comprendre la technique aux personnes du métier et à l’inverse, ayez plaisir à comprendre le métier de votre client.

DDD, un monde de patterns

Enfin, DDD embarque également un ensemble de patterns pour diriger votre modélisation. Une partie de ces modèles de conception adresse la modélisation du métier en lui-même (Entités, Objets valeurs, Agrégats, Services), une autre partie adresse la façon de dialoguer avec la persistance et les problématiques de création (Entrepôts, Fabriques), alors que d’autres servent le découpage (Modules).

Conclusion

Domain Driven Design propose des concepts simples.

  1. Proposez une modélisation objet dans laquelle transparaît la valeur métier, les processus du client. Faites que ce modèle évolue au fur et à mesure de votre compréhension du domaine.
  2. Pour modéliser avec perfection ce modèle, dialoguez avec votre client et définissez ensemble un langage omniprésent utilisé dans le métier et dans votre code. Si le vocabulaire évolue, faites également évoluer votre modélisation.
  3. Ayez une bonne connaissance des patterns de base pour les mettre à profit dans votre modélisation.

Aller plus loin

  1. Je m’attendais à une introduction technique aux concepts et objets du DDD mais cette approche différente est très intéressante. Le DDD c’est le genre de méthode qui s’apprend itérativement, à la fois en comprenant le technique mais aussi en faisant l’effort pour chacun de prendre du recul sur son expérience et sa façon de travailler, et cet article aide beaucoup dans ce sens.

  2. Je rebondis sur « Non au pilotage par les données ». Comme je l’ai déjà évoqué avec toi, à mon avis le DDD est très proche du BDD, dans la mesure où il se focalise sur le Comportement fonctionnel de l’application (ou du Produit). BDD et DDD vont facilement de pair.

    Je dis souvent (par provocation) que « le développement est un accident de parcours d’un logiciel », pour dire que seul le fonctionnel compte, et que, oui, le code n’est pas une fin en soi.
    Effectivement, souvent les développeurs ont le sentiment de perdre leurs pouvoirs. Mais au contraire, à mon avis c’est justement comme ça qu’ils font leur vrai boulot : implémenter des solutions de qualité, pour offrir un bénéfice métier à l’utilisateur…

    Merci pour le billet! Pour compléter, n’oubliez pas qu’il existe un 2ème tome au DDD vite fait :-)

    • Bonjour et merci pour tes compléments.

      As tu un lien sur le deuxième tome DDD Vite Fait ? je ne l’ai pas trouvé après une première recherche… je voudrais de ce fait l’ajouter à l’article.

      • BDD, DDD…

        N’y voyez aucune offense mais tout ça sonne à mes oreilles d’extrémiste intégriste comme des « buzzwords » et ne sont finalement que des synonymes de « modélisation ».

        Que cette modélisation soit faite au niveau des classes par les tests unitaires ou au niveau applicatif par des tests fonctionnels, ou bien encore en amont par un dialogue continu et permanent avec le client ne change strictement rien, tout cela est blanc bonnet et bonnet blanc et c’est effectivement indispensable pour répondre correctement aux besoins du client.

        Et surtout, tous ces outils ne sont pas incompatibles, c’est même tout le contraire.

        Il n’y a pas besoin de choisir son école, son mode de pensée, sa philosophie, de décider de faire du BDD et du coup de refuser de faire du TDD parce que le BDD ou le BDD est LA solution.

        Ce serait d’ailleurs une grave erreur car tout cela est intrinsèquement liés et complémentaire et chaque élément du processus permet de compléter les autres en comblant leurs lacunes respectives.

        Après tout, écrire un test unitaire revient à définir le comportement que doit avoir une méthode d’une classe ou une fonction, et le développeur fait donc dans ce cas du BDD à l’échelle de la classe au lieu de le faire à l’échelle du programme.

        Même le test manuel a sa raison d’être et ne devrait surtout pas être omis sous prétexte que l’ensemble du code est testé via l’intégration continue.

        En effet, sauf évolution majeure dans un proche avenir, l’Humain est encore bien supérieur à la machine pour dire si le code répond correctement ou pas à ses besoins, ne serait-ce que parce qu’il sait (ou est censé le savoir…) ce qu’il veut.

        Or, bien souvent, la précision n’est pas apportée et du coup, les gens ont tendance à penser que le (?:DDD|TDD|BDD|etc) est exclusif de tout autre méthode ou solution.

        • N’y voyez aucune offense mais tout ça sonne à mes oreilles d’extrémiste intégriste comme des buzzwords et ne sont finalement que des synonymes de « modélisation ».

          Aucune offense, c’est globalement le message que je veux faire passer en disant « une lois pour faire appliquer les lois ».

          Or, bien souvent, la précision n’est pas apportée et du coup, les gens ont tendance à penser que le (?:DDD|TDD|BDD|etc) est exclusif de tout autre méthode ou solution.

          Nous sommes bien d’accord que DDD n’a absoluement rien à voir avec le TDD.

          Domain Driven Design est (s’il faut vulgariser) une approche de la modélisation, une façon de voir qui se focalise sur le métier, des outils pour dialoguer et maintenir le dialogue avec le client.

  3. Belle article. Cela me fait penser à la conversation que j’ai eu avec mon frère sur le travail d’informaticien.
    Il me disait que c’était surtout facilité le job des autres en apprennant ce qu’ils font.

  4. Merci pour cet article intéressant.

    J’ai toutefois une question par rapport à votre citation :

    Cette méthode de programmation, en plus d’être mauvaise, regorge d’autres pièges dont les « classes de services statiques » ou, pire, les « fat controller »

    Je comprends bien le souci des « fat controller », mais pourriez-vous préciser le problème des « classes de services statiques » ? (j’utilise cette méthode des classes de services statiques pour la couche de service de mon application)

  5. De l’usage des méthodes statiques | Gerald's Blog - pingback on 7 janvier 2013 at 18 h 08 min
  6. Ma réponse était un peu longue, alors je l’ai rédigée séparément : http://www.croes.org/gerald/blog/de-lusage-des-methodes-statiques/931/

  7. Merci pour ce développement ! :-)

  8. Merci Gérald pour l’article.

Laisser un commentaire


NOTE - Vous pouvez utiliser les éléments et attributs HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks and Pingbacks: