Domain Driven Design ? (fr)
Kevin Le Dû
Posted on April 10, 2023
Le développement logiciel est un domaine en constante évolution, avec de nouveaux défis à relever et des solutions à mettre en place pour répondre aux exigences croissantes des entreprises. L'une des approches qui a gagné en popularité ces dernières années pour faciliter la compréhension et la gestion de la complexité des systèmes est le Domain Driven Design (DDD).
Le Domain Driven Design est une méthodologie de conception et de développement logiciel axée sur la modélisation du domaine métier et l'alignement étroit entre la logique métier et le code. L'objectif principal du DDD est de faciliter la communication entre les développeurs et les experts métier, tout en produisant un code plus compréhensible, maintenable et évolutif.
I. Concepts clés du Domain Driven Design
A. Modèle conceptuel
Le modèle conceptuel est l'élément central du Domain Driven Design. Il permet de représenter les éléments du domaine métier et leurs interactions. Voici les principaux concepts du modèle conceptuel :
Domaine
Le domaine fait référence au champ d'expertise ou au secteur d'activité spécifique autour duquel le logiciel est construit. Il s'agit de l'ensemble des problèmes métier que le logiciel doit résoudre. Le domaine est composé de plusieurs sous-domaines, chacun représentant un aspect spécifique du domaine global.
Sous-domaines
Les sous-domaines sont des parties distinctes du domaine global, correspondant à des zones de responsabilité ou des fonctionnalités métier. Ils permettent de découper le domaine en unités plus petites et gérables. Chaque sous-domaine est généralement associé à un contexte limité.
Contexte limité (Bounded Context)
Un contexte limité est un espace bien délimité où un modèle spécifique s'applique. Il découpe le système en plusieurs parties cohérentes et indépendantes, chacune ayant ses propres modèles, règles et langage. Les contextes limités servent à encapsuler la complexité et à éviter les ambiguïtés en clarifiant les responsabilités et les frontières de chaque sous-domaine.
Langage Ubiquitaire (Ubiquitous Language)
Le langage ubiquitaire est un vocabulaire partagé entre les développeurs et les experts métier pour décrire les éléments du domaine et leurs interactions. Ce langage commun facilite la communication et la compréhension entre les parties prenantes, tout en garantissant que le code reflète fidèlement la logique métier. Il est essentiel d'utiliser le langage ubiquitaire dans le code, les discussions et la documentation pour assurer une cohérence entre les différents éléments du projet.
Le modèle conceptuel sert de base pour la conception et l'implémentation du système. Il permet aux développeurs de mieux comprendre et représenter la complexité du domaine métier, en facilitant la communication avec les experts métier et en favorisant un code plus cohérent et maintenable. Dans la suite de cet article, nous aborderons les blocs de construction qui permettent de mettre en œuvre le modèle conceptuel dans le code, ainsi que les différentes couches d'architecture et les stratégies de collaboration entre contextes limités.
B. Blocs de construction
Les blocs de construction sont les éléments constitutifs du modèle conceptuel. Ils décrivent les entités, les comportements et les relations du domaine. Voici les principaux blocs de construction du DDD :
Entités
Les entités sont des objets du domaine qui possèdent une identité unique et persistante. Elles représentent des concepts métier importants et ont un cycle de vie au sein du système. Les entités sont définies par leur identité plutôt que par leurs attributs et sont responsables de l'application des règles métier qui leur sont propres.
Objets de valeur (Value Objects)
Les objets de valeur sont des objets immuables qui représentent des attributs ou des propriétés du domaine, sans identité propre. Ils sont définis uniquement par leurs attributs et sont souvent utilisés pour décrire des caractéristiques des entités ou des agrégats. Les objets de valeur permettent de simplifier le modèle en regroupant des données et des comportements liés, tout en garantissant l'immuabilité et la cohérence des données.
Agrégats
Les agrégats sont des groupes cohérents d'entités et d'objets de valeur qui sont traités comme une unité pour les opérations métier et la persistance. Ils garantissent la cohérence et l'intégrité des données en encapsulant les règles métier et en limitant les interactions externes à travers leurs racines d'agrégats. Les agrégats définissent également les frontières de la cohérence transactionnelle, assurant que les opérations métier sont réalisées de manière atomique.
Racines d'agrégats (Aggregate Roots)
Les racines d'agrégats sont des entités spéciales qui servent de point d'entrée pour les interactions avec un agrégat. Elles assurent la cohérence de l'agrégat en contrôlant et en validant les modifications apportées aux entités et objets de valeur qu'ils contiennent. Les racines d'agrégats sont la seule interface à travers laquelle les clients du domaine peuvent interagir avec les éléments de l'agrégat.
Répertoires (Repositories)
Les répertoires sont des objets responsables de la gestion de la persistance et de la récupération des agrégats. Ils fournissent une abstraction pour le stockage des données, permettant aux développeurs de se concentrer sur la logique métier sans se soucier des détails de la persistance. Les répertoires garantissent également que les agrégats sont correctement reconstruits à partir de l'état persistant lors de leur récupération.
Services
Les services sont des objets qui encapsulent des comportements métier qui ne relèvent pas naturellement d'une entité ou d'un agrégat. Ils fournissent des opérations métier de haut niveau et coordonnent les interactions entre les entités, les agrégats et les répertoires. Les services sont généralement sans état et n'ont pas d'identité propre.
Événements de domaine (Domain Events)
Les événements de domaine sont des messages qui représentent des changements d'état significatifs dans le domaine. Ils sont déclenchés par des actions métier et permettent de découpler les différentes parties du système, en facilitant la communication entre les composants et en favorisant une architecture plus modulaire et adaptable. Les événements de domaine sont souvent utilisés pour propager des changements d'état entre les contextes limités ou pour intégrer des systèmes externes. Ils peuvent également servir à enregistrer des informations sur l'historique des actions métier pour des raisons d'audit ou d'analyse.
Spécifications
Les spécifications sont des objets qui encapsulent des règles métier complexes ou des conditions qui doivent être satisfaites par les entités et les agrégats. Elles sont utilisées pour valider les opérations métier, pour sélectionner les éléments qui répondent à certaines conditions ou pour guider les décisions métier. Les spécifications permettent de décentraliser la logique métier et de la réutiliser dans différentes parties du système, en facilitant la maintenance et l'évolution du code.
Ces blocs de construction forment la base du Domain Driven Design et permettent aux développeurs de modéliser le domaine métier de manière flexible et expressive. En utilisant ces blocs de manière appropriée, les développeurs peuvent créer un code plus cohérent, maintenable et évolutif, qui reflète fidèlement la logique métier et facilite la communication avec les experts métier. Dans les sections suivantes, nous explorerons les différentes couches d'architecture utilisées dans le DDD, ainsi que les stratégies de collaboration entre contextes limités pour gérer les interactions entre les différents sous-domaines du système.
II. Architecture en couches
A. Les quatre couches principales
Dans le Domain Driven Design, l'architecture est généralement organisée en quatre couches principales, qui correspondent aux différentes responsabilités du système. Cette organisation en couches favorise la séparation des préoccupations, la modularité et la maintenabilité du code. Voici les quatre couches principales utilisées dans le DDD :
Couche de présentation (Presentation Layer)
La couche de présentation est responsable de l'interaction avec l'utilisateur et de la présentation des données. Elle comprend les interfaces utilisateur (UI), les contrôleurs, les vues et les modèles de vues (ViewModels). Cette couche est conçue pour être indépendante de la logique métier et de la persistance des données, en se concentrant uniquement sur la manière dont les données sont affichées et les actions de l'utilisateur sont traitées.
Couche d'application (Application Layer)
La couche d'application sert de pont entre la couche de présentation et la couche de domaine. Elle coordonne les interactions entre les composants de la couche de présentation et les éléments du domaine, en orchestrant les opérations métier et en assurant la gestion des transactions. La couche d'application encapsule la logique des processus métier de haut niveau, mais ne contient pas de règles métier spécifiques, qui sont gérées par la couche de domaine.
Couche de domaine (Domain Layer)
La couche de domaine est au cœur du DDD et contient les modèles, les entités, les agrégats, les répertoires, les services et les autres éléments définis par les blocs de construction du DDD. Cette couche est responsable de l'implémentation des règles métier et de la garantie de la cohérence et de l'intégrité des données. La couche de domaine est indépendante des autres couches et ne doit pas dépendre directement de la couche de présentation, de l'infrastructure ou des détails de persistance.
Couche d'infrastructure (Infrastructure Layer)
La couche d'infrastructure fournit les services techniques et les utilitaires nécessaires pour soutenir les autres couches, tels que la persistance des données, la communication réseau, la gestion des fichiers, la journalisation, etc. Cette couche est conçue pour être flexible et extensible, en permettant aux développeurs de remplacer ou d'ajouter des services d'infrastructure sans affecter la logique métier ou l'architecture du système.
En utilisant cette architecture en couches, les développeurs peuvent créer des systèmes modulaires et évolutifs qui séparent clairement les différentes responsabilités et préoccupations. Cela facilite la maintenance, l'extension et la réutilisation du code, tout en garantissant que la logique métier est correctement encapsulée et protégée des détails techniques et des changements d'implémentation.
B. Collaboration entre contextes limités
Dans un système complexe, il est souvent nécessaire de gérer les interactions entre les différents contextes limités. Le DDD propose plusieurs stratégies de collaboration entre contextes limités pour assurer une communication efficace et cohérente entre les sous-domaines, tout en préservant leur autonomie et leur indépendance. Voici quelques-unes des principales stratégies de collaboration entre contextes limités :
Intégration par événements (Event-Driven Integration)
L'intégration par événements consiste à utiliser des événements de domaine pour propager les changements d'état entre les contextes limités. Cette approche permet de découpler les sous-domaines, en réduisant les dépendances directes et en favorisant une architecture plus modulaire et adaptable. L'intégration par événements est particulièrement utile pour les systèmes distribués, les microservices ou les applications basées sur des architectures réactives.
Services partagés (Shared Services)
Les services partagés sont des composants qui fournissent des fonctionnalités communes ou des services de support aux différents contextes limités. Ils permettent de centraliser et de réutiliser la logique métier ou les services d'infrastructure, en évitant la duplication du code et en facilitant la maintenance. Les services partagés doivent être conçus pour être indépendants des contextes limités spécifiques, en fournissant des interfaces génériques et en respectant les principes de la séparation des préoccupations.
Anti-Corruption Layer (ACL)
L'Anti-Corruption Layer est une couche d'adaptation qui sert de barrière entre les contextes limités pour prévenir les dépendances directes et protéger les modèles internes de chaque contexte limité. L'ACL traduit les messages, les requêtes et les commandes entre les contextes limités, en assurant que les conventions, les règles et les modèles de chaque contexte sont respectés. Cette approche permet de préserver l'autonomie et la cohérence des modèles de chaque contexte limité, tout en facilitant la communication et la collaboration entre les sous-domaines.
Conformiste (Conformist)
Le conformiste est une stratégie de collaboration qui consiste à adapter un contexte limité pour qu'il se conforme aux modèles, aux conventions et aux règles d'un autre contexte limité. Cette approche est utile lorsque l'interopérabilité et la cohérence entre les contextes limités sont plus importantes que l'autonomie et l'indépendance des modèles. Le conformiste peut simplifier la communication et réduire les coûts d'intégration, mais il peut égalemet entraîner des compromis en termes de flexibilité et de maintenabilité.
C. Considérations pour choisir une stratégie de collaboration
Lorsqu'il s'agit de choisir une stratégie de collaboration entre contextes limités dans un système basé sur le Domain Driven Design, plusieurs facteurs doivent être pris en compte pour assurer une communication efficace et cohérente, tout en préservant l'autonomie et l'indépendance de chaque sous-domaine. Voici quelques considérations importantes pour choisir la stratégie de collaboration la plus adaptée à votre projet :
Complexité du domaine
La complexité du domaine métier joue un rôle crucial dans le choix de la stratégie de collaboration. Les systèmes avec des domaines plus complexes et interconnectés pourraient bénéficier davantage de l'intégration par événements ou de l'utilisation d'une couche anti-corruption, tandis que les systèmes avec des domaines moins complexes pourraient opter pour des services partagés ou une stratégie de conformiste.
Couplage et cohésion
Il est essentiel d'évaluer le niveau de couplage et de cohésion entre les contextes limités pour choisir la bonne stratégie de collaboration. Les contextes fortement couplés ou ayant une forte cohésion pourraient bénéficier de l'utilisation de services partagés ou d'une stratégie de conformiste, tandis que les contextes faiblement couplés ou ayant une faible cohésion pourraient être mieux gérés avec l'intégration par événements ou l'utilisation d'une couche anti-corruption.
Évolutivité et performance
Les exigences en matière d'évolutivité et de performance doivent également être prises en compte lors de la sélection d'une stratégie de collaboration. Les systèmes ayant des contraintes de performance élevées ou nécessitant une évolutivité importante pourraient être mieux adaptés à l'intégration par événements ou à l'utilisation d'une couche anti-corruption pour réduire les dépendances et faciliter la répartition des charges.
Flexibilité et maintenabilité
La flexibilité et la maintenabilité du système sont des facteurs importants à considérer lors du choix d'une stratégie de collaboration. Les systèmes qui nécessitent une grande flexibilité pour s'adapter aux changements de l'environnement métier pourraient bénéficier de l'utilisation de l'intégration par événements ou d'une couche anti-corruption, tandis que les systèmes ayant des exigences de maintenabilité plus élevées pourraient opter pour des services partagés ou une stratégie de conformiste.
En choisissant la stratégie de collaboration appropriée pour chaque situation, les développeurs peuvent créer des systèmes flexibles et évolutifs qui gèrent efficacement les interactions entre les contextes limités, tout en préservant la cohérence, l'autonomie et l'indépendance des modèles de chaque sous-domaine. Ces stratégies de collaboration sont un aspect essentiel de l'architecture en couches du Domain Driven Design et contribuent à la réussite et à la longévité des projets.
III. Bonnes pratiques et pièges à éviter
A. Les bonnes pratiques
Focalisation sur la modélisation du domaine
Il est crucial de se concentrer sur la modélisation du domaine métier afin de créer un modèle de domaine adéquat. Prenez le temps de bien comprendre les exigences métier, les règles et les processus pour construire un modèle précis et efficace. Cette compréhension approfondie du domaine permettra de créer des logiciels mieux adaptés aux besoins des utilisateurs.
Collaboration avec les experts métier
Travaillez en étroite collaboration avec les experts métier pour garantir une compréhension commune des exigences et des objectifs du système. La collaboration entre les développeurs et les experts métier est essentielle pour aligner le code sur les besoins réels de l'entreprise et pour faciliter la communication entre les équipes.
Refactorisation continue
Le domaine métier évolue constamment, et il est essentiel de maintenir le modèle de domaine à jour en conséquence. La refactorisation continue du code permet d'assurer la cohérence et la qualité du modèle de domaine, tout en facilitant l'adaptation aux changements et aux nouvelles exigences.
B. Pièges courants et comment les éviter
Surutilisation des services
Un piège courant dans le DDD est de surutiliser les services, ce qui peut entraîner un couplage excessif et une complexité inutile. Pour éviter cela, assurez-vous de bien comprendre les responsabilités de chaque service et n'utilisez les services que lorsque cela est nécessaire pour gérer les dépendances et les interactions entre les objets de domaine. Favorisez les objets de domaine riches en comportements plutôt que les services anémiques qui se contentent de manipuler les données.
Confusion entre les couches d'application et du domaine
Il est important de maintenir une séparation claire entre les couches d'application et du domaine pour éviter les problèmes de couplage et de responsabilités. La couche d'application doit gérer la logique de flux de travail et la coordination, tandis que la couche du domaine doit se concentrer sur la modélisation de la logique métier. Ne mélangez pas ces responsabilités et veillez à maintenir une architecture en couches cohérente.
Modélisation trop complexe
Un autre piège courant est de créer un modèle de domaine trop complexe, ce qui peut rendre le code difficile à comprendre et à maintenir. Pour éviter cela, concentrez-vous sur la modélisation des aspects essentiels du domaine et utilisez des abstractions et des patterns appropriés pour gérer la complexité. N'hésitez pas à simplifier le modèle et à refactoriser les parties du code qui deviennent trop complexes ou difficiles à gérer.
Négligence des contextes limités
Ne pas prendre en compte les contextes limités peut conduire à des problèmes d'intégration et de collaboration entre les différentes parties du système. Identifiez clairement les contextes limités et leurs responsabilités, et utilisez des stratégies de collaboration appropriées pour gérer les interactions entre eux. Veillez à ce que chaque contexte limité puisse évoluer indépendamment des autres, tout en préservant l'intégrité du système dans son ensemble.
Ignorer les exigences non fonctionnelles
Le DDD est axé sur la modélisation du domaine métier, mais il ne faut pas négliger les exigences non fonctionnelles, telles que la performance, la sécurité et l'évolutivité. Tenez compte de ces aspects dès le début du projet et intégrez-les dans la conception du système. Assurez-vous également de surveiller et d'évaluer régulièrement ces exigences non fonctionnelles tout au long du cycle de vie du développement.
Annexes
Livres
- "Domain-Driven Design: Tackling Complexity in the Heart of Software" par Eric Evans - C'est le livre fondateur du DDD, qui introduit les concepts clés et les principes de base de cette approche.
- "Implementing Domain-Driven Design" par Vaughn Vernon - Ce livre offre une approche pratique pour appliquer les principes du DDD dans vos projets, avec des exemples concrets et des conseils pour la mise en œuvre.
- "Domain-Driven Design Distilled" par Vaughn Vernon - Il s'agit d'une version condensée du livre précédent, qui présente les concepts clés du DDD de manière plus concise et accessible.
Conférences
- DDD Europe : Cette conférence annuelle rassemble des experts du DDD et offre des ateliers, des présentations et des formations pour approfondir vos connaissances.
Articles et blogs
- Martin Fowler's website (https://martinfowler.com/tags/domain%20driven%20design.html) - Martin Fowler, un expert en développement logiciel, propose plusieurs articles et ressources sur le DDD.
- InfoQ (https://www.infoq.com/domain-driven-design) - InfoQ offre de nombreux articles, présentations et interviews sur le DDD.
Forums et groupes de discussion
- Domain Driven Design Google Group (https://groups.google.com/g/dddcqrs) - Ce groupe de discussion est un lieu d'échange entre praticiens et experts du DDD.
- DDD/CQRS Slack Group (https://ddd-cqrs-es.slack.com) - Ce groupe Slack réunit des développeurs et des experts du DDD pour discuter et partager des connaissances.
Posted on April 10, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.