跳转到主要内容

《领域驱动设计》读书笔记

重读 Evans 这本书之后的笔记:真正有价值的是前四章的思维方式,而不是后面那堆模式清单。

这本书我读过三遍。第一遍在工作两年时,只记住了实体、值对象、聚合这几个名词;第二遍在做核心重构时,才发现前面几章才是重点;第三遍是带团队时读的,读出来的东西又不一样。

这本书真正的价值

大部分人把它当模式手册用,翻到"聚合"那一节抄个定义就开始设计。但 Evans 花了整本书篇幅想说的其实是一件事:软件设计的瓶颈是知识,不是技术

模型不是画出来的,是在和业务专家反复对话中"长"出来的。书里那些模式只是长出来之后用于表达的工具。工具本身不产生知识。

一个团队如果没有和业务专家持续对话的机制,那么它用不用 DDD 的模式都无所谓——反正模型里没有真正的领域知识。

我划重点的三处

第一是统一语言。 这是全书性价比最高的概念,也最容易被跳过。如果业务方说"客户"指的是签约主体,而代码里的 Customer 指的是自然人,那么所有后续设计都建立在一个错位的基础上。我们后来的做法很土:维护一份术语表,中英文对照,明确写出每个词的边界和不包含什么。上线一年下来,它减少的沟通成本比任何架构决策都多。

第二是模型驱动设计的"绑定"要求。 书里强调模型和实现必须绑死——模型改了代码就得改,代码改了模型文档也得改。做不到这一点,模型就退化成挂在墙上的装饰。这也是为什么我不再维护单独的模型图,而是让代码本身成为模型的唯一表达:

// 反例:技术化命名,业务方看不懂,术语在翻译中丢失
public class RuleProcessor {
    public BigDecimal calc(BigDecimal amt, BigDecimal r, int type) { }
}

// 正例:类名与方法名直接采用统一语言中的业务术语
// accrual(计提)不简化成 calc,basis(计息基础)不省略
public class InterestAccrualRule {
    public Money accrue(DailyBalance balance, Rate rate, DayCountBasis basis) { }
}

第三是"深层模型"和重构的关系。 书里说好模型需要经历多次突破,而突破往往来自某次对业务的重新理解。这一点我深有体会:我们的账务模型是在第三次重写时才想清楚"分录是第一公民、交易只是外壳",前两版都是围着交易类型打转。第一次就设计出好模型的期待本身就不现实。

读完之后我改了什么

  • 需求评审改成建模会。不再让业务方念文档,而是当场画概念、当场确认术语。
  • 术语表进代码仓库。放在 docs/glossary.md,跟代码一起评审,改术语要走 PR。
  • 不再追求完整套用模式。战术模式里我们只常用值对象和聚合,事件溯源、CQRS 一律不用,除非有明确的读写比例失衡问题。
  • 接受模型会被重写。第一版模型的目标是能跑并暴露问题,不是一次做对。

如果只有两小时读这本书,我建议读第一部分和第三部分的第 8 章(突破),跳过所有模式定义。模式的定义随便搜一下都有,而"如何通过对话获得领域知识"这件事,只有认真读原文才能体会到。