Le langage ubiquitaire
Un langage unique, rigoureux et partagé entre experts métier et développeurs — incarné jusque dans le code.
Sur la plupart des projets, deux langages cohabitent en silence. D'un côté, les experts du domaine parlent avec le jargon de leur métier : un transitaire évoque un « itinéraire », une « clause de mise en douane », un « préavis de chargement ». De l'autre, les développeurs parlent de tables, de lignes à supprimer, de booléens, de services qui « repeuplent » des enregistrements. Entre les deux, une poignée de personnes deviennent bilingues et traduisent en permanence — devenant au passage des goulets d'étranglement dont les traductions sont toujours un peu fausses.
Eric Evans en fait un diagnostic sans appel : ce fossé linguistique tue les projets. La traduction permanente masque les désaccords de compréhension, brouille les concepts du modèle, et empêche le jaillissement d'idées qui mène aux modèles profonds. Sa réponse tient en deux mots et un principe : le langage ubiquitaire (Ubiquitous Language). Un seul langage, fondé sur le modèle de domaine, employé partout — dans les conversations, les schémas, la documentation, les tests et, surtout, dans le code. Les exemples du livre sont en Java ou conceptuels ; nous les traduisons en TypeScript idiomatique, dans des univers de logistique (transport de fret), d'e-commerce et de banque.
Le coût caché de la traduction
Sur un projet sans langage commun, la traduction se ramifie à l'infini. Les développeurs traduisent pour les experts métier. Les experts métier traduisent entre développeurs et autres experts. Or toute traduction est inexacte, et son inexactitude se paie cher :
- Elle masque les désaccords de compréhension — entre experts et développeurs, mais aussi entre développeurs, et entre experts eux-mêmes.
- Elle embrouille les concepts du modèle, ce qui provoque des refactorisations destructrices du code.
- Elle dissimule la formation de schismes : deux personnes emploient le même terme avec des sens différents, sans même s'en rendre compte. Le logiciel finit par ne plus « tenir ensemble ».
- L'effort de traduction étouffe l'échange de connaissances qui produit les intuitions de modélisation profondes.
Le problème est aggravé par un troisième larron : le vocabulaire enfoui dans le code, souvent déconnecté du langage des discussions quotidiennes. Pire encore, une même personne ne parle pas comme elle écrit ni comme elle code. Les expressions les plus justes du domaine émergent souvent à l'oral, sous une forme fugace, et ne sont jamais captées — ni dans l'écrit, ni dans le code.
À retenir
Aucun des dialectes en présence ne peut servir de langue commune, car aucun ne couvre tous les besoins. Le jargon métier ignore la conception ; le jargon technique ignore le sens métier. Il faut un langage qui soit plus que le plus petit dénominateur commun — et ce langage, c'est le modèle de domaine qui le fournit.
Le modèle comme ossature du langage
L'idée centrale d'Evans est qu'un modèle peut être vu comme un langage. Son vocabulaire est constitué des noms des classes et des opérations importantes. Il fournit les moyens de discuter des règles rendues explicites dans le modèle. On l'enrichit ensuite des noms des patrons que l'équipe applique couramment et des grands principes d'organisation du système.
Ce langage fondé sur le modèle doit servir de langage primaire : entre développeurs pour décrire les artefacts du système, entre développeurs et experts métier, et entre experts métier eux-mêmes pour parler des exigences et des fonctionnalités. Plus le langage est employé de manière pervasive, plus la compréhension circule sans friction.
Mais il y a une subtilité, presque un paradoxe. Au départ, le modèle n'est peut-être pas assez bon pour remplir ce rôle : les jargons spécialisés du métier sont souvent plus complets et mieux adaptés au problème que le modèle formalisé que produisent les développeurs. Le prérequis d'un bon modèle est donc… l'engagement de l'équipe à s'appuyer dessus malgré ses imperfections.
Astuce
L'usage persistant du langage fait remonter ses faiblesses à la surface. Une tournure maladroite, un terme ambigu, un concept manquant : tout cela se révèle quand on s'oblige à parler avec le modèle. L'équipe expérimente alors des alternatives, et chaque amélioration du langage est reconnue comme une amélioration du modèle — qui se répercute dans les diagrammes et dans le renommage des classes et méthodes.
Affiner le langage, c'est affiner le modèle. Et inversement. Les deux ne font qu'un.
Deux dialogues sur le routage de fret
Evans illustre tout cela par un exemple devenu célèbre : deux dialogues entre un utilisateur (expert métier) et un développeur, à propos d'une application de routage de fret commercial. Les différences sont subtiles, mais décisives. La question à se poser en les lisant : parlent-ils de ce que le logiciel signifie pour le métier, ou de la façon dont il fonctionne techniquement ?
Scénario 1 : une abstraction minimale du domaine
Dans le premier dialogue, le développeur répond en termes purement techniques. Le code correspondant ne connaît que des tables et des drapeaux.
// ❌ Avant : le code parle technique, pas métier.
class Cargo {
cargoId!: string;
origin!: string;
destination!: string;
customsClearance?: string;
weight!: number;
hazMatCode!: string;
hasShipmentData = false; // booléen technique
}
// Le développeur raisonne en lignes de table à supprimer.
function onCustomsClearanceChange(cargo: Cargo): void {
database.delete("cargo_bookings", { cargoId: cargo.cargoId });
routingService.populate(
cargo.origin,
cargo.destination,
cargo.customsClearance,
);
cargo.hasShipmentData = true;
} DÉVELOPPEUR : On supprimera toutes les lignes de la table d'expédition pour ce cargo, puis on passera l'origine, la destination et le nouveau point de mise en douane au service de routage, et il repeuplera la table. On aura besoin d'un booléen dans le Cargo pour savoir s'il y a des données dans la table.
Quand l'utilisateur ajoute une subtilité métier — « on ne veut pas re-router si ce n'est pas nécessaire » —, la conversation s'enlise : il faut « interroger la table pour retrouver l'ancien point de mise en douane dérivé, puis le comparer au nouveau ». Le métier disparaît derrière la plomberie.
Scénario 2 : un modèle enrichi pour soutenir la discussion
Dans le second dialogue, deux concepts métier deviennent des objets de première classe : la spécification de route (Route Specification) et l'itinéraire (Itinerary), composé d'étapes (Legs). L'utilisateur employait déjà le mot « itinéraire » dans les deux dialogues — mais ici, c'est un objet qu'on peut désigner précisément.
// ✅ Après : le code parle le langage du métier.
class RouteSpecification {
constructor(
readonly origin: Location,
readonly destination: Location,
readonly customsClearance?: Location,
) {}
// Une règle métier devient une méthode nommée.
isSatisfiedBy(itinerary: Itinerary): boolean {
return itinerary.satisfies(this);
}
}
class Cargo {
constructor(
readonly cargoId: string,
private routeSpec: RouteSpecification,
private itinerary?: Itinerary,
) {}
changeRouteSpecification(spec: RouteSpecification): void {
this.routeSpec = spec;
if (!this.itinerary || !spec.isSatisfiedBy(this.itinerary)) {
this.itinerary = routingService.generate(spec);
}
}
} DÉVELOPPEUR : Quand vous modifiez quoi que ce soit dans la spécification de route, on vérifie si l'itinéraire la satisfait toujours. Si ce n'est pas le cas, on demande au service de routage de régénérer l'itinéraire.
La même contrainte métier — « ne re-router que si nécessaire » — qui paralysait le premier dialogue se formule ici en une phrase limpide, et se traduit directement par une méthode isSatisfiedBy. Le langage du modèle rend le dialogue économique. Les deux interlocuteurs peuvent enfin discuter de l'intention métier, pas des effets de bord d'une requête SQL.
| Scénario 1 | Scénario 2 | |
|---|---|---|
| Vocabulaire | tables, lignes, booléens | RouteSpecification, Itinerary, Leg |
| Règle « re-router » | requête + comparaison ad hoc | spec.isSatisfiedBy(itinerary) |
| Qui comprend ? | le développeur seul | l'expert et le développeur |
| Le code reflète… | la base de données | le domaine |
Modéliser à voix haute
Evans insiste sur un canal trop souvent négligé : la parole. Le décalage entre l'oral et les autres formes de communication est particulièrement nocif, car l'être humain a un génie naturel pour le langage parlé — qu'il gaspille en ne parlant presque jamais le langage du modèle.
Écoutez la prochaine réunion d'exigences à laquelle vous assistez. Vous entendrez du jargon métier, du jargon technique, des descriptions de fonctionnalités concrètes. Vous entendrez sûrement quelques noms du modèle. Mais entendrez-vous des phrases entières qui décrivent les relations et les interactions de votre modèle ?
L'une des meilleures façons d'affiner un modèle est de l'explorer à voix haute, en essayant différentes tournures. Les aspérités s'entendent immédiatement :
- « Si on donne au service de routage une origine, une destination et une date d'arrivée, il peut chercher les escales et… les coller dans la base. »
- « L'origine, la destination, et tout le reste… ça alimente le service de routage, et on récupère un itinéraire qui contient tout ce qu'il nous faut. »
- « Un service de routage trouve un itinéraire qui satisfait une spécification de route. »
La troisième formulation se lit comme une phrase, sujet-verbe-complément, et chacun de ses mots correspond à un élément du modèle. C'est le signe d'un modèle qui « coule ». Jouez avec le modèle quand vous parlez du système ; décrivez des scénarios à voix haute en combinant ses éléments ; trouvez des manières plus simples de dire ce que vous avez à dire, puis ramenez ces idées dans les diagrammes et le code.
Note
De même que lorsque des peuples de langues différentes se rencontrent pour commercer ils inventent un pidgin adapté à la tâche, une équipe qui parle réellement avec son modèle fait émerger naturellement les différences d'interprétation et les résout. Le langage parlé est un outil de conception, pas un simple accessoire des réunions.
Une équipe, un langage
Les développeurs ressentent souvent le besoin de « protéger » les experts métier du modèle : « c'est trop abstrait pour eux », « ils ne comprennent pas les objets », « on doit recueillir les exigences dans leur terminologie ». Evans balaie ces excuses. Oubliez-les.
Bien sûr, certains composants techniques de la conception n'intéressent pas les experts. Mais le cœur du modèle, lui, doit les intéresser. Trop abstrait ? Alors comment savez-vous que vos abstractions sont solides ? Comprenez-vous le domaine mieux qu'eux ? Si des experts métier chevronnés ne comprennent pas le modèle, c'est qu'il y a un problème avec le modèle.
La division des langages, quand elle est nécessaire, ne doit jamais passer entre experts métier et développeurs. C'est une règle de fond :
- Un développeur emploie évidemment un jargon technique que l'expert n'a pas à comprendre (transactions, persistance, files de messages).
- Un expert possède un jargon spécialisé qui dépasse de loin le périmètre de l'application.
- Mais ces deux jargons sont des extensions du langage commun, pas des vocabulaires alternatifs pour le même domaine reflétant des modèles concurrents.
Vaughn Vernon, dans DDD Distilled, complète ce tableau d'une exigence : le langage ubiquitaire doit être rigoureux — strict, exact, serré. Et il rappelle qu'un langage est toujours relatif à un contexte délimité (Bounded Context). Le mot « police » n'a pas le même sens en souscription, en sinistres et en inspection d'assurance ; chacun mérite son propre contexte, avec sa propre classe Police. Nous y reviendrons dans un chapitre dédié ; retenez pour l'instant qu'« un langage » signifie « un langage par contexte », et non un espéranto universel.
Piège courant
Le modèle dérive du jargon des experts, mais il le « nettoie » : il donne des définitions plus nettes et plus étroites. Les experts peuvent et doivent apprendre ces définitions affinées — et protester si elles divergent du sens réel de leur métier. C'est un dialogue, pas une dictée.
Incarner le langage dans le code
Le langage ubiquitaire n'a de valeur que s'il descend jusque dans le code. Concrètement, cela veut dire nommer classes, méthodes et variables avec les termes métier exacts, sans couche de traduction technique parasite.
// ❌ Avant : noms techniques, mapping mental requis.
class OrderManager {
processData(data: OrderDTO): void {
if (data.flag === 1 && data.amount > data.limit) {
this.repo.updateStatus(data.id, "S2");
}
}
} Que fait ce code ? Impossible de le dire sans interroger l'auteur. flag === 1 ? "S2" ? Le sens métier vit dans la tête d'une personne, pas dans le code. C'est exactement le « schisme » silencieux que dénonce Evans.
// ✅ Après : le code se lit comme une phrase du métier.
class Order {
placeOnCreditHold(): void {
if (this.isFlaggedForReview() && this.exceedsCreditLimit()) {
this.status = OrderStatus.CreditHold;
}
}
private isFlaggedForReview(): boolean {
return this.reviewFlag === ReviewFlag.Suspicious;
}
private exceedsCreditLimit(): boolean {
return this.totalAmount.isGreaterThan(this.customerCreditLimit);
}
} La méthode placeOnCreditHold (« placer en blocage de crédit ») nomme une opération que l'expert reconnaît instantanément. Un responsable du crédit pourrait relire ces trois lignes et confirmer la règle. Le code est devenu un support de conversation, pas seulement d'exécution.
Attention
Un mauvais nom coûte plus qu'une simple gêne de lecture. Contrairement au comportement d'un code (inéluctablement exact), un nom de méthode peut être ambigu, trompeur, ou périmé par rapport à ce que fait réellement la méthode. Un nom technique comme processData n'expose aucune contradiction métier : il les cache. Le jour où la règle de crédit change, personne ne sait quoi modifier.
Exprimer un scénario dans le langage métier
Vernon montre comment transformer un scénario parlé en test d'acceptation rédigé dans le langage du modèle. Reprenons un exemple proche du sien, transposé à la réservation logistique : « Un client peut réserver un itinéraire pour son fret. La réservation n'est possible que si l'itinéraire satisfait la spécification de route. Une fois la réservation effectuée, le fret est notifié. »
// ✅ Le test parle EXACTEMENT le langage du domaine.
describe("Réservation d'un itinéraire pour un fret", () => {
it("réserve quand l'itinéraire satisfait la spécification", () => {
const spec = new RouteSpecification(hongKong, hamburg);
const cargo = aCargoWithRouteSpecification(spec);
const itinerary = anItinerarySatisfying(spec);
cargo.assignToRoute(itinerary);
expect(cargo.isRouted()).toBe(true);
expect(cargo.itinerary).toBe(itinerary);
});
it("refuse quand l'itinéraire ne satisfait pas la spec", () => {
const spec = new RouteSpecification(hongKong, hamburg);
const cargo = aCargoWithRouteSpecification(spec);
const wrongItinerary = anItineraryEndingIn(rotterdam);
expect(() => cargo.assignToRoute(wrongItinerary)).toThrow(
ItineraryDoesNotSatisfySpecification,
);
});
}); Chaque identifiant — RouteSpecification, assignToRoute, isRouted, ItineraryDoesNotSatisfySpecification — appartient au langage ubiquitaire. Le test devient un document que l'expert métier peut relire, voire co-écrire. C'est ce que Vernon nomme la spécification par l'exemple (proche du BDD, Behavior-Driven Development, et de sa forme given/when/then). On notera au passage que les Domain Events comme BacklogItemCommitted chez Vernon, ainsi que l'Event Storming qu'il évoque pour accélérer la découverte, sont des prolongements modernes du DDD, postérieurs au livre d'Evans de 2003 — utiles, mais à ne pas confondre avec la brique d'origine.
Documents et schémas au service du langage
Faut-il pour autant écrire des montagnes de documentation et de diagrammes UML ? Evans répond avec nuance, et son fil conducteur est toujours le même : tout doit servir le langage, jamais le remplacer.
Les diagrammes UML sont d'excellents supports de discussion lorsqu'ils sont minimaux : esquissez trois à cinq objets centraux au problème du moment, et tout le monde reste concentré, partageant la même vue des relations et — surtout — des noms. Le problème survient quand on veut faire passer tout le modèle par l'UML : les diagrammes exhaustifs sont à la fois trop complets (on ne voit plus la forêt) et trop incomplets (l'UML ne sait exprimer ni le sens des concepts, ni leur comportement, qui retombent dans du texte ou de la parole).
Deux critères d'Evans pour juger un document de conception :
- Ne pas faire ce que le code fait déjà bien. Le code est la spécification ultime et exacte du comportement. Le document doit éclairer le sens, donner une vue des grandes structures, attirer l'attention sur les éléments essentiels.
- Être impliqué dans l'activité du projet. Le test le plus simple : le document est-il écrit dans le langage que les gens parlent aujourd'hui sur le projet ? Le langage embarqué dans le code ?
Astuce
Servez-vous du langage ubiquitaire comme d'un détecteur de documents morts. Si les termes d'un document de conception ne réapparaissent ni dans les conversations ni dans le code, il ne remplit pas son rôle. Et si vous entendez le langage évoluer pendant qu'un document, lui, reste figé : c'est qu'il n'est plus pertinent. Le maintenir à jour à la seule force de la discipline gaspille de l'effort.
Evans inverse même la pratique habituelle : plutôt qu'un diagramme annoté de texte, il rédige un document texte illustré de diagrammes sélectifs et simplifiés, parfois dessinés à la main — leur caractère provisoire reflétant la nature même de nos idées de modélisation. Le détail vital, lui, est capturé dans le code. Le modèle n'est pas le diagramme ; le diagramme sert à communiquer et expliquer le modèle.
À retenir
- La traduction permanente tue les projets : elle masque les désaccords, brouille les concepts et étouffe l'échange de connaissances. Le remède est un langage commun, et non un compromis minimal.
- Le modèle est l'ossature du langage : affiner le langage, c'est affiner le modèle, et réciproquement. L'usage persistant fait remonter les faiblesses à la surface.
- Une équipe, un langage : la frontière linguistique ne passe jamais entre experts métier et développeurs. Les jargons techniques ou métier sont des extensions, jamais des vocabulaires concurrents pour le même domaine.
- Parlez le modèle à voix haute : modéliser à l'oral révèle les aspérités plus vite que n'importe quel diagramme. Bannissez les traductions mentales.
- Le langage s'incarne dans le code : nommez classes, méthodes et tests avec les termes métier exacts (
placeOnCreditHold,isSatisfiedBy), jamais avec des codes techniques (flag === 1,"S2"). - Documents et schémas servent le langage : gardez-les minimaux, vivants et alignés sur le langage parlé. Le code reste la spécification exacte ; le reste éclaire le sens.