Domain-Driven Design & architecture hexagonale (Partie 1)

Rémy Campanals
6 min readNov 6, 2022

Bonjour fellow développeurs !

Aujourd’hui nous allons analyser les bien-faits de l’architecture hexagonale et du Domain-Driven Design dans la tech, dans un premier temps pour une API en PHP puis dans un second temps voir ensemble comment cela peut être appliqué à tout type de projet, par exemple une single page application en ReactJS.

Avant toute chose, nous devons mettre une chose au clair avant de commencer et pour cela je vais paraphraser une citation utilisée par notre cher Kevin Dunglas national lors de sa présentation du DDD et la version 3 d’API Platform :

Domain-Driven Design is NOT a fast way to build software. However, it is able to EASE your life when you have to deal with complex business expectations. ”

William Durand - DDD with Symfony2: Making Things Clear

Qu’est-ce que le DDD ?

Le DDD (ou Domain-Driven Design donc) est une approche de développement pour nous faciliter la vie quand les besoins business sont ou deviennent complexes.
C’est, de mon point de vue, la manière la plus efficace de découper son code (classes, entitées, object values, etc.) et de hiérarchiser les dossiers de l’application selon certaines règles.

Du coup, comment le DDD peut nous aider à construire des applications possédant un business complexe ? En considérant ton domaine (aussi appelé règles métiers) comme le coeur de ton application pour contraindre, contrôler et influencer notre manière de construire l’application.

Comment utiliser le DDD ?

Si vous êtes comme moi et que vous avez appris comment développer des applications web sur internet via des tutoriels et/ou en suivant la documentation de Symfony, votre hiérarchie de fichier va ressembler peu ou prou à ça :

La base.

Au début rien ne nous choque et c’est bien normal, d’ailleurs tous mes débuts de projets commencent à peu près comme ça quand je cherche à expérimenter quelque chose très rapidement.

Par contre le jour où votre application commence à prendre de l’ampleur, les fichiers s’entassent au même endroit (tous les controllers dans le dossier controller, toutes les entitées dans le dossier entity, etc…), on ne sait pas trop quelle classe communique avec qui, et je vous le donne en mille : la maintenance de l’application devient TRES vite compliqué surtout quand on commence à atteindre les 1000 fichiers ou plus.

Dans une startup c’est le moment où beaucoup de devs commencent à se demander s’il ne vaut mieux pas tout refaire from scratch, bloquant tout le monde ou presque pendant 1 an ou deux (selon la complexité de l’application et la taille de l’équipe IT), avec une chance de refaire les mêmes erreurs passées. C’est là que le DDD est salvateur si on a bien pensé son produit dès le début, ou que le métier requière de rapides changements techniques.

Bon, comment peut-on changer ça ? Si on reprend notre cas de figure du simple blog et qu’on y ajoutait une notion d’utilisateurs ? Par exemple pour y gérer la mise en favoris d’un article ? Reprenons un peu tout ça avec le DDD en tête :

“DDD ≠ RAD (Rapid Application Development)”

Pour comprendre comment en arriver là, il faut réfléchir l’application en fonction des règles métiers qui définisse notre produit : Pour fonctionner, mon entreprise a besoin de gérer un blog et des utilisateurs. Donc première chose à faire : Créer un dossier “Blog” et “Users” tout de suite à la racine du dossier src/.

Déjà d’un point de vue purement pratique, il est plus facile de s’y retrouver lorsqu’on cherche une action particulière de notre application rien qu’en utilisant nos yeux ! 👀

Ensuite, et je suppose que vous vous posez la question suivante : Pourquoi a-t-il créé deux entités BlogPostEntity (dans Blog/Entity/ et Users/Entity/) ?

La réponse est plutôt simple, on ne réfléchit plus que par le prisme de chaque domain désormais, et également pour éviter un anti-pattern destructeur : le God Object, l’objet ou la classe qui fait trop de choses ou qui en sait trop.

La solution : le Single Responsibility Principle

De par son nom, le SRP signifie que chaque classe ne devrait avoir qu’une seule responsabilité :

✅ “Pour que le produit fonctionne”, le Domain BlogPost doit évidemment avoir un id, un titre, un corps de texte, une date de création et c’est tout (propriétés définies par le produit évidemment).

❌ L’article ne doit pas savoir qui a ajouté le BlogPost en favoris (à la rigueur le produit peut contraindre le domain BlogPost à savoir le nombre de mise en favoris) pour fonctionner.

✅ “Pour que le produit fonctionne”, le Domain User doit évidemment avoir un id, une adresse email ou numéro de téléphone pour identifier l’utilisateur, avoir un mot de passe et c’est tout (propriétés également définies par le produit).

❌ L’utilisateur, pour fonctionner, ne doit pas savoir les informations de toutes les propriétés contenu dans l’entité BlogPost qui a été mis en favoris.

Et c’est là que la magie opère, l’entité BlogPost qui se situe quant à elle dans le Domain User lui peut ne posséder que la propriété id du BlogPost mis en favoris. Les autres informations qui définissent un BlogPost n’ont pas besoin d’être définies dans l’entité BlogPost du Domain User.

Petite parenthèse pour les API Rest

Si vous réalisez une API Rest, je vous encourage à respecter les conventions de nommage en ce qui concerne les routes pour accéder aux ressources souhaitées.

En REST, la data demandée est appellée “ressource”. Avoir une convention de nommage robuste et consistente est la meilleure des stratégies — et confirmera que cela est la meilleure des décisions sur le long terme.

Et ça tombe bien, l’architecture de votre application et REST coincident en terme de nommage des resources :

Toutes les bonnes practices s’alignent petit à petit ! :)

Fin de la parenthèse !

En pratique qu’est-ce que ça donne ?

En pratique ça demande plus de fichiers et plus de dossiers, mais des fichiers avec moins de ligne de code :

L’entité BlogPost pour le Domain Blog
L’entité BlogPost pour le Domain Users

En résulte des entités avec une seule responsabilité, qui dans le cas de la modification ou suppression d’une feature (la mise en favoris d’un article ici) n’entrainera que très peu de répercussion sur la feature principal du produit qui est : Afficher des articles de blog.

En conclusion sur le Domain-Driven Design

Nous l’avons compris, mettre en place une architecture avec une approche en DDD ne se fait pas rapidement, mais certaines choses nécessitent d’être bien faites dès le début si on ne veut pas perdre d’avantage de temps plus tard et regretter de voir son produit s’effondrer à cause d’une maintenance laborieuse qui ralentit l’évolution de ce dernier ou voir le moral de son équipe IT tomber à plat (c’est plus fréquent qu’on ne le croit, trois start-ups sur trois que j’ai rejoins ont vu leur ancienne équipe mettre les voiles à mon arrivé à cause d’une dette technique insupportable à gérer).

Dans cette première partie, nous avons vu les bien faits de l’approche DDD, je trouve que cette approche s’allie très bien avec l’architecture hexagonale. Nous verrons dans la seconde partie comment la mettre en place, le temps que vous digérez tout ça et que vous commencez à l’appliquer dans vos projets ! 💻

PS : C’est mon premier article que je publie en ligne, n’hésitez pas à me dire dans les commentaires si cela vous a plu, si j’ai fais des erreurs pour pouvoir m’améliorer !

Si cela vous a aidé, partagez l’article pour que d’autres personnes puissent en profiter également ! ❤️

--

--

Rémy Campanals

CEO of Symbioze.org. Developper. UX/UI Designer. Well… a lot of things web related.