3. 领域事件定义:概念、命名规范与属性设计

领域事件(Domain Event)是事件风暴的核心产出物,也是分布式事务中实现最终一致性的关键消息载体。本节将系统定义领域事件的概念、命名规范与属性设计原则,确保团队在建模过程中产出高质量、可落地的领域事件。

3.1 领域事件的概念

领域事件是领域专家关心的、发生在过去且对业务有意义的重大状态变化。它记录了“某件事已经发生”的事实,并携带相关的上下文数据,供其他限界上下文或同一上下文内的其他聚合订阅消费。

维度 说明 示例
时间性 事件发生在过去,不可撤销 “订单已支付”发生在支付完成时刻
业务意义 领域专家能理解并认可的事件 “库存已扣减”而非“数据库行已更新”
不可变性 事件一旦发布,内容不可修改 补偿通过新事件实现,而非修改旧事件
因果性 事件是命令执行后的结果 “提交订单”命令 → “订单已提交”事件
关键区分:领域事件 ≠ 系统日志。领域事件必须包含业务语义,能被其他限界上下文理解并触发后续业务动作;系统日志仅用于技术排障,不参与业务流转。

3.2 命名规范:过去时动词

领域事件的命名遵循“业务对象 + 过去时动词短语”的格式,使用英文驼峰命名,确保事件名称清晰表达“发生了什么”。

规范项 规则 正确示例 错误示例
时态 必须使用过去时(-ed 或过去分词) OrderSubmitted OrderSubmit(现在时)
业务对象 使用领域通用语言中的实体/聚合名称 PaymentCompleted PayDone(非标准术语)
动词选择 使用业务动作的精确动词 InventoryReserved InventoryChanged(过于模糊)
大小写 PascalCase(大驼峰) OrderShipped order_shipped(蛇形)

常见领域事件命名示例:

  • OrderSubmitted — 订单已提交
  • PaymentCaptured — 支付已捕获
  • InventoryReserved — 库存已预留
  • ShipmentDelivered — 配送已签收
  • RefundInitiated — 退款已发起
避坑提示:避免使用 OrderCreated 这类过于泛化的事件名。如果“创建订单”和“提交订单”是两个不同的业务节点,应分别命名为 OrderDrafted(草稿已创建)和 OrderSubmitted(订单已提交),以精确表达业务语义。

3.3 属性设计原则

领域事件的属性设计遵循“最小完备”原则:只携带消费者需要的数据,不包含实现细节,同时保证事件可被独立理解和处理。

属性类别 必选/可选 说明 示例
事件ID 必选 全局唯一标识,用于幂等去重 evt_20250321_001
事件时间 必选 事件发生的业务时间(UTC) 2025-03-21T10:30:00Z
聚合ID 必选 事件所属聚合的唯一标识 order_98765
聚合类型 必选 事件所属聚合的领域类型 Order
业务数据 按需 消费者需要的业务上下文 totalAmount, items
版本号 推荐 事件 schema 版本,支持演进 1
来源上下文 推荐 产生事件的限界上下文名称 OrderContext
设计检查清单:
  1. 消费者能否仅凭事件数据完成业务处理,无需回查源系统?
  2. 事件数据是否包含敏感信息(如密码、支付密钥)?应排除。
  3. 事件数据是否包含技术实现细节(如数据库ID、内部IP)?应排除。
  4. 事件数据是否足够支撑幂等判断?必须包含聚合ID和事件ID。

3.4 领域事件结构示例

以下是一个完整的 OrderSubmitted 事件 JSON 示例,展示属性设计的落地形态:

{
  "eventId": "evt_20250321_a1b2c3d4",
  "eventType": "OrderSubmitted",
  "eventVersion": 1,
  "occurredOn": "2025-03-21T10:30:00.123Z",
  "sourceContext": "OrderContext",
  "aggregateId": "order_98765",
  "aggregateType": "Order",
  "data": {
    "orderId": "order_98765",
    "customerId": "cust_12345",
    "totalAmount": 299.99,
    "currency": "CNY",
    "items": [
      {
        "productId": "prod_001",
        "quantity": 2,
        "unitPrice": 149.995
      }
    ],
    "shippingAddress": {
      "province": "Guangdong",
      "city": "Shenzhen",
      "detail": "Nanshan District"
    }
  }
}

3.5 领域事件与分布式事务的关系

在分布式事务场景中,领域事件扮演“事务协调信号”的角色。每个本地事务完成后发布一个领域事件,触发下一个限界上下文的本地事务,形成事件驱动的 Saga 或 TCC 补偿流程。

领域事件在分布式事务中的流转 订单上下文 本地事务:创建订单 OrderSubmitted 事件ID | 聚合ID | 业务数据 支付上下文 本地事务:扣款 发布 订阅 PaymentCaptured 事件ID | 聚合ID | 支付结果 库存上下文 本地事务:扣减库存 支付成功 → 发布事件 订阅 关键设计要点: 1. 每个领域事件对应一个本地事务的完成,事件本身不包含事务状态。 2. 事件属性必须包含聚合ID,支持消费者进行幂等判断和补偿定位。

3.6 事件风暴中的领域事件识别技巧

在事件风暴工作坊中,团队通过以下步骤快速识别并定义领域事件:

  1. 橙色便利贴:用橙色便利贴记录领域事件,贴在时间轴右侧。
  2. 过去时动词:每张便利贴以过去时动词结尾,如“已提交”、“已支付”。
  3. 业务验证:邀请领域专家确认“这个事件是否真实发生过且有意义”。
  4. 属性头脑风暴:围绕事件讨论“消费者需要什么数据”,记录在事件下方。
  5. 命名评审:团队共同评审事件名称是否清晰、无歧义、符合通用语言。
实战建议:在事件风暴初期,不要过度设计事件属性。先用便利贴记录事件名称和关键数据字段,后续通过“事件溯源”和“消费者访谈”逐步完善属性清单。过度设计会拖慢工作坊节奏,降低领域专家的参与度。