Contextes délimités
VoletStratégique Le concept central de DDD. Si une seule notion doit être retenue de tout ce corpus, c’est celle-ci.
Un contexte délimité est une frontière explicite à l’intérieur de laquelle un modèle s’applique et chaque terme a exactement un sens. En dehors, le modèle ne prétend rien. Les mêmes mots peuvent y désigner autre chose, et c’est très bien.
Le problème qu’il résout
Prenez le mot « client » dans une entreprise de taille moyenne, et posez la question à trois services.
| Service | Ce qu’est un client | Ce qui l’intéresse |
|---|---|---|
| Commerce | Un prospect, une opportunité | Historique des échanges, potentiel, appétence |
| Facturation | Une entité juridique | Raison sociale, TVA intracommunautaire, IBAN, encours |
| Support | Un utilisateur | Incidents, contrat de service, matériel installé |
Aucun n’a tort. Le réflexe habituel est pourtant de construire une classe
Client qui satisfasse les trois — le fameux modèle de données d’entreprise
unifié. Le résultat est prévisible et se reconnaît partout :
- quarante-cinq champs, dont trente sont
nullpour tout usage donné ; - des champs dont la signification dépend d’un autre champ (« l’IBAN n’est renseigné que si le client est facturable, sauf pour les grands comptes ») ;
- une classe que personne ne peut modifier sans risquer de casser trois services ;
- et un vocabulaire qui redevient ambigu, puisque le mot recouvre à nouveau trois réalités.
La solution de DDD est contre-intuitive et libératrice : arrêter de chercher un modèle unique. Trois contextes, trois modèles de client, reliés par la seule chose qu’ils ont réellement en commun — une identité.
Notez ce qui a disparu : le champ inutilisé, le null conditionnel, le
commentaire d’exception. Et ce qui est apparu : trois noms différents. Prospect,
Debiteur, Beneficiaire ne sont pas des synonymes de « client » — ce sont les
mots que chaque service emploie réellement.
Tip
La duplication apparente inquiète toujours. Ce n’est pas de la duplication : ce sont trois concepts différents qui partagent un identifiant. La preuve opérationnelle : ils ne changent pas pour les mêmes raisons ni au même rythme. Une nouvelle règle de scoring commercial ne touche pas la facturation. C’est exactement le critère de la responsabilité unique, appliqué à l’échelle d’un modèle.
La frontière est d’abord linguistique
On ne trace pas un contexte selon des critères techniques. On le trace là où le langage change. Les trois signaux décrits dans Langage omniprésent sont les outils de détection : un mot qui a besoin d’un adjectif, deux mots pour une chose, un mot qui déclenche deux réactions.
D’autres indices convergent en général avec le premier :
- Le rythme de changement. Deux parties qui évoluent à des cadences très différentes appartiennent probablement à deux contextes.
- Les personnes. Si vous devez interroger deux experts distincts qui ne se parlent pas, la frontière est déjà là dans l’organisation.
- Les règles de cohérence. Deux ensembles de données qui n’ont jamais besoin d’être cohérents dans la même transaction peuvent être séparés.
- Les données réellement échangées. Si le contexte B n’a besoin que de trois champs sur quarante de A, il n’a pas besoin du modèle de A.
Ce qui constitue vraiment un contexte
Un contexte délimité n’est pas seulement une idée : c’est une frontière qu’on doit pouvoir constater. En pratique, il possède en propre :
| Élément | Exigence |
|---|---|
| Un modèle | Un ensemble cohérent d’agrégats et d’objets valeur |
| Un langage | Un vocabulaire sans ambiguïté interne |
| Une base de données | Non partagée — c’est le point le plus violé |
| Un code source | Un module, un paquet, une crate, un dépôt |
| Une équipe | Idéalement une seule ; jamais un morceau partagé entre trois |
Warning
Deux contextes qui partagent des tables ne sont pas deux contextes. La base de
données partagée est le mécanisme le plus efficace pour annuler tout le bénéfice du
découpage : le schéma devient une interface implicite que personne ne peut faire
évoluer, et le modèle de chacun se met à dépendre de celui des autres sans qu’aucun
import ne le montre. Si la séparation physique est impossible à court terme,
séparer les schémas — ou au minimum interdire les jointures inter-contextes — est
le compromis minimal défendable.
Contexte délimité et microservice
C’est la confusion la plus répandue et la plus coûteuse.
| Contexte délimité | Microservice | |
|---|---|---|
| Nature de la décision | Modélisation | Déploiement |
| Question posée | Où le modèle cesse-t-il d’être valide ? | Que déploie-t-on séparément ? |
| Conséquence si on se trompe | Modèle ambigu | Latence, pannes partielles, transactions distribuées |
Les deux notions sont indépendantes, et les combinaisons possibles sont toutes légitimes :
- Un contexte, un module dans un monolithe. Le point de départ recommandé — le monolithe modulaire. Toutes les frontières de modélisation, aucun coût réseau.
- Un contexte, un service. Le cas dont tout le monde parle. Justifié par des besoins d’échelle, de cadence de déploiement ou d’autonomie d’équipe — pas par la modélisation.
- Plusieurs contextes dans un service. Fréquent et souvent sain, au début.
- Plusieurs services pour un contexte. Presque toujours une erreur : les services se partagent alors un modèle et un invariant, et l’on obtient un monolithe distribué — le couplage du monolithe avec les pannes du distribué.
Note
La règle pratique qui évite le plus de dégâts : découper en contextes d’abord, en services plus tard. Les frontières de modélisation sont difficiles à trouver et faciles à déplacer dans un monolithe ; elles deviennent presque impossibles à déplacer une fois qu’un appel réseau et un contrat d’API les traversent. Un contexte mal placé dans un monolithe est un refactoring ; un contexte mal placé entre deux services est un projet.
Quelle taille ?
Il n’existe pas de bonne réponse chiffrée, mais deux échecs symétriques.
Trop grand : le langage redevient ambigu à l’intérieur, ce qui est précisément ce qu’on voulait éviter. Le symptôme est le retour des adjectifs de désambiguïsation dans les conversations de l’équipe.
Trop petit : les invariants métier se retrouvent à cheval sur deux contextes, donc sur deux transactions. On se met à avoir besoin de cohérence immédiate entre des choses séparées, c’est-à-dire de transactions distribuées — le signe le plus sûr d’une frontière mal placée.
L’heuristique la plus utilisable : un contexte doit tenir dans la tête d’une équipe, et son modèle doit pouvoir être expliqué à un nouvel arrivant en une séance. Si l’explication nécessite « alors là, ça dépend du cas », le contexte est probablement trop large.
Le même objet dans deux contextes
Une dernière subtilité qui met du temps à passer. Une même chose du monde réel — une personne, un colis, un contrat — peut être modélisée dans plusieurs contextes, avec des attributs différents, un comportement différent, et parfois un cycle de vie différent.
Ce ne sont pas des copies à synchroniser : ce sont des points de vue. Le seul lien est l’identité. Le contexte Expédition n’a pas besoin de connaître le plafond de crédit ; le contexte Facturation n’a pas besoin de connaître le poids du colis. Chacun garde ce dont il a besoin pour décider, et rien de plus.
La question qui suit naturellement — comment ces contextes se procurent-ils ce dont ils ont besoin, et qui dépend de qui — est celle de la cartographie de contextes.
Références
- Eric Evans, Domain-Driven Design, chapitre 14 — Maintaining Model Integrity
- https://martinfowler.com/bliki/BoundedContext.html
- https://github.com/ddd-crew/bounded-context-canvas — canevas pour décrire un contexte