Le DDD, ça commence avant le code
On croit souvent que le DDD, ce sont des entités, des value objects, des agrégats. C'est la partie visible. La partie qui décide de tout, elle, se joue bien avant.
Imagine que tu débarques dans une entreprise de fret maritime. On te confie le logiciel qui suit les cargaisons : quel conteneur part de Hong Kong, sur quel navire, vers quel port, à quelle date. Ta première réaction de développeur, c'est de te demander quelles tables créer, quel framework brancher, comment structurer tes dossiers. C'est légitime — mais ce n'est pas là qu'est la difficulté.
La difficulté, elle est dans le métier lui-même : ce qu'est vraiment un itinéraire, ce que veut dire « réserver de la place sur un voyage », pourquoi une cargaison « en douane » n'est pas une cargaison « en transit ». Ces distinctions-là, aucun framework ne te les donne. Elles vivent dans la tête des experts, dans un vocabulaire que tu ne connais pas encore, et c'est de là que viennent les vrais bugs — pas d'une mauvaise indentation.
La complexité qui compte n'est pas technique (bases de données, réseau, plateforme) mais métier. Le Domain-Driven Design place cette complexité métier au centre, et fait tout le reste tourner autour d'elle.
Le DDD, on le découpe traditionnellement en deux moitiés. La moitié tactique, c'est l'outillage de code : entités, value objects, agrégats, dépôts. C'est ce que tu connais peut-être déjà, et c'est le sujet du cours DDD : les agrégats. La moitié stratégique, celle de ce cours-ci, se joue une couche au-dessus : de quoi parle-t-on, avec qui, et où trace-t-on les frontières ?
Or c'est un secret mal gardé de la communauté DDD : la moitié stratégique est de loin la plus importante. Eric Evans, qui a écrit le livre fondateur en 2003, le dit lui-même avec deux décennies de recul.
« Context mapping… is perhaps the one thing I would say should be done on every project. »
Traduit : parmi tous les outils du DDD, s'il ne devait en garder qu'un pour tous ses projets, ce serait la cartographie des contextes — un outil stratégique, pas une ligne de code. Les blocs de construction tactiques, eux, il les juge largement surestimés : tout le monde s'arrête au chapitre 5 de son livre, personne ne lit le chapitre 14.
Avant d'entrer dans le vif, posons la carte de ce voyage. On va d'abord comprendre ce qu'est vraiment un modèle (et ce qu'il n'est pas), puis comment le langage se forge avec le métier, comment explorer plusieurs modèles plutôt que se marier au premier, et enfin — le cœur du cours — comment découper un grand système en bounded contexts et cartographier leurs relations.
Un modèle est un système d'abstractions, pas une photo du réel
La tentation, quand on modélise, c'est de vouloir « coller à la réalité ». C'est exactement le piège. Un bon modèle n'est pas réaliste — il est utile.
Prends une carte du monde accrochée à un mur. Celle que tu as en tête est probablement une projection de Mercator : les méridiens y sont des droites parallèles, ce qui est très pratique pour tracer un cap à la boussole. Mais Mercator ment effrontément sur les surfaces — le Groenland y paraît aussi grand que l'Afrique, alors qu'il est quatorze fois plus petit. Est-ce que c'est un défaut de la carte ? Non. C'est un choix. Une carte qui respecterait les surfaces serait inutilisable pour naviguer, et une carte fidèle en tout serait une reproduction à l'échelle 1:1 — c'est-à-dire la Terre elle-même, qui ne tient sur aucun mur.
Modéliser, ce n'est pas photographier le réel. C'est choisir ce qu'on garde et ce qu'on jette, en fonction d'un problème précis à résoudre. Ce qui est hors du problème est délibérément absent.
Le logiciel fonctionne exactement pareil. Quand tu modélises une cargaison, tu ne représentes pas « tout ce qu'est une cargaison » — sa couleur, l'odeur du conteneur, le prénom du docker qui l'a chargée. Tu retiens ce qui sert ton problème : son itinéraire, son statut douanier, le voyage réservé. Vouloir tout capturer, c'est le perfectionnisme, et le perfectionnisme sabote le bon design.
« Realism doesn't give us models that we actually can use. »
De cette idée découle une conséquence qui surprend souvent : un modèle n'a aucune valeur en soi. Un diagramme élégant, une hiérarchie de classes parfaite, ça ne vaut rien tant qu'on ne l'a pas confronté à un usage. La valeur naît de l'adéquation entre le modèle et les problèmes qu'on lui pose.
« Having a model doesn't actually give you any advantage as such. »
Evans aime demander : « un marteau, est-ce utile ? ». La question n'a pas de réponse dans l'absolu. Un marteau est formidable pour planter un clou et pathétique pour scier une planche. Personne ne dirait « ce marteau est mal conçu » parce qu'il scie mal — on prendrait une scie. Un modèle, c'est un marteau : sa qualité se juge face à une tâche, jamais dans le vide.
Cette mise au point paraît philosophique, mais elle a des effets très concrets sur ton clavier. Elle t'autorise à jeter un modèle qui ne colle plus sans culpabiliser — il n'était pas « faux », il ne sert simplement plus. Elle t'évite les guerres de tranchées sur « la vraie nature » d'un concept. Et surtout, elle prépare la révélation centrale du cours : puisqu'un modèle est taillé pour un problème, un système qui a plusieurs problèmes distincts a besoin de plusieurs modèles — chacun dans sa frontière.
Le langage ubiquitaire : les mots comptent
Si ton code parle une langue et tes experts métier une autre, il y a un traducteur entre les deux — et ce traducteur, c'est toi. Chaque traduction est une occasion de se tromper.
Repartons du fret. Tu es en réunion avec une experte du routage, et elle t'explique un itinéraire : « le conteneur fait escale à Rotterdam, puis à New York, avant d'arriver à Dallas ». Tu hoches la tête, tu rentres coder, et dans ton modèle tu écris une classe Leg — un « tronçon » entre deux points. Ça marche. Mais remarque le décalage minuscule : elle a dit escale (« stops »), toi tu as écrit tronçon (« legs »). Deux mots pour un itinéraire qu'on regarde sous deux angles.
Ce genre de décalage a l'air anodin. Il est en réalité le symptôme le plus précieux du DDD. Quand un mot sert à expliquer le métier mais n'existe nulle part dans le code, c'est le signe qu'un morceau du modèle te manque.
Un langage partagé, rigoureux, construit ensemble par les experts métier et les développeurs, et utilisé partout : dans les conversations, dans les documents, et jusque dans le code — noms de classes, de méthodes, de variables. Le même mot désigne la même chose des deux côtés.
Le but ultime, c'est que le code « se lise comme l'expression de la solution » — qu'un expert métier, en te regardant nommer tes méthodes, reconnaisse sa propre langue. Quand itineraire.reacheminerVers(port) apparaît à l'écran, plus besoin de traduire : le mot dans la réunion et le mot dans le code sont le même mot. Le traducteur mental disparaît, et avec lui toute une classe de bugs silencieux.
Attention à un contresens fréquent sur le mot « ubiquitaire ». Ubiquitaire ne veut pas dire « le même langage dans tout le système ». Ça veut dire « le même langage dans toutes les activités autour d'un modèle donné » — parler, documenter, coder. La nuance est capitale, et c'est elle qui ouvre la porte des bounded contexts.
« Ubiquitous means everywhere… but it doesn't mean everywhere throughout the system. »
Autrement dit : le langage est total à l'intérieur d'un périmètre, mais ce périmètre a des bords. Le mot « cargaison » n'a pas forcément le même sens pour l'équipe qui gère le routage et pour celle qui gère la facturation. Vouloir un seul dictionnaire pour toute l'entreprise, c'est le rêve qui produit les systèmes les plus embrouillés. On verra pourquoi dès la section 04.
Pour l'instant, retiens la discipline : forger le vocabulaire avec le métier, le raffiner en continu, et le faire descendre jusque dans le code. C'est un travail de tous les jours, pas une phase de cadrage qu'on coche une fois. Le langage vit, il se corrige, il se précise — exactement comme le modèle qu'il exprime.
Explorer : le premier modèle n'est pas le dernier
Face à un problème, la première idée correcte a un défaut redoutable : elle est correcte. Du coup on s'y accroche, et on arrête de chercher mieux.
Quand tu achètes une voiture, tu ne prends pas la première du parking. Tu en compares plusieurs, tu en essaies même qui ne te conviennent pas, parce que c'est en voyant ce qui ne va pas que tu comprends ce que tu veux vraiment. Modéliser, c'est pareil — et pourtant, en code, on fait presque toujours l'inverse : on trouve un modèle qui marche, et on fonce.
« The first decent idea… is often the last idea, because we latch on to it and we stop thinking. »
Evans distingue deux modes de pensée qu'on a tendance à écraser l'un sur l'autre. Générer des idées, c'est un mode où la quantité prime, où les mauvaises idées sont les bienvenues parce qu'elles nourrissent les bonnes, où l'on suspend tout jugement. Sélectionner, c'est le mode critique inverse. Le drame, c'est de sélectionner pendant qu'on génère : dès la première idée décente, l'esprit critique s'allume et tue toutes les suivantes avant qu'elles naissent.
Pourquoi tant insister ? À cause d'un phénomène qu'on sous-estime : la dépendance au chemin. Le modèle vers lequel tu converges ne dépend pas seulement du problème — il dépend de l'ordre dans lequel tu as rencontré les cas. Commence par « réserver une cargaison » et tu penseras en escales ; commence par « quel navire fait ce trajet ? » et tu penseras en tronçons. Le premier scénario que tu codes oriente tout le reste, souvent pour des années.
Le modèle final n'est pas dicté par le seul problème : il est marqué par le trajet parcouru pour y arriver. D'où l'intérêt d'explorer largement avant que le premier choix ne se fige en dette structurelle.
Reprenons l'itinéraire de fret. Deux modèles rivaux, tous deux « corrects » :
Modèle « escales » (stops)
Modèle « tronçons » (legs)
Aucun des deux n'est « le bon ». Chacun rend certaines questions triviales et d'autres pénibles. Le simulateur ci-dessous te laisse choisir un modèle, puis lui poser des questions métier réelles. Observe : la même question est parfois une simple lecture, parfois une reconstruction laborieuse — selon le modèle. C'est ça, l'adéquation modèle/problème, rendue tangible.
Choisis d'abord un modèle, puis pose-lui chaque question métier. Le verdict te dit si la réponse est directe ou s'il faut reconstruire l'information. Il n'y a pas de modèle gagnant — seulement des modèles adaptés.
Ce que le simulateur met en scène, c'est la leçon d'Evans en une phrase : il n'y a pas de meilleur modèle dans l'absolu, seulement un modèle qui colle mieux à ce que tu fais le plus souvent. Et comme le premier scénario que tu traites oriente ton choix, mieux vaut avoir vu venir les autres.
Le bounded context : un contexte avec une frontière
Le mot « valeur » veut dire quelque chose de précis en comptabilité, autre chose en physique, autre chose encore quand on parle des valeurs d'une personne. Le contexte tranche. En logiciel aussi.
Reprends le fil de la section précédente. On a vu qu'un modèle est taillé pour un problème, et qu'un mot n'a de sens que rapporté à ce problème. Pousse la logique jusqu'au bout : dans une entreprise un peu grande, il y a plusieurs problèmes distincts, donc plusieurs modèles, donc plusieurs langages. Le mot « cargaison » chez les gens du routage n'est pas le « cargaison » de la facturation. Que faire de ces modèles qui se ressemblent sans être identiques ?
La réponse d'Evans est d'une simplicité désarmante : on trace une frontière autour de chaque modèle, et à l'intérieur de cette frontière — et seulement là — le langage est cohérent et sans ambiguïté. C'est ça, un bounded context.
Une frontière à l'intérieur de laquelle un modèle donné, exprimé dans un langage ubiquitaire cohérent, est valable et sans ambiguïté. À l'extérieur, ce modèle n'a plus cours. Michael Plöd le résume : « a boundary for a model expressed in a consistent ubiquitous language tailored around a specific purpose ».
Evans en donne la définition la plus dépouillée qui soit, et il insiste sur le fait qu'elle est littérale :
« A bounded context is just literally a context with a boundary. »
Pourquoi la frontière est-elle non négociable ? Parce que sans elle, les expressions du modèle perdent leur sens. Prends une règle métier posée dans le contexte du routage : « si x < y, alors la marge de transit est y - x ». Sortie de son contexte, cette formule ne veut plus rien dire — quel x, quel y, quelle marge ? Le sens était accroché au contexte qui l'a posée.
« There is no meaning to expressions outside of a given context. »
« Without the boundary, it doesn't work. It doesn't even make sense. »
Reste une question terre-à-terre : à quoi ressemble une frontière « pour de vrai » ? Un trait sur un diagramme ne suffit pas. Evans propose un critère concret et un peu brutal : la frontière, c'est tout ce qu'un développeur voit facilement. Un schéma de base de données distinct, un service séparé, une unité de déploiement à part — voilà des frontières tangibles. Deux « contextes » qui partagent la même base de données ne sont pas séparés, quoi qu'en dise l'architecture sur le papier.
Le bounded context a un cousin tactique que tu connais peut-être : l'agrégat. L'agrégat est une frontière de cohérence transactionnelle, minuscule, à l'échelle de quelques objets. Le bounded context est une frontière de modèle et de langage, à l'échelle d'un sous-système entier. Même idée fondatrice — protéger une cohérence en la délimitant — mais deux ordres de grandeur d'écart. Ce cours parle de la grande frontière ; l'autre cours parle de la petite.
Et voici le bénéfice qui change tout, qu'on développera en cartographie : le bounded context permet aux équipes de ne pas être d'accord. Chacune garde son modèle, sa vision, son vocabulaire ; on ne se met d'accord que sur l'interface entre les contextes. Fini les réunions interminables pour décider d'une définition unique de « client » qui satisferait tout le monde — c'est-à-dire personne.
Bounded context, sous-domaine, organisation : ne pas tout confondre
Trois découpages se superposent dans une entreprise : celui du problème, celui de la solution, celui des équipes. On croit qu'ils coïncident. Ils ne coïncident jamais tout à fait.
C'est la confusion la plus tenace du DDD, et elle mérite qu'on s'y arrête. « Bounded context » et « sous-domaine », on les emploie souvent comme synonymes. Ils ne le sont pas. La clé pour les démêler vient d'Eric Evans dans son livre, puis affinée par Vaughn Vernon : ce sont deux espaces différents.
Un sous-domaine vit dans l'espace du problème : c'est un morceau de l'activité de l'entreprise, quelque chose qui existe que tu écrives du logiciel ou non. Un bounded context vit dans l'espace de la solution : c'est une frontière que tu décides de tracer dans ton logiciel pour y protéger un modèle.
Dit autrement : le sous-domaine, tu le découvres (il est dans le métier) ; le bounded context, tu le conçois (il est dans ton design). Dans un monde idéal, un bounded context correspond à un sous-domaine, proprement, un pour un. Dans le monde réel, un vieux système peut couvrir trois sous-domaines à la fois, ou un sous-domaine peut être éclaté sur deux contextes. La correspondance est un objectif, pas une donnée.
Les sous-domaines se rangent classiquement en trois familles, et cette classification pilote tes décisions d'investissement.
| Type de sous-domaine | Ce que c'est | Décision typique |
|---|---|---|
| Core | Ce qui te différencie, ta raison d'exister, là où est ton avantage compétitif. Pour le transporteur, l'optimisation d'itinéraires. | Tes meilleurs développeurs, du DDD rigoureux, du code fait maison. |
| Supporting | Nécessaire mais pas différenciant. La gestion des dossiers clients. | Fait maison si besoin, mais sans sur-investir. Rigueur modérée. |
| Generic | Résolu de la même façon pour tout le monde. Authentification, paie, envoi d'e-mails. | Acheter ou intégrer une solution du marché. Ne pas réinventer. |
Vient enfin le troisième découpage, le plus glissant : celui de l'organisation. Evans raconte l'histoire d'une banque dont le logiciel était découpé en deux contextes propres, « cash » et « crédit ». Un jour, la direction réorganise : non plus par produit, mais par type de client — « entreprises » d'un côté, « particuliers » de l'autre. Les nouvelles équipes ne correspondent plus aux anciens contextes. Personne ne sait plus vraiment qui est responsable de quoi. L'intendance devient floue, et le code, faute de gardien clair, glisse doucement vers la big ball of mud.
Ces trois cercles s'influencent (on verra la loi de Conway en section 07), mais les confondre est une source d'erreurs sans fin. Garde la boussole : le sous-domaine se découvre, le bounded context se décide, l'équipe s'organise — et l'art stratégique consiste justement à les faire converger sans croire qu'ils sont donnés.
Découvrir et découper : un processus, pas une révélation
Personne ne se réveille un matin avec la carte parfaite de ses contextes en tête. On les fait émerger, à plusieurs, par petites touches — et le premier découpage sera de toute façon révisé.
Jusqu'ici on a parlé de ce qu'est une frontière. Reste la question pratique qui angoisse le plus : où la tracer ? Il n'existe pas de formule. Mais il existe une démarche, popularisée par la communauté DDD sous le nom de DDD Starter Modelling Process. Un mot d'avertissement de ses auteurs, à graver : c'est un guide, pas une procédure. Les étapes sont optionnelles, l'ordre est indicatif, tout est itératif et collaboratif.
La démarche s'organise en quatre grands mouvements, du plus flou au plus concret.
| Mouvement | Ce qu'on y fait |
|---|---|
| Aligner & comprendre | Se mettre d'accord sur le métier lui-même (à quoi sert l'entreprise, comment elle gagne sa vie). Outils : business model canvas, glossaire. |
| Découvrir | Faire remonter les événements, les acteurs, les zones de flou. C'est le terrain de l'EventStorming, du domain storytelling, de l'example mapping. |
| Décomposer | Faire émerger les sous-domaines en regroupant « ce qui change ensemble ». |
| Connecter | Cartographier les relations entre contextes (context mapping, flux de messages entre domaines) — le sujet des sections 07 à 10. |
L'outil vedette de la phase « découvrir », c'est l'EventStorming d'Alberto Brandolini : on couvre un grand mur de post-it représentant les événements métier (« cargaison réservée », « voyage annulé », « dédouanement effectué »), dans l'ordre du temps, avec les experts dans la pièce. Les zones où le vocabulaire se met à diverger, où deux personnes ne sont pas d'accord sur un mot — ce qu'on appelle les hotspots — sont précisément les endroits où passent souvent les frontières de contexte.
« EventStorming is my pizza — you can put everything on it except pineapples and database tables. »
La blague dit une chose sérieuse : dans un atelier de découverte, on parle métier et événements, jamais de tables de base de données. La technique vient après ; laisser le schéma technique s'inviter trop tôt, c'est laisser la solution contaminer la compréhension du problème.
Une fois les sous-domaines dégrossis, comment décider où investir ? Nick Tune propose le Core Domain Chart : on place chaque sous-domaine sur deux axes — son avantage compétitif (à quel point il te différencie) et sa complexité de modèle. La position sur la carte suggère la stratégie : construire soi-même avec soin, acheter sur étagère, ou externaliser.
+ complexe
+ simple
+ complexe
Enfin, pour cadrer un contexte une fois qu'on l'a identifié, le Bounded Context Canvas aide à répondre aux bonnes questions : quel est son rôle, quel langage y parle-t-on, quelles décisions métier y sont prises, quelles sont ses entrées et sorties ? Un signal d'alarme à connaître : si le nom d'un contexte contient le mot « Manager » ou « Service » générique, c'est souvent le symptôme d'un fourre-tout mal délimité.
La carte de contextes : rendre le couplage visible
Tu peux avoir découpé tes contextes à la perfection. S'ils communiquent, il y a des relations entre eux — et ces relations ont des rapports de force que personne n'a décidés consciemment.
« Good fences make good neighbors », dit le poète Robert Frost — les bonnes clôtures font les bons voisins. Michael Plöd aime citer ce vers pour introduire le context mapping. Une frontière nette ne coupe pas les relations ; elle les rend saines, parce qu'on sait enfin où l'un finit et où l'autre commence. Mais encore faut-il dessiner ces relations. C'est l'objet de la carte de contextes.
Une représentation des bounded contexts d'un système et des relations entre eux : qui appelle qui, qui impose son modèle à qui, quelles équipes doivent se parler. Plöd la surnomme le « joyau caché » du DDD — l'outil qui rend visible ce qui, d'habitude, se subit.
Pourquoi si précieuse ? Parce qu'elle révèle une réalité qu'on préfère ignorer : entre deux contextes, il y a presque toujours un rapport de pouvoir. Plöd le formule sans détour.
« The upstream team has a lot of power, whereas the downstream team is sometimes helpless. »
Le vocabulaire à retenir est celui de la rivière. Le contexte upstream (amont) est celui dont les décisions coulent vers les autres ; le contexte downstream (aval) subit ces décisions. Contre-intuition importante, soulignée par Evans : le sens du pouvoir n'est pas forcément le sens du flux de données. Quand tu envoies ta déclaration au fisc, c'est toi qui produis la donnée — et pourtant c'est le fisc qui est upstream, parce que c'est lui qui dicte le format et les règles. Tu te conformes, quel que soit le sens dans lequel circulent les octets.
Ces relations se rangent en trois grandes familles, chacune appelant des patterns différents qu'on détaillera dans les deux sections suivantes.
| Type de dépendance | Nature | Patterns associés |
|---|---|---|
| Mutuelle | Les deux contextes dépendent l'un de l'autre. | Partnership, Shared Kernel |
| Amont / aval | L'un dicte, l'autre suit. | Customer-Supplier, Conformist, Anti-Corruption Layer, Open Host Service |
| Libre | Aucune dépendance directe voulue. | Separate Ways, Published Language |
Plöd insiste sur le fait qu'une bonne carte s'observe sous quatre perspectives complémentaires : les appels techniques (qui invoque qui), la propagation des modèles (dont on va voir qu'elle est le vrai danger), la communication entre équipes, et les API exposées. Une carte qui ne montre que les appels HTTP passe à côté de l'essentiel.
Un dernier point qu'Evans a ajouté avec l'expérience : les motivations d'une frontière (est-ce un sous-domaine générique ? du sur-étagère ? quel niveau de rigueur ? quel style d'architecture ?) doivent être documentées sur le contexte lui-même, pas dans la tête d'une équipe qui changera. Il appelle ça, avec un clin d'œil, le « context mapping 2.0 ». Une carte qui survit au turnover, voilà le but.
Patterns d'intégration : jusqu'où le couplage pénètre
Deux contextes doivent parler. La vraie question n'est pas « en HTTP ou en messages ? » — c'est « quand l'autre change son modèle, jusqu'où l'onde de choc remonte chez moi ? ».
On arrive au cœur réellement neuf du DDD stratégique. Deux contextes qui s'intègrent, ça semble être une question de tuyauterie technique. C'est en réalité une question de profondeur de couplage : à quel point le modèle de l'autre s'infiltre dans le tien. Plöd est catégorique sur un point qu'on oublie toujours.
« There is no decoupling. When systems have a connection together, we have a loose coupling. »
Il n'existe pas de découplage. Dès que deux systèmes se parlent, ils sont couplés — la seule question est de savoir si ce couplage est lâche (loose) ou pénétrant. Les patterns d'intégration sont classés, précisément, par profondeur de pénétration. Voyons les principaux, du plus protecteur au plus envahissant.
Un contexte expose une API publique, stable et pensée pour plusieurs consommateurs à la fois. Plutôt que d'inventer une intégration sur mesure pour chacun, l'upstream publie un contrat unique. Il porte le coût de la stabilité pour épargner ses consommateurs.
Un langage d'échange standardisé et documenté, indépendant du modèle interne de qui que ce soit. Les formats
iCalendar (.ics) ou vCard en sont l'exemple parfait : personne n'impose son modèle, tout le monde parle une lingua franca. À ne pas confondre avec l'OHS — l'OHS expose un contexte, le published language est un standard partagé au-dessus des contextes.
Une couche de traduction que le contexte aval construit pour protéger son propre modèle. Tout ce qui vient de l'upstream est traduit, à l'entrée, dans le vocabulaire local. Le modèle étranger ne franchit jamais la frontière : il s'arrête à l'ACL. C'est du couplage lâche — pas nul, mais confiné.
Le contexte aval renonce à sa propre vision et adopte tel quel le modèle de l'upstream. Zéro traduction, donc zéro coût de traduction — mais le modèle étranger pénètre alors jusqu'au cœur. Chaque changement en amont te traverse de part en part. Parfois un choix raisonnable (l'upstream est bien conçu, stable) ; sur ton core domain, presque toujours une faute.
Deux contextes partagent un morceau de modèle ou de schéma commun. C'est le couplage le plus fort : tout changement du noyau partagé impacte les deux côtés, qui doivent se coordonner en permanence. Puissant entre deux équipes très proches, poison entre deux équipes distantes.
Plöd a une image saisissante pour le danger central : la « model propagation from the gates of hell ». Un couplage profond — un conformist, un shared kernel mal maîtrisé — laisse le modèle de l'upstream se propager insidieusement à travers ta frontière, jusqu'à contaminer ton cœur. Le simulateur ci-dessous rend cette propagation visible. Choisis ton pattern, puis déclenche un changement de modèle chez l'upstream, et regarde jusqu'où l'onde de choc remonte.
Ton contexte est fait de trois anneaux : l'adaptateur (au contact de l'extérieur), l'application, et le cœur métier. Choisis comment tu t'intègres au système upstream, puis clique pour simuler un changement de son modèle. Observe où l'onde s'arrête.
La leçon est nette : l'ACL te coûte une couche de traduction à écrire et à maintenir — parfois presque aussi grosse que le contexte qu'elle protège — mais elle confine l'onde de choc à un seul point. Le conformist ne coûte rien à écrire et te fait payer à chaque changement de l'autre, dans tout ton code. Sur un sous-domaine générique, le conformist se défend ; sur ton cœur, l'ACL est le prix de ta liberté. Ce mécanisme de traduction se combine très bien avec un découplage par événements — voir DDD : les Domain Events — et il est la vraie parade au couplage caché qu'on retrouve dans les relations many-to-many propagées à travers les frontières.
Patterns d'équipe : le code suit les relations humaines
Certains patterns du context mapping ne parlent pas de code du tout. Ils parlent de qui invite qui en réunion, de qui a le pouvoir de dire non, et de ce qui arrive quand personne ne l'a.
La cartographie des contextes a une face technique — comment les modèles s'intègrent, qu'on a vue — et une face socio-technique : comment les équipes qui possèdent ces contextes se comportent entre elles. Plöd insiste : ces patterns d'équipe sont au moins aussi déterminants que les patterns de code, parce que, loi de Conway oblige, la structure sociale finit toujours par s'imprimer dans le logiciel.
Deux équipes dont les contextes dépendent mutuellement l'un de l'autre s'engagent à coordonner leur planning et à réussir ou échouer ensemble. Plöd les décrit avec humour : « they live in meetings » — elles vivent en réunion. Puissant quand l'objectif est vraiment commun, épuisant sinon.
Relation amont/aval saine : le fournisseur (upstream) reste maître de son modèle, mais l'équipe cliente (downstream) a un vrai poids dans sa planification. Le client exprime ses besoins, le fournisseur les priorise honnêtement. Un équilibre négocié, pas subi.
Ce dernier pattern a deux dégénérescences qu'il faut savoir nommer, parce que les voir, c'est déjà commencer à les soigner :
| Anti-pattern | Ce qui se passe |
|---|---|
| Vetoing customer | Le client abuse de son pouvoir et bloque le fournisseur avec des exigences contradictoires. Le fournisseur n'avance plus. |
| Helpless supplier | Le fournisseur subit sans jamais pouvoir dire non ni imposer ses contraintes. Le contrat se déforme au gré des clients. |
Le choix, assumé, de ne pas intégrer deux contextes. Parfois la meilleure décision d'architecture est l'absence de connexion : on duplique un peu, on économise énormément de couplage. Ne jamais sous-estimer la valeur d'un « on ne se parle pas ».
Et puis il y a le pattern qui n'en est pas un — celui qu'on dessine sur la carte comme un panneau « danger » :
Evans a ajouté, avec les années, une image que tout développeur reconnaît. Autour de la grosse boule de boue, on construit un mur — un ACL — et derrière ce mur on s'offre « one year of paradise » : un an de tranquillité à coder proprement dans un contexte neuf, sans que la boue ne remonte. Le mur n'assainit pas la boue ; il protège le paradis. C'est le sujet exact de la section suivante.
Vivre avec le legacy : le mur et la douve
Aucun système ne naît sur une page blanche. Il y a toujours un vieux monolithe, un logiciel acheté, une API imposée. La stratégie DDD ne consiste pas à tout réécrire — mais à savoir où mettre les frontières.
On idéalise volontiers le DDD comme un art du terrain vierge. La réalité, c'est presque toujours un système existant qu'on ne peut ni jeter ni ignorer. Bonne nouvelle : le DDD stratégique a été forgé pour cette réalité. Evans et Plöd donnent tout un vocabulaire pour composer avec le legacy sans se laisser dévorer par lui.
Le premier réflexe, on l'a vu, c'est l'anti-corruption layer. Mais Evans précise un point qu'on oublie : un bon ACL protège dans les deux sens. Il traduit ce qui entre pour que le legacy ne corrompe pas ton modèle neuf, et il traduit ce qui sort pour que ton modèle neuf ne casse pas le legacy qui, lui, ne changera pas. C'est une membrane, pas une passoire à sens unique.
Face à un legacy, tu as un vrai choix stratégique entre deux postures opposées, et le nommer t'évite de le subir :
Conformist
Anti-Corruption Layer
Evans enrichit encore la palette pour le cas fréquent du système ancien qu'on veut faire évoluer sans big bang. Le bubble context : une petite bulle de modèle propre créée à côté du legacy, protégée par un ACL, dans laquelle on peut travailler proprement. Si la bulle devient autonome et durable, elle devient une autonomous bubble. C'est la stratégie du grignotage — on gagne du terrain propre, mètre par mètre, plutôt que de tout raser d'un coup.
L'équation « un microservice = un bounded context » est trop simple, prévient Evans. Un bounded context peut se réaliser en plusieurs microservices, ou un microservice mal découpé peut chevaucher deux contextes. Le bounded context est une frontière de modèle ; le microservice est une frontière de déploiement. Elles peuvent coïncider, ce n'est pas obligatoire.
Deux postures d'intégration reviennent avec les systèmes tiers, et il faut les choisir en conscience. Face à un géant comme un CRM du marché, on est souvent conformist — on parle sa langue, un point c'est tout, parce qu'on ne pèse rien face à lui et que ce n'est pas notre cœur de métier. Face à un vieux système interne qu'on veut moderniser, on met presque toujours un ACL — parce qu'on veut, cette fois, garder la main sur le modèle.
Et rappelle-toi la contre-intuition de la section 07 : le pouvoir ne suit pas le flux de données. Même quand c'est toi qui envoies l'information à un système externe, si c'est lui qui dicte le format, c'est lui l'upstream, et c'est à toi de te conformer ou de traduire. La stratégie, ici, c'est de choisir lequel — jamais de le découvrir après coup dans la douleur.
Synthèse : le DDD est une philosophie, pas une religion
On a parcouru beaucoup de patterns. Le risque, maintenant, serait d'en faire un dogme et de les appliquer partout. Ce serait trahir l'esprit même de la démarche.
Refaisons le chemin. On est parti de l'idée qu'un modèle n'est pas la réalité mais une abstraction utile, taillée pour un problème. De là est né le langage ubiquitaire — le même vocabulaire du métier jusque dans le code — puis le constat qu'un langage n'a de sens que dans une frontière. Cette frontière, c'est le bounded context, à distinguer soigneusement du sous-domaine (le problème) et de l'équipe (l'organisation). On a vu comment découvrir ses contextes par un processus collaboratif et itératif, puis comment cartographier leurs relations — les rapports de pouvoir upstream/downstream, la profondeur du couplage, les patterns d'intégration et d'équipe, et l'art de vivre avec le legacy.
Le fil rouge de tout cela, ce sont les quatre essentiels qu'Evans retient de vingt ans de pratique :
Remarque ce qui ne figure pas dans cette liste : aucun bloc de construction tactique. Ni entité, ni value object, ni agrégat. Evans considère qu'on a collectivement sur-vendu la partie tactique et sous-utilisé la partie stratégique. La seule exception qu'il concède, c'est l'agrégat — le seul bloc tactique qu'il ne trouve pas surestimé (raison de plus pour lire DDD : les agrégats).
Et surtout, le DDD n'est pas une case à cocher sur tous les projets. C'est une philosophie appliquée, avec un spectre de rigueur — on ajuste la dose de formalisme à la complexité réelle du domaine. Un CRUD sans subtilité métier n'a pas besoin de bounded contexts ni de langage ubiquitaire : ce serait de la cérémonie pure. Le DDD ne se justifie que là où il y a une vraie complexité de domaine à dompter.
« DDD is a kind of applied philosophy. It is emphatically not a religion. »
Quand NE PAS faire de DDD stratégique
- Le domaine est simple, sans règles métier subtiles (un formulaire, un CRUD) : la cérémonie coûterait plus qu'elle ne rapporte.
- Tu n'as aucun accès à un expert métier : tu modéliserais dans le vide.
- Le projet est jetable ou expérimental : investir dans des frontières durables n'a pas de sens.
Guide de choix express
| Situation | Réflexe stratégique |
|---|---|
| Un mot change de sens selon les interlocuteurs | Deux bounded contexts, une frontière entre eux. |
| Un système externe impose son modèle sur ton cœur | Anti-Corruption Layer, sans hésiter. |
| Un système générique, non différenciant, bien fait | Conformist assumé — ou l'acheter. |
| Tu exposes une API à plusieurs consommateurs | Open Host Service + Published Language. |
| Deux équipes doivent réussir ensemble | Partnership — mais surveille les réunions. |
| Une zone de code est irrécupérable | Nomme-la Big Ball of Mud, entoure-la d'un ACL. |
Pour aller plus loin
Ce cours est le versant stratégique. Pour le versant tactique — comment ces idées se traduisent en objets de code — enchaîne avec :