领域建模 (Domain Modeling)
概述
领域建模是 DDD 的核心实践。架构师的水平高低在很大程度上体现在领域建模水平上。
领域建模的三大目的:
- 捕捉业务知识 ——把领域专家脑中的业务规则搬到可执行的模型
- 形成统一语言 ——让业务、产品、开发、测试用同一套词汇沟通
- 沉淀领域模型 ——让业务知识随代码长存,不依赖个人
好的领域建模意味着:
- 对业务有深刻的理解
- 能洞察问题本质
- 产出的模型稳定可演进
- 业务方能读懂并认可
领域建模的七大交付物
文章强调领域建模产出的是一整套"交付物",不仅是领域模型本身:
┌───────────────────────────────────────────────────────────────┐
│ 领域建模交付物 │
├───────────────────────────────────────────────────────────────┤
│ │
│ ★ 领域模型 (Domain Model) ── 最重要的产出 │
│ └ 领域对象 / 属性 / 关系 / 行为 / 边界 │
│ │
│ ▸ 用例图 (Use Case Diagram) ── 明确系统功能 │
│ ▸ 数据模型 (Data Model) ── ER 图 / 关系数据库模型 │
│ ▸ 状态图 (State Diagram) ── 实体生命周期 │
│ ▸ 活动图 (Activity Diagram) ── 业务流程 / 泳道图 │
│ ▸ 序列图 (Sequence Diagram) ── 对象交互 / 消息传递 │
│ ▸ 架构模型 (Architecture Model) ── 组件 / 模块 / 接口 │
│ │
└───────────────────────────────────────────────────────────────┘
关键理念:
- 领域模型永远是核心,其他图都是辅助
- ER 图的位置最低:仓储实施细节,只在领域建模完成后才画
- 不是所有项目都需要 7 种图,按需产出
建模方法论全景
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 领域建模方法 │
│ │
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
│ │ [事件风暴建模] │ │ [四色建模法] │ │
│ │ │ │ │ │
│ │ ▸ 互动式工作坊 │ │ ▸ 强分析推导 │ │
│ │ ▸ 发散 - 收敛 │ │ ▸ 从现金流 / KPI 出发 │ │
│ │ ▸ 依赖主持人 │ │ ▸ 可独立完成 │ │
│ │ ▸ 快速对齐共识 │ │ ▸ 结果稳定 │ │
│ │ │ │ │ │
│ │ 适合:业务不清、需共识 │ │ 适合:业务稳定、长期建模 │ │
│ └──────────────────────────┘ └──────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
| 维度 | 事件风暴 | 四色建模 |
|---|---|---|
| 驱动方式 | 发散 - 收敛 | 链式推导 |
| 核心线索 | 头脑风暴找事件 | 现金流 / KPI 为起点 |
| 人员规模 | 多角色工作坊(5-15 人) | 架构师 + 少量业务(2-5 人) |
| 产出稳定性 | 依赖主持人 | 逻辑严谨可复现 |
| 适用阶段 | 业务不明朗 | 业务稳定 |
| 学习曲线 | 低 | 较高 |
| 典型时间 | 半天到 1 天 | 数天到 1 周 |
最佳实践:二者可结合使用 ——先用事件风暴对齐共识,再用四色建模做严谨收敛。
通用的领域建模六步法
不论采用哪种方法,建模过程都可以归纳为六步:
Step 1 理解业务
├─ 与领域专家深度沟通
├─ 了解业务流程、规则、异常
└─ 收集业务愿景
Step 2 识别核心概念
├─ 名词 → 候选实体 / 值对象
├─ 动词 → 候选行为
└─ 用通用语言描述
Step 3 确定业务边界
├─ 识别子域
├─ 划分限界上下文
└─ 每个上下文内独立建模
Step 4 选择建模方法
├─ 事件风暴(共识优先)
├─ 四色建模(稳定性优先)
└─ 或结合使用
Step 5 产出建模交付物
├─ 领域模型(核心)
├─ 用例图、状态机、活动图等(按需)
└─ 架构模型
Step 6 验证与迭代
├─ 业务方角色扮演验证
├─ 覆盖异常流程
└─ 持续重构模型
建模交付物详解
1. 领域模型(最重要)
关注点:领域对象、属性、关系、行为、边界
示例(RabbitAdvisors 订阅上下文):
Reader ───(订阅)──▶ Subscription ◀──(权利来自)── Payment
│ │ ▲
│ │ (针对) │
│ ▼ │
└──(下单)──▶ Order ──(由...支付)─────────────────┘
│
│ (订阅)
▼
Column
2. 用例图(明确功能)
RabbitAdvisors
┌──────────────────┐
│ │
┌─Reader──────▶│ (浏览专栏) │
│ │ (订阅专栏) │
│ │ (阅读内容) │
│ │ (查看订阅) │
│ │ │
├─Editor──────▶│ (创建专栏) │
│ │ (修改报价) │
│ │ │
└─Author──────▶│ (查看分成) │
│ (签订合同) │
└──────────────────┘
3. 状态机(刻画生命周期)
Subscription 状态机:
[ 无 ] ──create──▶ [ ACTIVE ] ──cancel──▶ [ CANCELLED ]
│
│ expire
▼
[ EXPIRED ]
4. 活动图(描述流程,泳道图)
读者泳道 订单系统泳道 金融系统泳道 订阅系统泳道
│ │ │ │
点击订阅 ──▶ 创建订单 ──▶ 发起支付 ──▶ 扣款成功 ──▶ 创建订阅
│ │ │ │
等待 等待支付 扣款结果 持久化
5. 序列图(对象交互)
Reader Facade AppService DomainSvc Repo PaymentClient
│ │ │ │ │ │
│─订阅─▶│ │ │ │ │
│ │─subscribe▶│ │ │ │
│ │ │─subscribe▶│ │ │
│ │ │ │─创建订单 │ │
│ │ │ │─────发起支付────▶ │
│ │ │ │◀─────支付回执─────│
│ │ │ │─持久化 ─▶│ │
│ │ │◀─────────│ │ │
│ │◀─────────│ │ │ │
│◀─────│ │ │ │ │
6. ER 图(数据库建模,最后画)
t_subscription (id, reader_id, column_id, start_time, end_time, status)
t_order (id, reader_id, column_id, amount, status, created_at)
t_payment (id, order_id, amount, paid_at, status)
重要:在 DDD 中,ER 图只是仓储实施细节,只在领域建模完成后才画。对于习惯面向数据库编程的工程师,这是最大的思维转变。
领域建模的关键原则
1. 业务驱动,不是技术驱动
❌ 先设计数据库表,再套 ORM
✅ 先建领域模型,ER 图是仓储实现细节
2. 边界先行
❌ 所有实体画一张大图
✅ 在单一限界上下文内建模,上下文间通过事件 / ACL 通信
3. 反复精化
❌ 一次建模一步到位
✅ 随业务理解加深持续重构模型
4. 验证模型
❌ 建完直接交付开发
✅ 让业务方"角色扮演"验证模型能覆盖实际经营
5. 模型先于代码
❌ 边写代码边想业务
✅ 模型对齐后再编码,编码反过来检验模型
建模常见困境及对策
困境:业务方表达混乱,抓不住核心
对策:用事件风暴的"橙色贴纸"捕捉事件,事件是最客观的事实
困境:业务方总讲 Happy Path
对策:主持人主动追问"会失败吗?失败怎么办?"
困境:开发想先动手写代码
对策:建模不到位就写代码 = 技术债;先建模后编码
困境:模型演进成本高
对策:用充血模型 + 工厂 + 仓储抽象让模型独立于技术
困境:跨团队/上下文分歧大
对策:明确上下文边界,同一词在不同上下文可以不同含义
何时做领域建模
✅ 必做:
▸ 核心域的初次建模
▸ 核心域的重大业务变更
▸ 限界上下文边界调整
▸ 新功能涉及多个聚合的复杂流程
⚪ 可做:
▸ 支撑域的建模
▸ 已有系统的重构前
❌ 可不做:
▸ 通用域(认证、日志、通知)
▸ 简单 CRUD
▸ 工具类 / 一次性脚本
领域建模的成熟度路径
L1 能用 DDD 术语(名词派)
└─ 会说"聚合"、"实体"、"值对象"
L2 能套用 DDD 模板(形式派)
└─ 代码目录分了层,类名带了后缀
L3 能用充血模型建模(战术派)
└─ 业务逻辑回归领域对象,聚合有边界
L4 能划分限界上下文(战略派)
└─ 多团队协作时能画出合理的上下文地图
L5 能用领域建模驱动业务讨论(业务派)
└─ 模型直接成为统一语言,业务方能参与
L6 能识别核心域,合理投资(决策派)
└─ 什么地方投大资源,什么地方买现成方案
常见误区
❌ 把 UML 画图当成建模目标——产出一堆精致的类图 / 时序图,但业务方看不懂、开发也不照着写 → 建模的产物是业务专家与开发的共同理解,图只是载体;图越多 ≠ 建得越好
❌ 数据库表先行——先设计表结构再"反推"领域模型,模型沦为 ORM 字段的镜像 → 先建领域模型,ER 图是仓储实施细节;让业务概念驱动表结构,而不是反过来
❌ 建模一步到位、锁死不允许演进——大型工作坊产出"完美模型"后就冻结,半年后无人维护 → 模型必须随业务理解加深而精化;建模是持续的实践,不是一次性活动
与其他 DDD 概念的关系
| 概念 | 关系 |
|---|---|
| 战略设计 | 建模的上游,提供边界 |
| 战术设计 | 建模的下游,把模型变代码 |
| 事件风暴 | 一种具体的建模方法 |
| 四色建模 | 另一种具体的建模方法 |
| 通用语言 | 建模过程中共同产出 |
| 领域模型 | 建模的核心产出物 |
| 限界上下文 | 建模的边界约束 |
| RabbitAdvisors 案例 | 完整建模案例 |
总结
核心:领域建模是把业务知识变成可执行、可演进、可沟通的领域模型的过程。
三个目的:捕捉业务知识、形成统一语言、沉淀领域模型。
七大交付物:领域模型(最重要) + 用例图、数据模型、状态图、活动图、序列图、架构模型。
两大方法:事件风暴(发散共识)+ 四色建模(强分析稳定),可结合使用。
精髓:
- 业务驱动,不是技术驱动
- 边界先行,避免大一统模型
- 反复精化,让模型伴随业务演进
- 建模能力 > 方法论套用 —— 深刻理解业务才是关键