2. 领域驱动设计基础:DDD核心概念与战略/战术设计概览

领域驱动设计(Domain-Driven Design,DDD)是一套应对复杂软件系统建模的方法论。它强调以业务领域为核心,通过统一语言(Ubiquitous Language)连接业务专家与技术团队,从而指导服务边界划分与接口设计。本章将系统梳理DDD的核心构造块,并区分战略设计与战术设计两个层次。

2.1 核心构造块:实体、值对象、聚合

DDD将模型元素分为若干基础模式,其中实体(Entity)、值对象(Value Object)和聚合(Aggregate)是最关键的三个构造块。

概念 定义 标识特征 典型示例
实体 具有唯一标识、生命周期可追踪的对象 拥有ID,属性可变但身份不变 用户(userId)、订单(orderId)
值对象 描述某种属性或状态,无唯一标识 不可变,通过属性值比较相等 地址(城市+街道+邮编)、金额(货币+数值)
聚合 一组相关对象的集群,外部只能通过聚合根访问 有聚合根(一个实体),保证内部一致性 订单聚合(订单实体+订单项值对象+收货地址值对象)
设计提示:在API接口映射时,实体通常对应资源路径中的主资源(如 /users/{id}),值对象适合作为请求/响应体中的嵌套属性,聚合则决定了事务边界与数据一致性范围。

2.2 领域服务与领域事件

当某个业务操作无法自然地归属于某个实体或值对象时,应引入领域服务(Domain Service)。领域服务是无状态的,它协调多个聚合或外部资源完成一个业务用例。例如:TransferService.transfer(fromAccount, toAccount, amount)。

领域事件(Domain Event)用于记录领域中发生的、业务人员关心的状态变化。它是实现事件驱动架构和最终一致性的关键。每个领域事件通常包含事件ID、发生时间、事件数据和版本号。

// 领域事件示例(Java风格)
public class OrderSubmittedEvent implements DomainEvent {
    private final String eventId;
    private final String orderId;
    private final LocalDateTime occurredOn;
    private final OrderSnapshot orderData;

    // 构造函数、getters省略
}
API映射建议:领域事件可以直接映射为异步消息(如Kafka、RabbitMQ)或Webhook回调的载荷结构。事件名称应使用过去时态动词,例如 OrderSubmitted、PaymentCompleted。

2.3 战略设计与战术设计概览

DDD将设计活动分为两个层次:战略设计关注宏观的限界上下文(Bounded Context)划分与上下文映射关系;战术设计关注微观的聚合、实体、值对象等构造块的具体实现。

下图展示了战略设计与战术设计在DDD整体流程中的位置与关系:

DDD 设计层次概览 战略设计 (宏观:业务边界与集成) 限界上下文 Bounded Context 上下文映射 Context Map 统一语言 Ubiquitous Language 输出:服务边界、集成模式、API分组 战术设计 (微观:模型实现与接口) 实体 + 值对象 聚合 + 聚合根 领域服务 领域事件 输出:接口契约、数据模型、事务边界 指导

2.4 战略设计:限界上下文与上下文映射

限界上下文是DDD中最关键的边界概念。它定义了模型应用的显式范围,每个限界上下文内部有独立的统一语言和模型实现。不同上下文之间通过上下文映射建立集成关系,常见的映射模式包括:

  • 合作关系(Partnership):两个上下文紧密协作,同步演进。
  • 共享内核(Shared Kernel):共享部分模型代码,但保持各自边界。
  • 客户-供应商(Customer-Supplier):上游(供应商)决定模型,下游(客户)适配。
  • 防腐层(Anti-Corruption Layer):下游通过转换层隔离上游模型的污染。
  • 开放主机服务(Open Host Service):上游以API形式暴露服务,下游通过发布语言(Published Language)调用。
常见误区:不要将限界上下文等同于微服务。一个限界上下文可以拆分为多个微服务,也可能多个上下文合并为一个服务。API设计治理的目标是让接口边界与限界上下文对齐,而非机械地一对一映射。

2.5 战术设计:聚合与事务边界

战术设计的核心是聚合设计。聚合通过聚合根(Aggregate Root)保证内部对象的一致性,外部只能通过聚合根的方法修改聚合内部状态。设计聚合时应遵循以下原则:

  1. 小聚合原则:只包含真正需要一致性的对象,避免加载过多数据。
  2. 通过聚合根访问:禁止外部直接修改聚合内部实体或值对象。
  3. 一次事务只修改一个聚合:跨聚合的修改应通过领域事件实现最终一致性。

下图展示了一个典型的订单聚合结构及其对外接口映射关系:

订单聚合结构与API映射 聚合边界(事务一致性) Order(聚合根) orderId, status, totalAmount OrderItem productId, quantity ShippingAddress city, street, zip API 接口映射 POST /orders 创建订单(聚合根操作) GET /orders/{id} 查询订单(返回聚合快照) PATCH /orders/{id}/status 修改状态(聚合根方法) 事件:OrderSubmitted 异步通知下游上下文 映射

2.6 从DDD到API设计治理的桥梁

DDD为API设计治理提供了清晰的决策依据:

  • 限界上下文决定API分组与微服务边界。
  • 聚合根决定资源路径的根节点与事务边界。
  • 值对象决定请求/响应体中的嵌套结构。
  • 领域服务决定无状态操作接口(如POST /transfers)。
  • 领域事件决定异步消息契约与Webhook格式。
核心原则:API接口是领域模型的投影,而非数据库表的直接暴露。先做领域建模,再做接口设计;先划清业务边界,再定义服务契约。