Le problème
Beaucoup de systèmes deviennent confus non pas parce qu’ils manquent de code, mais parce qu’ils mélangent plusieurs modèles métier dans le même espace.
On retrouve souvent les mêmes symptômes :
- un même mot veut dire plusieurs choses selon l’équipe
- une entité grossit jusqu’à représenter plusieurs réalités différentes
- des règles métier se contredisent selon le cas
- des champs s’ajoutent juste pour “couvrir aussi” un autre usage
- les intégrations entre modules finissent en bricolage de mapping implicite
Exemple classique : Customer.
Selon le contexte, Customer peut vouloir dire :
- un prospect dans le CRM
- un acheteur dans la facturation
- un titulaire de contrat dans un système de souscription
- un compte support dans un helpdesk
Le mot est le même. Le modèle ne l’est pas.
Quand on force tout dans une seule définition, on finit avec un modèle flou, instable et difficile à maintenir.
Le bounded context sert à éviter ça.
L’idée simple
Un bounded context est une frontière dans laquelle un modèle garde un sens précis.
À l’intérieur d’un contexte :
- les mots ont une définition claire
- les règles métier sont cohérentes
- les objets du modèle appartiennent à la même logique
À l’extérieur, ces mêmes mots peuvent exister avec un autre sens.
Le point important est simple :
on n’essaie pas d’imposer un modèle unique à tout le système.
On accepte qu’un système réel contienne plusieurs modèles, chacun valide dans sa propre frontière.
Comment ça fonctionne
Le bounded context est d’abord un outil de découpage du système.
1. Un mot n’a pas forcément le même sens partout
Dans un projet réel, les équipes utilisent souvent les mêmes mots pour parler de choses différentes.
Exemple avec Order :
- dans le checkout, une commande en cours de création
- dans la logistique, un colis à préparer
- dans la facturation, un document lié à un paiement
- dans le support, un historique consultable
Forcer un seul modèle Order pour tout le monde produit souvent :
- trop de champs
- trop de statuts
- trop de branches conditionnelles
- trop de couplage entre équipes
Le bounded context dit : chaque partie garde le modèle dont elle a besoin.
2. La frontière protège le sens
Un contexte n’est pas juste un dossier. C’est une frontière explicite :
- du vocabulaire
- des règles
- des objets
- des cas d’usage
À l’intérieur d’un contexte, on cherche la cohérence. Entre contextes, on accepte la traduction.
C’est ce qui évite qu’un modèle externe vienne déformer un modèle local.
3. Les relations entre contextes doivent être explicites
Deux contextes peuvent collaborer. Mais ils ne doivent pas fusionner par accident.
Quand un contexte a besoin d’informations d’un autre, il faut rendre l’échange visible :
- API
- événements
- mapping
- couche de traduction
- contrat d’intégration
Le pire scénario est le plus courant : un contexte commence à importer directement les structures internes d’un autre.
À partir de là, la frontière est déjà cassée.
Schéma
Lecture utile :
- chaque contexte a son propre modèle
- les échanges passent par des frontières explicites
- on évite le partage direct de structures internes
Exemple concret
Prenons une plateforme SaaS.
Au début, tout semble simple :
on crée une entité Customer.
Puis le système grandit.
Dans le contexte Sales
Le sujet principal est la conversion commerciale.
Customer signifie plutôt :
- une entreprise en discussion
- une étape de pipeline
- une source d’acquisition
- un owner commercial
- une probabilité de conversion
Ici, les statuts utiles ressemblent à :
leadqualifiedproposal_sentwonlost
Dans le contexte Billing
Le sujet principal est la facturation.
Customer signifie plutôt :
- un compte facturable
- un identifiant de facturation
- un pays fiscal
- une devise
- un statut de paiement
Ici, les préoccupations utiles sont :
- moyen de paiement
- facture en retard
- TVA
- suspension du compte
Dans le contexte Support
Le sujet principal est l’assistance.
Customer signifie plutôt :
- une organisation cliente
- un plan de support
- un niveau de priorité
- un historique d’incidents
- des contacts autorisés
Ici, les préoccupations utiles sont :
- SLA
- niveau d’escalade
- incidents ouverts
- dernier contact
Le mauvais design
Vouloir tout mettre dans une seule entité :
export type Customer = {
id: string;
salesOwnerId?: string;
leadSource?: string;
pipelineStage?: string;
billingEmail?: string;
vatNumber?: string;
paymentStatus?: string;
supportPlan?: string;
escalationLevel?: string;
lastIncidentAt?: Date;
};
Ce type est un signal d’alarme :
- trop de champs optionnels
- plusieurs responsabilités
- aucun sens métier stable
Le bon design
Chaque contexte porte son propre modèle.
Sales
export type SalesCustomer = {
id: string;
companyName: string;
pipelineStage: "lead" | "qualified" | "proposal_sent" | "won" | "lost";
salesOwnerId: string;
};
Billing
export type BillingCustomerAccount = {
id: string;
legalName: string;
billingEmail: string;
vatNumber?: string;
paymentStatus: "ok" | "late" | "suspended";
currency: string;
};
Support
export type SupportCustomer = {
id: string;
organizationName: string;
supportPlan: "standard" | "premium";
escalationLevel: 1 | 2 | 3;
};
Chaque modèle devient plus simple parce qu’il parle d’un seul problème.
Comment reconnaître un bounded context
En pratique, il y a plusieurs signaux utiles.
Le vocabulaire diverge
Si deux équipes utilisent le même mot avec des sens différents, il y a souvent plusieurs contextes.
Les règles changent selon la zone du système
Si la même entité doit respecter des règles très différentes selon l’usage, le modèle est probablement trop large.
Les champs deviennent artificiels
Quand on multiplie les champs optionnels, les sous-types implicites et les statuts fusionnés, on masque souvent plusieurs contextes sous un seul nom.
Les échanges demandent déjà de la traduction
Si une équipe transforme systématiquement les données d’une autre avant de les utiliser, c’est souvent qu’elle travaille déjà dans un autre contexte.
Exemple d’intégration saine
Un contexte Sales peut notifier Billing qu’un contrat est gagné.
Événement émis par Sales
export type CustomerContractWon = {
customerId: string;
companyName: string;
billingEmail: string;
planCode: string;
};
Traitement côté Billing
export class CreateBillingAccountFromWonContract {
async handle(event: CustomerContractWon): Promise<void> {
// Traduction vers le modèle Billing
}
}
Le point important :
Billingne réutilise pas le modèle interne deSalesBillingtraduit l’événement dans son propre langage- la frontière reste claire
Points importants
- Un bounded context protège le sens d’un modèle.
- Il évite de forcer un vocabulaire unique sur tout le système.
- Le même mot peut exister dans plusieurs contextes avec des sens différents.
- Le but n’est pas de séparer pour séparer.
- Le but est d’éviter un modèle global flou et contradictoire.
- Les échanges entre contextes doivent être explicites.
Erreurs fréquentes
Chercher un modèle unique pour tout le système
C’est l’erreur la plus classique.
Un modèle global paraît propre au début, puis devient un point de couplage massif.
Confondre bounded context et microservice
Un bounded context est une frontière de modèle, pas forcément un service déployé séparément.
On peut avoir plusieurs contextes dans un monolithe. On peut aussi avoir un microservice qui contient un mauvais mélange de contextes.
Découper par équipe ou par table
Le bounded context ne se décide ni par organigramme ni par schéma SQL.
La vraie question est : où le modèle garde-t-il un sens cohérent ?
Partager directement les objets internes
Si un contexte importe les classes, DTO ou entités internes d’un autre, la frontière devient théorique.
Les échanges doivent passer par des contrats explicites.
Utiliser le mot sans clarifier le vocabulaire
Nommer un dossier bounded-context n’aide pas si personne ne sait :
- quels mots appartiennent à ce contexte
- quelles règles y vivent
- ce qui entre et ce qui sort
Conclusion
Le bounded context sert à découper un système quand un seul modèle ne suffit plus.
Il permet de garder des mots clairs, des règles cohérentes et des frontières lisibles.
Le réflexe le plus utile est simple :
si un mot change de sens selon la zone du système, il y a probablement plusieurs contextes.