2. 领域驱动设计(DDD)基础回顾:实体、值对象、聚合、聚合根、领域事件、限界上下文

在深入支付订单系统的聚合建模之前,必须重新梳理领域驱动设计的核心战术构件。这些概念不仅是理论标签,更是指导代码结构与业务边界划分的实操工具。本章将结合支付场景,逐一拆解六大核心要素。

2.1 实体(Entity)与值对象(Value Object)

实体拥有唯一的身份标识(ID),其状态会随时间变化,但标识保持不变。在支付系统中,Order、Payment、Account 都是典型的实体。

值对象没有身份标识,通过其属性值来定义相等性,且通常是不可变的。例如:Money、Address、PaymentMethod。

维度 实体(Entity) 值对象(Value Object)
身份标识 有(如 orderId) 无
可变性 可变(状态可更新) 不可变(替换而非修改)
相等性判断 通过 ID 判断 通过所有属性值判断
支付示例 订单、支付单、商户 金额、币种、支付渠道编码
实践建议:在支付订单模型中,将 Money 设计为值对象,包含 amount 和 currency 两个属性,避免直接使用基本类型 BigDecimal 导致语义丢失。

2.2 聚合(Aggregate)与聚合根(Aggregate Root)

聚合是一组相关对象的集合,被视为数据修改的原子单元。外部对象只能引用聚合根,不能直接操作聚合内部的实体或值对象。聚合根是聚合中唯一允许被外部访问的实体,负责维护聚合内部的不变规则。

在支付订单系统中,一个典型的聚合是 订单聚合:

  • 聚合根:Order(订单实体)
  • 内部实体:OrderItem(订单项,有行号标识)
  • 值对象:Money(金额)、ShippingAddress(收货地址)
常见误区:将数据库的外键关联直接映射为聚合间的引用。正确的做法是聚合根之间通过全局唯一标识(ID)引用,而非对象引用,以保证聚合边界的独立性。
订单聚合结构示例 Order(聚合根) OrderItem(内部实体) OrderItem(内部实体) Money(值对象) ShippingAddress(值对象) 聚合边界 外部服务 仅通过聚合根 ID 引用

2.3 领域事件(Domain Event)

领域事件是领域中发生的、业务人员关心的、具有业务意义的事件。它用于在聚合之间或限界上下文之间传递状态变更通知,实现最终一致性。

支付系统中的典型领域事件:

  • OrderPlaced(订单已提交)
  • PaymentCompleted(支付已完成)
  • PaymentFailed(支付失败)
  • OrderShipped(订单已发货)
关键原则:领域事件是不可变的,通常使用过去时态命名(如 PaymentSucceeded),并包含事件发生时的上下文数据(如订单ID、金额、时间戳)。

2.4 限界上下文(Bounded Context)

限界上下文是 DDD 中最宏观的战略设计工具。它定义了模型应用的边界,每个上下文内部有统一的语言(Ubiquitous Language),且模型的含义在该边界内是自洽的。

在支付系统中,典型的限界上下文划分:

限界上下文 核心职责 聚合根示例
订单上下文 订单创建、商品管理、状态流转 Order
支付上下文 支付请求、渠道路由、对账 Payment
账户上下文 余额管理、资金流水、结算 Account
风控上下文 交易检测、规则引擎、黑白名单 RiskAssessment
支付系统限界上下文与事件协作 订单上下文 Order 聚合根 OrderItem 实体 支付上下文 Payment 聚合根 PaymentMethod 值对象 账户上下文 Account 聚合根 Ledger 实体 OrderPlaced PaymentCompleted 限界上下文协作规则 上下文之间通过领域事件或 API 通信,不共享数据库,不直接引用对方内部实体。

2.5 战术设计总结

在支付订单系统的建模过程中,DDD 的战术构件提供了清晰的职责划分:

  • 实体负责有身份的状态管理,如订单状态机流转。
  • 值对象封装无身份的业务量,如金额、费率、地址。
  • 聚合保证数据一致性边界,聚合根是唯一入口。
  • 领域事件实现跨聚合的最终一致性通知。
  • 限界上下文划定模型边界,避免概念污染。
下一阶段提示:掌握这些基础后,我们将进入支付订单系统的具体聚合建模,识别哪些实体应该放在同一个聚合内,哪些应该拆分到不同的限界上下文中。