学习领域驱动设计

Learning Domain-Driven Design (Vlad Khononov 著)
互动式全书精华摘要 · 4大模块 · 16章精讲
"在我们就问题达成一致之前谈论解决方案是没有意义的。" — Efrat Goldratt-Ashlag
第1章分析业务领域

DDD 的首要任务是理解问题空间 (Problem Space)。并非所有代码都同等重要,需将业务拆解为子域 (Subdomains)

💎

核心子域 (Core)

最高优先级 点击翻转
企业的核心竞争力

• 独特性:区别于竞争对手的关键。
• 复杂度高:包含最复杂的业务逻辑。
• 策略:必须内部开发,投入最优秀的资源。

📦

通用子域 (Generic)

购买/外购
行业标准功能

• 普遍性:所有公司都在做(如认证、发票)。
• 复杂度高:虽然复杂但不带来竞争优势。
• 策略:购买SaaS或使用开源,避免自研。

🏗️

支撑子域 (Supporting)

外包/初级
必要的辅助功能

• 辅助性:支持核心业务运行。
• 复杂度低:通常是CRUD操作。
• 策略:外包或由初级工程师开发。

第2章发现领域知识
核心概念:通用语言 (Ubiquitous Language)
  • 定义: 团队成员(领域专家、开发者、测试等)共同使用的、严格的、无歧义的语言。
  • 目的: 消除沟通中的“翻译”成本。
  • 范围: 存在于对话、文档、图表,最重要的是——代码中。
  • 原则: 一个术语在同一个上下文中有且仅有一个含义。
第3 & 4章限界上下文与集成

限界上下文 (Bounded Context) 是语义和模型的边界,属于解决方案空间 (Solution Space)

🧩

合作关系

Partnership / Shared Kernel
紧密协作

Partnership: 两个团队荣辱与共,同步部署。
Shared Kernel: 共享一部分代码或模型库(需谨慎,易导致耦合)。

🛡️

单向关系

Customer-Supplier
上下游关系

Conformist: 下游无条件遵从上游模型。
ACL (防腐层): 下游建立翻译层,隔离上游模型污染。
OHS (开放主机服务): 上游提供标准公共协议。

"业务逻辑是软件的心脏。战术设计提供了实现它的工具。"
第5-7章业务逻辑实现模式

根据子域的复杂度选择合适的实现模式,不要过度设计。

简单逻辑模式

Transaction Script / Active Record

适用: 支撑子域或通用子域。

  • 事务脚本: 过程式代码,直观,适合ETL。
  • 活动记录: 对象封装数据和数据库访问,适合简单的CRUD。

领域模型 (Domain Model)

应对复杂核心子域

核心构建块:

  • 值对象: 不可变,由属性定义,无ID。
  • 实体: 有ID,注重生命周期。
  • 聚合: 一致性边界,通过聚合根访问。

事件溯源 (Event Sourcing)

时间维度的建模

核心思想: 不存储当前状态,而是存储导致状态变化的一系列事件

优势: 审计日志、时间旅行、深层分析。

适用: 金融、法律等高价值核心子域。

第8-9章架构与通信
三种核心架构模式
  1. 分层架构 (Layered): 传统的 UI -> BLL -> DAL。容易导致依赖数据库。
  2. 端口与适配器 (Ports & Adapters / Hexagonal): 业务逻辑位于中心,依赖倒置。适合实现领域模型。
  3. CQRS (命令查询职责分离): 读写分离。写模型负责业务一致性,读模型负责高效查询。

跨组件通信模式
  • Outbox 模式: 解决“保存数据”和“发送消息”的原子性问题。
  • Saga: 管理跨服务的长事务,通过编排或协同实现最终一致性。
  • Process Manager: 具有状态的中心化流程管理器,用于复杂流程编排。
第10章设计启发式 (Heuristics)

如何根据上下文做决策?这里有一个简单的决策逻辑:

  • 涉及金钱或需要通过时间回溯进行审计? 👉 事件溯源领域模型
  • 核心子域,逻辑复杂? 👉 领域模型 (Domain Model)
  • 支撑子域,数据结构复杂? 👉 活动记录 (Active Record)
  • 逻辑简单? 👉 事务脚本 (Transaction Script)
第11章演进设计

业务是动态的,子域类型会随时间变化。例如,支撑子域可能随着业务发展变成核心子域(需要重构),核心子域可能因为出现通用解决方案变成通用子域(购买替换自研)。架构必须支持这种演进。

第12章事件风暴 (EventStorming)

一种快速发现领域知识、建立通用语言的协作工作坊。

🌪️

核心要素

  • 领域事件 (橙色): 过去发生的事实。
  • 命令 (蓝色): 触发事件的动作。
  • 角色 (黄色): 执行命令的人。
  • 聚合 (大黄): 接受命令并产生事件的逻辑单元。
第13章现实世界中的 DDD

在遗留系统(Brownfield)中落地 DDD 的策略:

  • 从战略设计切入: 首先理清子域和上下文。
  • 绞杀者模式 (Strangler Fig): 不要推倒重来。在旧系统旁构建新功能,逐步拦截流量,直至旧系统消亡。
  • 务实至上: 仅在核心子域投入最大的重构精力。
"微服务是限界上下文的一种物理边界表现形式,但两者并不等同。"
第14章微服务

误区: 微服务 = 限界上下文。

正解: 限界上下文是逻辑边界,微服务是物理边界。

  • 限界上下文 > 微服务:一个上下文可能包含多个服务。
  • 最佳实践: 将微服务边界与子域对齐,构建“深度模块”(接口简单,功能强大)。
第15章事件驱动架构 (EDA)

系统间通信的三种关键事件类型:

1. 事件通知

Notification

特点: 极简,仅包含ID或链接。
目的: 告诉外界“有事发生了”。
耦合度: 极低。

2. 事件携带状态转移

ECST

特点: 包含变更后的完整数据快照。
目的: 消费者可更新本地缓存,无需反查。
耦合度: 中等(数据模式耦合)。

3. 领域事件

Domain Event

特点: 完整描述业务生命周期中的变化。
目的: 建模业务意图。
注意: 尽量不要直接对外暴露内部领域事件,应转换为公有事件。

第16章数据网格 (Data Mesh)

将 DDD 原则应用于分析数据 (OLAP) 领域:

  • 去中心化: 数据的所有权归属于生成数据的领域团队(限界上下文)。
  • 数据即产品: 将分析数据视为一种对外提供的产品,保证质量、文档和 SLA。
  • 结合 CQRS: 利用 CQRS 的读模型来生成数据产品。

原文

源链接