Domain-Driven Design (DDD)
- architecture
- design
- méthodologie
Le Domain-Driven Design est une approche de conception logicielle qui place le métier au centre de toutes les décisions techniques. Introduit par Eric Evans en 2003 dans son livre Domain-Driven Design: Tackling Complexity in the Heart of Software, le DDD part d'un constat simple : dans les projets complexes, ce n'est pas la technologie qui pose le plus de problèmes — c'est la compréhension du domaine métier.
Le problème que résout le DDD
Dans beaucoup de projets, le code finit par ressembler à un patchwork de règles métier dispersées entre les contrôleurs, les services, les requêtes SQL et les middlewares. Personne ne sait vraiment où se trouve la logique de calcul d'un prix, de validation d'une commande ou de gestion d'un remboursement. Le vocabulaire utilisé par les développeurs ne correspond pas à celui des experts métier. Et quand un nouveau développeur arrive, il passe des semaines à comprendre comment les choses fonctionnent — pas techniquement, mais fonctionnellement.
Le DDD propose une réponse structurée à ce chaos : aligner le code sur le métier, pas l'inverse.
L'Ubiquitous Language : parler la même langue
Le premier pilier du DDD est le langage omniprésent (Ubiquitous Language). L'idée est que développeurs, product owners et experts métier utilisent exactement les mêmes termes — dans les conversations, dans le code, dans la documentation.
Si le métier parle de "Commande", le code contient une classe Commande — pas Order, pas OrderDTO, pas CommandeData. Si le métier distingue "Expédition" et "Livraison", le code fait la même distinction. Quand le vocabulaire diverge entre le code et le métier, les bugs conceptuels s'accumulent.
Les concepts tactiques
Entités et Value Objects
Une Entité est un objet défini par son identité, pas par ses attributs. Deux clients avec le même nom sont deux clients différents — c'est leur identifiant qui les distingue.
Un Value Object est un objet défini par ses attributs, sans identité propre. Une adresse, un montant, une période de dates. Deux montants de 49,99€ sont interchangeables.
// Value Object — défini par sa valeur
class Money {
constructor(readonly amount: number, readonly currency: string) {}
equals(other: Money): boolean {
return this.amount === other.amount && this.currency === other.currency;
}
add(other: Money): Money {
if (this.currency !== other.currency) throw new Error("Devises différentes");
return new Money(this.amount + other.amount, this.currency);
}
}
// Entité — définie par son identité
class Order {
constructor(
readonly id: string,
private items: OrderItem[],
private status: OrderStatus
) {}
}Aggregates
Un Agrégat est un groupe d'objets (entités + value objects) traités comme une unité cohérente. L'agrégat a une racine — l'entité principale par laquelle passent toutes les modifications. Aucun objet extérieur ne peut modifier directement un objet interne de l'agrégat.
Une Commande est un agrégat. Ses LignesDeCommande en font partie. On ne modifie jamais une ligne de commande directement — on passe toujours par la commande.
Domain Events
Les événements de domaine capturent quelque chose qui s'est passé dans le métier : CommandeValidée, PaiementReçu, StockInsuffisant. Ils permettent de découpler les conséquences d'une action de l'action elle-même.
Repositories
Le Repository est l'interface qui permet de récupérer et persister les agrégats. Il masque complètement la couche de persistance — le domaine ne sait pas s'il parle à une base SQL, un fichier ou une API.
Le DDD stratégique : les Bounded Contexts
Le DDD stratégique est souvent plus important que le tactique. Un Bounded Context est une frontière explicite dans laquelle un modèle de domaine est cohérent et un vocabulaire a un sens précis.
Le mot "Produit" n'a pas le même sens pour le catalogue (nom, description, images), pour le stock (quantité, emplacement, seuil de réapprovisionnement) et pour la facturation (prix, TVA, remise). Forcer un seul modèle Produit partagé entre ces trois contextes crée un objet monstre ingérable.
La solution : trois modèles Produit distincts, chacun dans son Bounded Context, avec des traductions explicites aux frontières.
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Catalogue │ │ Stock │ │ Facturation │
│ │ │ │ │ │
│ Produit: │ │ Produit: │ │ Produit: │
│ - nom │◄──►│ - quantité │◄──►│ - prixHT │
│ - description │ │ - emplacement │ │ - tauxTVA │
│ - images │ │ - seuilAlerte │ │ - remise │
└─────────────────┘ └──────────────────┘ └─────────────────┘
Quand utiliser le DDD — et quand s'abstenir
Le DDD n'est pas fait pour tous les projets. C'est sa force et sa limite.
| Situation | DDD ? |
|---|---|
| Application CRUD simple | Non — over-engineering garanti |
| Logique métier complexe avec beaucoup de règles | Oui — c'est son terrain |
| Prototype ou MVP | Non — trop de cérémonie |
| Domaine que l'équipe maîtrise mal | Oui — force la compréhension |
| Microservices avec des domaines distincts | Oui — les Bounded Contexts guident le découpage |
| API REST basique qui expose une base de données | Non — un service simple suffit |
La règle empirique d'Eric Evans : si la complexité métier dépasse la complexité technique, le DDD apporte de la valeur. Si votre principal défi est technique (performance, scale, infrastructure), le DDD n'est pas la réponse.
Les erreurs courantes
Appliquer le DDD partout. Le DDD a un coût en termes de complexité structurelle. L'appliquer à un module d'administration avec cinq écrans CRUD, c'est écraser une mouche avec un marteau.
Confondre DDD et architecture en couches. Le DDD n'impose pas une architecture spécifique. Il se combine bien avec l'architecture hexagonale ou la Clean Architecture, mais ce n'est pas un synonyme.
Ignorer le DDD stratégique. Beaucoup d'équipes se jettent sur les Entities, Value Objects et Repositories sans avoir défini leurs Bounded Contexts. C'est comme construire des murs sans avoir dessiné le plan de la maison.
Négliger l'Ubiquitous Language. Si votre code parle anglais mais votre métier parle français, vous avez déjà un problème de traduction permanent qui génère des malentendus.
Le DDD n'est pas une architecture, c'est une philosophie : le code doit refléter le métier, pas l'inverse. Quand la complexité de votre domaine justifie l'investissement, le DDD transforme un code spaghetti en un modèle lisible par tous — développeurs, product owners et experts métier. Mais gardez-le pour les projets qui le méritent.