Ubiquitous Language
解决什么问题:让业务和技术用同一套词说话——避免"业务说客户,代码说 User;业务说下单,代码说 CreateOrder"的翻译成本和失真。
它是什么
通用语言(Ubiquitous Language) 是 DDD 战略层的核心机制——业务团队和技术团队共享的一套词汇。这套词在 Bounded Context 内部必须完全一致:
- 业务说"客户" = 代码里就叫 Customer(不是 User / Client / CustomerInfo)
- 业务说"下单" = 代码里就叫 PlaceOrder(不是 Create / Submit / Post)
- 业务说"风控拒绝" = 代码里就叫 RiskRejected(不是 Block / Deny / Failed)
Vernon Ch 2: "The idea is that the Ubiquitous Language should be a shared, common, rigorous language used by everyone on the project, business and developers alike."
通用语言不是文档——是口头 + 代码 + 测试 + 业务沟通 全渠道共用一套词。
V2 视角(V2.7 B2 段 3 开篇定调):通用语言是 "DDD 核心是讨论" 的具体化机制——讨论必须基于一套共享词,否则讨论就变成各自诠释。
关键属性
| 属性 | 值/含义 |
|---|---|
| 范围 | 一个 Bounded Context 内部,不跨 BC |
| 形式 | 名词 + 动词 + 业务规则,全团队共用 |
| 更新 | 业务变了 → 语言变 → 代码变,三同步 |
| 载体 | 口头沟通 + 代码命名 + 测试用例 + 文档 |
| 反模式 | 业务词与技术词不一致("客户" vs "User") |
| 核心约束 | BC 内部一致,不要求跨 BC 一致(跨 BC 用 Context Map) |
| 判错标准 | 听到"业务这么说,代码那么写" = 通用语言失效 |
怎么用
场景 1:建立通用语言(项目启动)
- 业务团队 + 技术团队一起做 Event Storming——业务事件就是通用语言的"动词"
- 把所有业务事件列出来:OrderCreated / OrderPaid / OrderShipped / OrderCompleted
- 围绕事件识别"主体名词":Order / Customer / Product / Payment
- 每个名词、每个动词定一个名字——不许有两套
场景 2:BC 边界的语言冲突(最常遇到)
问题:订单 BC 里的"订单"和支付 BC 里的"订单"含义不同。
订单 BC :Order = {id, items, status, delivery}
支付 BC :Order = {id, total, paidAmount, refundable}处理:
- 不强制统一——两个 BC 各自维护自己的"Order" 概念
- 用 Context Map 标注关系(Payment BC 的 Order 是 Order BC 的 Order 的"开放主机服务")
- 通用语言只在 BC 内部有效——这是 V2 B3 段 5 改造后的"团队可拥有" 工程纪律
场景 3:业务变化时同步更新
业务说"我们以前叫'下单',现在叫'创单'了"——
- 业务事件改名:OrderCreated 不变(事件是事实)但用户操作名"创单"替代"下单"
- 代码命名同步:PlaceOrder → CreateOrder(如果项目里"创单"是新约定)
- 测试用例同步:测试方法名跟着改
- 业务沟通同步:业务团队和开发团队一起改词
V2.7 B7 视角(自然演化):通用语言必然演化——业务变了,词必须变。语言 = 业务对象的镜像。
场景 4:从代码反推通用语言
老项目里通用语言已经丢了,代码里看到 User / Customer / Client 混用——
- 盘点现有命名:搜出所有 "用户" 相关 class / table / field
- 对齐到业务:业务到底怎么叫这个对象?
- 确定唯一名字(最常用的是 Customer / Account)
- 逐步替换:从 BC 边界开始往里改,不要一次性全改(V2 B5 段 5 改造后的"SE = 编程 × 时间" 视角——这是时间维度的活)
常见误区
- "通用语言 = 文档"——错。文档没人看。通用语言在口头 + 代码 + 测试里,不在 wiki 页面
- "跨 BC 也要统一"——错。BC 内部一致即可,跨 BC 用 Context Map 翻译。强制跨 BC 统一 = 重新造成分布式单体
- "通用语言一次性建好"——错。V2 B7 段 3:"自然演化"——语言随业务演化,必然变,不要"设计完美语言"
- "业务和技术各说各的"——错。如果业务说"客户"代码叫 User,要么改名要么业务跟着改。两套词 = 翻译成本 + 失真
- "通用语言 = 业务术语翻译成技术词"——错。通用语言是业务+技术共创新词,不是"翻译"。翻译会失真,共创不会
关键洞察
通用语言是 DDD 战略层的"可执行机制"——不是"写下来的设计"
它在 Event Storming 里产生、在口头沟通里传播、在代码命名里固化、在测试用例里被验证。 判断一个 BC 的通用语言是否生效的标准 = 业务说"客户"代码也叫"客户",没有翻译层。 判断失败的标志 = 业务说 A、代码叫 B,中间靠"业务-技术翻译" 文档桥接。
相关链接
- Bounded Context——通用语言的有效范围
- Context Map——跨 BC 时怎么处理语言冲突
- [V3 涌现视域] · 认识自己——V2.7 开篇定调:"DDD 核心是讨论"
- [V3 涌现作为] · 分解——通用语言在 BC 边界内的工程纪律
- [V3 涌现之时] · 演化——通用语言的自然演化
- Aggregate——通用语言在战术层的实现