3、领域驱动设计(DDD)核心概念速览:实体、值对象、聚合、领域服务、领域事件、限界上下文

在进入订单系统微服务拆分实战之前,必须统一团队对 DDD 核心战术要素的认知。这些要素是构建领域模型的基本“积木”,也是后续划定微服务边界、设计聚合根、实现领域逻辑的语法基础。本节以订单系统为贯穿案例,逐一速览六大核心概念。

3.1 实体(Entity)

实体是具有唯一标识且会持续变化的对象。在订单系统中,订单(Order) 是最典型的实体——每个订单拥有唯一的订单号(ID),其状态、金额、地址等属性会随业务流转而改变。实体的核心特征:

  • 身份标识:通过 ID 区分两个属性完全相同的对象。
  • 可变性:属性可以修改,但标识不变。
  • 生命周期:从创建到归档,实体始终存在。
订单系统案例: 订单实体包含 orderId、customerId、orderItems、totalAmount、status、createdAt 等属性。即使订单状态从“待支付”变为“已支付”,它仍然是同一个订单。

3.2 值对象(Value Object)

值对象通过属性值来定义自身,没有唯一标识,且通常是不可变的。在订单系统中,地址(Address)、货币金额(Money) 是典型的值对象。两个地址如果省/市/区/街道完全相同,则视为同一个地址。

对比维度 实体(Entity) 值对象(Value Object)
标识 有唯一 ID 无 ID,靠属性值相等
可变性 可变 不可变(推荐)
生命周期 独立生命周期 依附于实体
相等判断 ID 相等 所有属性相等
订单案例 Order, Customer, Product Address, Money, OrderItem(无独立标识时)

3.3 聚合(Aggregate)

聚合是一组相关对象的集合,由聚合根(Aggregate Root)作为外部访问的唯一入口。聚合保证了内部数据的一致性和不变性。在订单系统中,订单聚合以 Order 为聚合根,内部包含 OrderItem 列表、ShippingAddress 值对象、PaymentInfo 值对象等。

订单聚合结构示例 Order(聚合根) OrderItem(实体) OrderItem(实体) OrderItem(实体) ShippingAddress(值对象) PaymentInfo(值对象) Money(值对象) 聚合边界:外部只能通过 Order 聚合根访问内部对象 聚合根 Order 负责维护内部所有对象的一致性 删除 Order 时,级联删除所有 OrderItem
设计原则: 聚合内部通过聚合根保证事务一致性;聚合之间通过最终一致性通信。在微服务拆分时,一个聚合通常对应一个微服务内的一个限界上下文。

3.4 领域服务(Domain Service)

当某个业务逻辑无法自然地归属于某个实体或值对象时,应将其建模为领域服务。领域服务是无状态的,它协调多个领域对象完成一个业务操作。在订单系统中,订单价格计算服务(OrderPricingService) 就是一个典型的领域服务——它需要读取商品价格、应用折扣策略、计算税费,最终得出订单总金额。

// Go 语言示例:领域服务接口
type OrderPricingService interface {
    CalculateTotal(order *Order, discountPolicy DiscountPolicy) (Money, error)
}

// 实现:协调 Order、OrderItem、DiscountPolicy 等对象
type orderPricingService struct {
    productRepo ProductRepository
    taxService  TaxService
}

func (s *orderPricingService) CalculateTotal(order *Order, policy DiscountPolicy) (Money, error) {
    // 1. 计算商品小计
    subtotal := s.calculateSubtotal(order.Items)
    // 2. 应用折扣
    discounted := policy.Apply(subtotal)
    // 3. 计算税费
    tax := s.taxService.CalculateTax(discounted, order.ShippingAddress)
    // 4. 返回总金额
    return discounted.Add(tax), nil
}

3.5 领域事件(Domain Event)

领域事件表示领域中发生的、对业务有意义的事实。它通常以过去时命名,如 OrderPlaced、PaymentReceived。领域事件用于实现聚合之间的松耦合通信,也是微服务间异步协作的核心机制。

领域事件 触发时机 典型消费者
OrderPlaced 用户提交订单后 库存服务、支付服务、通知服务
PaymentReceived 支付成功回调后 订单服务(更新状态)、物流服务
OrderShipped 仓库发货后 通知服务、用户积分服务
OrderCancelled 用户取消或超时取消 库存服务(释放库存)、支付服务(退款)
实践注意: 领域事件应包含足够的数据(事件载荷),使消费者无需回查源聚合即可完成业务处理。例如 OrderPlaced 事件应包含 orderId、customerId、items 列表、总金额等。

3.6 限界上下文(Bounded Context)

限界上下文是 DDD 中最核心的战略设计概念。它定义了模型边界——在一个限界上下文内部,领域模型是统一、自洽的;不同限界上下文之间通过上下文映射(Context Map) 进行集成。在订单系统中,典型的限界上下文包括:

  • 订单上下文(Order Context):负责订单创建、状态流转、订单查询。
  • 库存上下文(Inventory Context):负责库存扣减、库存预警。
  • 支付上下文(Payment Context):负责支付请求、支付回调、退款。
  • 物流上下文(Logistics Context):负责发货、配送、签收。
订单系统限界上下文与上下文映射 订单上下文 Order OrderItem OrderPricingService 库存上下文 Product Inventory StockReservationService 支付上下文 Payment Transaction PaymentGateway 物流上下文 Shipment Tracking DeliveryService OrderPlaced PaymentReceived OrderShipped 每个限界上下文拥有独立的领域模型、数据库和微服务部署单元

3.7 概念关系总结

六大核心概念在 DDD 实践中形成清晰的层次关系:

  1. 限界上下文 是最高层级的战略边界,每个上下文内部拥有独立的领域模型。
  2. 聚合 是模型内部的数据一致性边界,聚合根 是外部访问的唯一入口。
  3. 实体 和 值对象 是聚合内的基本构造单元。
  4. 领域服务 编排实体和值对象完成跨对象的业务逻辑。
  5. 领域事件 实现聚合之间、限界上下文之间的异步通信。