Aller au contenu principal
Architecture

Domain-Driven Design (DDD)

8 min de lecture
  • architecture
  • design
  • méthodologie
DDD : quand le métier guide l'architecture

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.

SituationDDD ?
Application CRUD simpleNon — over-engineering garanti
Logique métier complexe avec beaucoup de règlesOui — c'est son terrain
Prototype ou MVPNon — trop de cérémonie
Domaine que l'équipe maîtrise malOui — force la compréhension
Microservices avec des domaines distinctsOui — les Bounded Contexts guident le découpage
API REST basique qui expose une base de donnéesNon — 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.