领域驱动设计
从业务语言和领域规则出发,用实体、值对象、聚合与上下文边界组织代码,并用可复现的实验检验每一个边界是否守得住。
从哪里开始
先读设计专题里的 从统一语言到限界上下文,它讲清了子域、限界上下文和防腐层。然后按顺序读本专题:事件风暴 和 领域建模 把业务讨论变成规则和模型;实体与值对象、聚合边界 和 分层 把模型放进代码;边界不止一个、持久化 和 上下文集成 处理模型与数据库、与其他上下文、与部署单元的关系;CQRS 按需阅读;最后在 精益切片与遗留改造 里看怎样在真实项目里开始。
这个专题讲什么
很多项目说自己用了 DDD,证据是目录里有 domain、application、infrastructure,类名里有 Repository 和 AggregateRoot。顺着一个需求走下去,业务规则仍然散在控制器、服务、SQL 和定时任务里;同一个词在不同团队含义不同;表结构一改,领域对象跟着改;并发一来,规则被绕开。
这个专题关心的是知识进入代码的路径:业务人员和开发人员先用同一套语言描述问题,再把必须同时成立的规则放进明确的边界,最后用测试、事务和架构规则证明这些边界没有被绕过。分层、仓储、领域事件和 CQRS 都是可选的手段;统一语言、边界和规则的一致性才是主线。
统一案例
所有文章使用同一个虚构的活动报名平台,每篇只截取其中一个问题:
| 上下文 | 负责什么 | 核心概念 |
|---|---|---|
| 活动 | 发布活动和场次,设定容量 | 活动、场次、容量 |
| 报名 | 报名、候补、取消与递补 | 场次聚合、报名、候补、参会人 |
| 计费 | 应收、退款 | 应收、付款人、金额 |
| 通知 | 模板、渠道、投递 | 通知、投递记录 |
报名是核心域,其余三个是支撑域或通用域。各篇的实验都在 codesphere-labs/ddd 中,可以用 make verify 复现。
什么时候不需要
以增删改查为主、规则很少、上线后很少变化的模块,简单的分层和事务脚本就够了。DDD 的结构用来管理复杂性,复杂性不在那里时,结构本身就是负担。
文章
01事件风暴从过去式的事件反推命令、执行者与策略,把热点定成规则;初稿模型漏掉的规则让 3 个验收测试失败→02领域建模名词搬运模型缺了什么:用业务问题确认约束、把操作放进模型、分类先看规则,词汇表与规则表可追踪→03实体与值对象按身份还是按值相等;BigDecimal 精度、record 浅不可变、保存时才分配 id 的实测问题→04聚合边界不变量决定边界:候补拆成独立聚合后新报名全部插队,以活动为根的锁等待是以场次为根的十几倍→05分层、应用服务与仓储一条用例穿过四层的实际顺序,规则放在哪里,对象转换的往返检查,把依赖方向写成测试→06DDD 的边界不止一个六种边界与模块化单体;拆出通知服务后停机、超时与重复带来的新失败,以及拆分的证据→07持久化与重建重建不是创建、版本号冲突、子表按差异保存,三种继承映射的执行计划、空间与约束→08上下文集成契约与防腐层,双写丢失与 Outbox,重复投递、乱序与毒消息的实测处理→09CQRS 不是两套系统从查询不走仓储到同步、异步读模型:同一看板 84.9ms、31.4ms 与 1.4ms,投影暂停与重放→10精益切片与遗留改造值不值得、第一个切片怎么选;字符化测试与影子比对找出两条隐含规则,按比例分流与回滚→
相关专题
- 设计原则与模式 — 关注点分离、封装与组合、状态机与事件,是本专题的基础
- Domain Driven Kit — 一个按四层结构组织的实现,文中多处与它的当前能力对照
- 分布式与高并发 — 跨库查询、订单一致性等与上下文拆分相关的问题