读书笔记:实现领域驱动设计
Implementing Domain-Driven Design
- 是什么(What):
- 一套以领域模型为核心、分战略设计(限界上下文/上下文映射)与战术设计(实体/值对象/聚合/领域事件)的软件设计方法论
- 为什么(Why):
- 传统开发先切数据再堆行为,业务逻辑碎片化
- DDD 让团队先用通用语言理解业务,再以模型驱动代码,降低业务与技术的耦合
- 怎么做(How):
- 事件风暴协作建模 → 通用语言统一沟通 → 限界上下文划边界 → 聚合/领域事件等战术模式落地代码
- 不该做:为分任务拆上下文、设计臃肿聚合
核心观点:
DDD 从战略和战术两个层面驱动软件设计:
- 战略层用通用语言、限界上下文和上下文映射划清业务边界
- 战术层用实体、值对象、聚合、领域事件等构建块将领域模型落地为代码,使业务模型与代码模型保持一致
- 软件的核心复杂度在于业务本身,而非技术;应先理解业务再写代码,而非反过来
限界上下文是领域驱动设计最关键的模式:同一概念在不同上下文中含义不同,必须显式划定边界才能建立精确模型聚合是一致性的最小单元:一次事务只修改一个聚合,跨聚合通过领域事件实现最终一致性- 通用语言不是可选的文档工作,而是贯穿需求、设计、代码的统一表达,是团队协作的基础设施
启发点(关键洞察):
- 先有边界,后有模型:
- 限界上下文是 DDD 最核心的战略模式。同一个词(如"订单")在不同上下文中含义不同,不划清边界就无法建立精确模型。
- 设计小聚合:
- 聚合越大,并发冲突和重构成本越高
- 应以"真正的不变条件"为一致性边界,通过唯一标识引用其他聚合,跨聚合使用最终一致性
- 不变量就是业务对象必须永远保持的
真:聚合不是把相关对象放一起,而是把需要共同维护这些真的对象放在一起
- 通用语言不是文档,而是活的代码:
- 代码中的类名、方法名应直接反映领域概念,代码即设计、设计即沟通
- 领域事件是解耦利器:
- 当"发生 A 则触发 B"时,用领域事件替代直接调用,既解耦聚合/微服务,又形成完整的业务闭环
- 战略设计比战术设计更重要:
- 子域划分和上下文边界的错误,比实体建模的错误代价高得多
- 为分配任务而拆分限界上下文是一种常见的反模式
| 类型 | 回答的问题 |
|---|---|
| 实体 | 我自身应该如何行为? |
| 值对象 | 这个业务概念是什么? |
| 领域服务 | 多个领域对象如何完成一个领域操作? |
| 应用服务 | 一个系统用例如何被执行? |
| 基础设施服务 | 技术能力如何实现? |
行动:
- 在现有项目中识别核心域、支撑域和通用域,画出上下文映射图,审视当前服务边界是否与业务边界对齐
- 审查现有聚合设计:是否存在臃肿聚合?能否拆小并通过领域事件实现最终一致性?
- 在团队中推行通用语言,确保 PRD、代码、日常沟通使用同一套术语
金句:
- 领域驱动设计是教我们如何做好软件的,同时也是教我们如何更好地使用面向对象技术的。
- DDD 让你首先考虑的是业务语言,而不是数据。
- 为了分配任务而拆分限界上下文是一种错误的上下文建模方式。
- 在一致性边界之内建模真正的不变条件。
评论