Pourquoi le Domain-Driven Design ?
Le défi de la complexité métier, le modèle de domaine comme langage partagé, et l'art du « knowledge crunching ».
La plupart des logiciels d'entreprise ne meurent pas d'un défaut technique. Ils meurent d'incompréhension. Le code finit par dire une chose pendant que le métier en pense une autre, et chaque évolution creuse un peu plus l'écart. Eric Evans, dans son livre fondateur Domain-Driven Design (2003), part d'un constat dérangeant : le vrai défi d'une application complexe n'est presque jamais la technologie. C'est la complexité du domaine métier lui-même — ces règles tacites, ces exceptions, ces processus que les experts manipulent sans même savoir les formuler.
Le Domain-Driven Design (DDD), littéralement « conception pilotée par le domaine », est une réponse à ce problème. Ce n'est ni un framework, ni une architecture imposée : c'est une manière de penser la conception, où le cœur de l'effort porte sur un modèle du métier que l'équipe technique et les experts construisent ensemble, raffinent en continu, et relient directement au code. Ce premier chapitre pose les fondations : qu'est-ce qu'un modèle de domaine, comment le « digérer » avec les experts (le knowledge crunching), et quand cet investissement en vaut la peine. Les exemples du livre sont en Java ou conceptuels ; nous les traduirons en TypeScript idiomatique, dans un univers de logistique maritime et d'e-commerce.
Le vrai défi n'est pas technique
On imagine souvent qu'un projet est difficile à cause de sa pile technique : la base de données, la montée en charge, le déploiement. Ces sujets sont réels, mais ils sont solubles : ils ont des solutions connues, documentées, réutilisables d'un projet à l'autre.
La complexité du domaine, elle, est irréductible et spécifique. Personne d'autre ne connaît votre métier à votre place. Evans raconte avoir conçu un logiciel de circuits imprimés sans rien connaître à l'électronique : les experts lui « faisaient tourner la tête en trois minutes ». Le défi n'était pas d'écrire du code performant, mais de comprendre suffisamment le domaine pour que le code reflète sa logique réelle.
Quand cette compréhension manque, un symptôme typique apparaît : une règle métier essentielle se retrouve enfouie au milieu d'une fonction applicative, méconnaissable. Reprenons l'exemple du transport maritime cher à Evans. Une compagnie accepte sciemment plus de fret qu'un navire ne peut en porter — c'est la surréservation (overbooking), pratique standard du secteur.
// ❌ Avant : la règle de surréservation noyée dans une fonction.
function reserverFret(fret: Fret, voyage: Voyage): Confirmation {
const capaciteMax = voyage.capacite() * 1.1;
const charge = voyage.fretReserve() + fret.volume();
if (charge > capaciteMax) {
throw new ReservationRefusee();
}
const confirmation = sequenceConfirmation.suivante();
voyage.ajouterFret(fret, confirmation);
return confirmation;
} Le problème n'est pas que ce code soit faux : il marche. Le problème est qu'il cache une connaissance précieuse. Aucun expert métier ne pourra lire ce * 1.1 et confirmer la règle. Aucun développeur ne pourra relier la ligne « Autoriser 10 % de surréservation » du cahier des charges à ce calcul. La connaissance est là, mais elle est muette.
Le modèle de domaine
La réponse de DDD passe par un modèle de domaine (Domain Model). Le terme est trompeur : un modèle n'est pas un diagramme qu'on dessine puis qu'on jette, ni une copie exhaustive de la réalité. C'est une abstraction rigoureuse, choisie et partagée du métier.
Trois mots sont à peser :
- Choisie : un modèle n'est pas la réalité, c'est une simplification orientée vers un problème. Pour la simulation de signal d'Evans, on ignorait délibérément le comportement interne des puces — « bien trop compliqué » — au profit d'une simple liste de propagations. Un bon modèle exclut des centaines de faits vrais mais non pertinents.
- Rigoureuse : assez précise pour rendre le code simple à implémenter et à comprendre. Pas une métaphore vague, mais un système de concepts qui tient la route.
- Partagée : c'est le point crucial. Le modèle est la colonne vertébrale du langage de l'équipe. Développeurs et experts l'utilisent pour parler, et il est lié au code.
À retenir
Un modèle de domaine n'est pas une documentation produite à côté du code. C'est la même chose, vue sous deux angles. Si le modèle dit « politique de surréservation » mais que le code dit * 1.1, vous n'avez pas un modèle : vous avez un dessin et un programme qui divergeront dès le premier sprint.
Rendons donc le modèle explicite. La règle de surréservation n'est pas un calcul obscur : c'est une politique (policy, un cas du patron Strategy). En lui donnant un nom et un objet, on extrait la connaissance hors de la fonction applicative.
// ✅ Après : la connaissance métier devient un concept nommé.
class PolitiqueSurreservation {
private readonly tauxMax = 1.1;
estAutorisee(fret: Fret, voyage: Voyage): boolean {
const charge = fret.volume() + voyage.fretReserve();
return charge <= voyage.capacite() * this.tauxMax;
}
}
function reserverFret(
fret: Fret,
voyage: Voyage,
politique: PolitiqueSurreservation,
): Confirmation {
if (!politique.estAutorisee(fret, voyage)) {
throw new ReservationRefusee();
}
const confirmation = sequenceConfirmation.suivante();
voyage.ajouterFret(fret, confirmation);
return confirmation;
} Le gain n'est pas cosmétique. Désormais, tout le monde voit que la surréservation est une règle métier distincte et importante, pas une bizarrerie arithmétique. Le code est devenu un artefact que l'expert peut relire (avec un peu d'aide) pour valider la règle — la boucle de feedback se referme.
Le « knowledge crunching » : digérer la connaissance
Comment passe-t-on du * 1.1 à la PolitiqueSurreservation ? Pas par génie solitaire d'un développeur, ni par un cahier des charges transmis du haut vers le bas. On y arrive par ce qu'Evans appelle le knowledge crunching — qu'on peut traduire par « digestion » ou « brassage » de la connaissance.
L'image est celle de l'analyste financier qui brasse des montagnes de chiffres pour en extraire la poignée qui éclaire une décision. De même, le modélisateur efficace tamise un torrent d'informations pour en tirer le mince filet pertinent, essaie une idée organisatrice après l'autre, et accepte d'en rejeter beaucoup. Le succès, écrit Evans, vient d'un ensemble émergent de concepts abstraits qui donnent du sens à la masse des détails.
C'est une activité fondamentalement collaborative et itérative. Une équipe de développeurs et d'experts métier brasse ensemble la matière brute — entretiens, documents, systèmes existants, beaucoup de discussions — jusqu'à ce qu'un modèle utile émerge. Evans en illustre la mécanique par des dialogues : l'expert corrige le vocabulaire (« on ne dit pas composant mais instance de composant »), le développeur reformule en schéma, on découvre une contrainte (« un signal arrive sur une broche, pas n'importe où »), et le modèle se transforme.
Astuce
Si, à la fin d'une session de modélisation, vous avez appris quelque chose sur le métier que vous ignoriez le matin — et si l'expert a clarifié un point qu'il tenait pour acquis —, vous faites du knowledge crunching. Si vous avez seulement traduit une spec en tickets, vous ne faites que transcrire.
Pourquoi cela fonctionne
Evans isole cinq ingrédients du succès. Ils méritent d'être gravés :
| Ingrédient | Ce qu'il signifie concrètement |
|---|---|
| Lier modèle et implémentation au plus tôt | Un prototype brut, sans persistance ni interface, juste pour valider le modèle en code. |
| Cultiver un langage fondé sur le modèle | Parler en termes issus du modèle teste sa viabilité « à l'oreille », immédiatement. |
| Un modèle riche en connaissance | Les objets ont du comportement et appliquent des règles ; ce n'est pas un schéma de données. |
| Un modèle distillé | On ajoute les concepts utiles, mais surtout on retire ceux qui ne s'avèrent pas centraux. |
| Le knowledge crunching lui-même | Le langage, les croquis et l'esprit d'expérimentation transforment les réunions en laboratoires du modèle. |
Les pièges à éviter
Evans oppose le knowledge crunching à deux anti-modèles fréquents.
Le premier est le cycle en cascade. Les experts parlent aux analystes, qui digèrent et abstraient, puis transmettent aux programmeurs qui codent. Ça échoue par absence totale de feedback : la connaissance ruisselle dans un seul sens et ne s'accumule pas. Les analystes n'apprennent rien des programmeurs ni des premières versions.
Le second est l'itération sans abstraction. On demande une fonctionnalité, on la construit, on la montre, on demande la suivante. Avec du refactoring, le code reste propre — mais si les développeurs ne s'intéressent pas au domaine, ils apprennent ce que l'application doit faire, jamais les principes qui le sous-tendent. On obtient un logiciel correct, mais sans cet effet de levier où de puissantes fonctionnalités nouvelles découlent naturellement des anciennes.
// ❌ Itération sans abstraction : un calcul ad hoc par fonctionnalité.
function delaiSignalAcceptable(chemin: Broche[]): boolean {
return chemin.length <= 3; // d'où vient ce 3 ? mystère.
}
// ✅ Le concept métier émerge : un « saut » par traversée de réseau.
class CheminSignal {
constructor(private readonly sauts: number) {}
// Règle métier explicite, nommée par l'expert.
risqueDeRetardHorloge(): boolean {
return this.sauts > this.MAX_SAUTS;
}
private readonly MAX_SAUTS = 3;
} Apprentissage continu et modèles profonds
La connaissance d'un projet est, au départ, fragmentée : éparpillée dans des têtes et des documents, mêlée à du bruit, au point qu'on ne sait même pas ce qu'on a besoin de savoir. Pire, tout projet fuit la connaissance : les gens partent, les équipes se réorganisent, et comme le code n'exprime pas le savoir durement acquis, la tradition orale s'interrompt et tout est perdu.
D'où l'importance de l'apprentissage continu : faire grandir consciemment la connaissance de l'équipe, et la stocker dans le code et le modèle plutôt que dans les seules conversations. Un noyau d'équipe stable, expert du domaine, devient le cœur de l'organisation.
Cet apprentissage débouche parfois sur un modèle profond (deep model). Les modèles utiles ne sont presque jamais à la surface. Sur son système de conteneurs maritimes, Evans avait d'abord modélisé le fret, son itinéraire, ses déplacements — tout cela correct et utile. Mais les experts restaient insatisfaits : il manquait leur façon de voir le métier.
La révélation est venue tard. Le déplacement physique des conteneurs était largement sous-traité ; ce qui comptait vraiment pour les clients, c'était une série de transferts de responsabilité entre parties (l'expéditeur, les transporteurs, le destinataire), jalonnée de documents légaux comme le connaissement. Le modèle a changé en profondeur : non plus « déplacer des conteneurs de lieu en lieu », mais « transférer la responsabilité du fret d'une entité à l'autre ».
// Modèle de surface : le fret se déplace géographiquement.
class Fret {
deplacerVers(lieu: Lieu): void { /* ... */ }
}
// Modèle profond : ce qui compte, c'est le transfert de responsabilité.
class TransfertDeResponsabilite {
constructor(
readonly fret: Fret,
readonly de: Partie,
readonly vers: Partie,
readonly type: TypeTransfert, // chargement, douane, livraison...
) {}
} Note
Le knowledge crunching est une exploration : on ne sait pas où l'on aboutira. Le modèle profond du transport maritime n'aurait pas pu être deviné au premier jour. Il a fallu construire le modèle de surface, vivre avec, écouter l'insatisfaction des experts — et accepter de tout réorganiser quand le vrai centre de gravité est apparu.
Quand faire du DDD (et quand s'abstenir)
Tout ce travail a un coût. Brasser la connaissance, distiller un modèle, le maintenir en phase avec le code : c'est un investissement réel, qui n'est pas toujours justifié.
La règle est simple. DDD se justifie quand le cœur métier est à la fois complexe et stratégique — quand c'est précisément ce qui distingue votre organisation de ses concurrents. Vaughn Vernon, dans DDD Distilled, le formule ainsi : votre organisation ne peut pas exceller en tout, alors elle doit choisir où exceller, et y investir une conception réfléchie.
À l'inverse, appliquer tout l'arsenal DDD à un CRUD trivial, à un sous-domaine périphérique ou à un outil interne sans enjeu relève de la sur-ingénierie. Evans le dit explicitement à propos de la surréservation : « je ne recommande pas d'appliquer une conception aussi élaborée à chaque détail du domaine ». L'art consiste à concentrer l'effort sur le cœur et à minimiser le reste.
| Situation | DDD complet ? |
|---|---|
| Cœur métier complexe et stratégique | Oui — c'est là que l'investissement paie. |
| Règles riches, exceptions, processus tacites | Oui — le modèle capture ce savoir. |
| CRUD simple, peu de règles | Non — sur-ingénierie probable. |
| Sous-domaine générique (envoi d'e-mails, auth) | Plutôt acheter ou réutiliser. |
Attention
Le danger de DDD n'est pas l'échec technique, c'est l'application uniforme. Couvrir un domaine pauvre de fabriques, d'agrégats et de référentiels produit de la complexité accidentelle sans aucune contrepartie métier. Réservez la puissance lourde au cœur stratégique.
Les deux volets : stratégique et tactique
Le reste de cette série suit la structure que Vernon a popularisée, en deux grands volets complémentaires.
Le design stratégique donne les grands coups de pinceau, avant tout détail d'implémentation. Il répond aux questions « où est le cœur ? comment découper ? comment intégrer ? ». Ses outils :
- le langage ubiquitaire (Ubiquitous Language) : un vocabulaire unique, partagé par l'équipe et reflété dans le code ;
- les contextes délimités (Bounded Contexts) : les frontières à l'intérieur desquelles un modèle et son langage sont cohérents ;
- les sous-domaines (Subdomains) : la distinction entre cœur, sous-domaines de support et sous-domaines génériques ;
- la cartographie de contextes (Context Mapping) : les relations, humaines et techniques, entre contextes qui doivent s'intégrer.
Le design tactique vient ensuite, pinceau fin, pour modéler les détails à l'intérieur d'un contexte. Ses briques :
- les entités (Entities), définies par leur identité ;
- les objets-valeurs (Value Objects), définis par leurs attributs ;
- les agrégats (Aggregates), grappes d'objets traitées comme une unité de cohérence ;
- les fabriques (Factories) et référentiels (Repositories), pour créer et retrouver ces objets.
Astuce
L'ordre compte. Vernon insiste : on commence par le stratégique. Tracer de beaux objets-valeurs n'a aucun intérêt s'ils vivent dans un contexte mal délimité, avec un langage flou. Les frontières d'abord, les détails ensuite.
Un dernier point d'honnêteté historique. Plusieurs idées aujourd'hui associées à DDD sont postérieures au livre d'Evans (2003). Les événements de domaine (Domain Events) comme brique tactique de premier plan, le CQRS, l'Event Sourcing et l'Event Storming se sont diffusés plus tard, portés notamment par Vernon et la communauté. Nous les signalerons comme des prolongements modernes, sans les attribuer au texte original.
À retenir
- Le défi central d'un logiciel d'entreprise est la complexité du domaine, pas la technique : cette complexité est spécifique, irréductible et ne se résout qu'en comprenant le métier.
- Le modèle de domaine est une abstraction choisie, rigoureuse et partagée — pas un diagramme jetable ni la réalité exhaustive — et il doit rester lié au code, sous peine de divergence.
- Le knowledge crunching distille la connaissance par collaboration étroite et itérative avec les experts ; fuyez la cascade (pas de feedback) et l'itération sans abstraction (pas de principes).
- Rendez la connaissance explicite : une règle métier enfouie dans un
if(le* 1.1) doit devenir un concept nommé que l'expert peut relire. - Les modèles profonds émergent tard, par exploration ; acceptez de réorganiser quand le vrai centre de gravité du métier apparaît.
- N'appliquez DDD que là où le cœur est complexe et stratégique ; ailleurs, c'est de la sur-ingénierie. Commencez par le stratégique, puis le tactique.