读书笔记:实现领域驱动设计

2021-07-241 出链

Implementing Domain-Driven Design

https://book.douban.com/subject/25844633

  • 是什么(What):
    • 一套以领域模型为核心、分战略设计(限界上下文/上下文映射)与战术设计(实体/值对象/聚合/领域事件)的软件设计方法论
  • 为什么(Why):
    • 传统开发先切数据再堆行为,业务逻辑碎片化
    • DDD 让团队先用通用语言理解业务,再以模型驱动代码,降低业务与技术的耦合
  • 怎么做(How):
    • 事件风暴协作建模 → 通用语言统一沟通 → 限界上下文划边界 → 聚合/领域事件等战术模式落地代码
    • 不该做:为分任务拆上下文、设计臃肿聚合

核心观点:

DDD 从战略和战术两个层面驱动软件设计:

  1. 战略层用通用语言、限界上下文和上下文映射划清业务边界
  2. 战术层用实体、值对象、聚合、领域事件等构建块将领域模型落地为代码,使业务模型与代码模型保持一致
  • 软件的核心复杂度在于业务本身,而非技术;应先理解业务再写代码,而非反过来
  • 限界上下文领域驱动设计最关键的模式:同一概念在不同上下文中含义不同,必须显式划定边界才能建立精确模型
  • 聚合是一致性的最小单元:一次事务只修改一个聚合,跨聚合通过领域事件实现最终一致性
  • 通用语言不是可选的文档工作,而是贯穿需求、设计、代码的统一表达,是团队协作的基础设施

启发点(关键洞察):

  1. 先有边界,后有模型:
  • 限界上下文是 DDD 最核心的战略模式。同一个词(如"订单")在不同上下文中含义不同,不划清边界就无法建立精确模型。
  1. 设计小聚合:
  • 聚合越大,并发冲突和重构成本越高
  • 应以"真正的不变条件"为一致性边界,通过唯一标识引用其他聚合,跨聚合使用最终一致性
  • 不变量就是业务对象必须永远保持的:聚合不是把相关对象放一起,而是把需要共同维护这些的对象放在一起
  1. 通用语言不是文档,而是活的代码:
  • 代码中的类名、方法名应直接反映领域概念,代码即设计、设计即沟通
  1. 领域事件是解耦利器:
  • 当"发生 A 则触发 B"时,用领域事件替代直接调用,既解耦聚合/微服务,又形成完整的业务闭环
  1. 战略设计比战术设计更重要:
  • 子域划分和上下文边界的错误,比实体建模的错误代价高得多
  • 为分配任务而拆分限界上下文是一种常见的反模式
类型 回答的问题
实体 我自身应该如何行为?
值对象 这个业务概念是什么?
领域服务 多个领域对象如何完成一个领域操作?
应用服务 一个系统用例如何被执行?
基础设施服务 技术能力如何实现?

行动:

  1. 在现有项目中识别核心域、支撑域和通用域,画出上下文映射图,审视当前服务边界是否与业务边界对齐
  2. 审查现有聚合设计:是否存在臃肿聚合?能否拆小并通过领域事件实现最终一致性?
  3. 在团队中推行通用语言,确保 PRD、代码、日常沟通使用同一套术语

金句:

  1. 领域驱动设计是教我们如何做好软件的,同时也是教我们如何更好地使用面向对象技术的。
  2. DDD 让你首先考虑的是业务语言,而不是数据。
  3. 为了分配任务而拆分限界上下文是一种错误的上下文建模方式。
  4. 在一致性边界之内建模真正的不变条件。
  1. https://martinfowler.com/tags/domain%20driven%20design.html
  2. https://deniskyashif.com/2026/07/25/modeling-facts-and-reactions-with-domain-events/

评论