3. 限界上下文(Bounded Context)识别:通过业务事件风暴(Event Storming)识别核心域、支撑域、通用域

在领域驱动设计中,限界上下文(Bounded Context)是划分系统边界的基本单元。它定义了模型在特定上下文中含义的边界,确保术语、规则和业务逻辑在该边界内保持一致性。本节将介绍如何通过业务事件风暴(Event Storming)这一协作建模技术,系统性地识别出核心域、支撑域和通用域,并最终确定微服务的拆分边界。

3.1 业务事件风暴概述

事件风暴是由 Alberto Brandolini 提出的一种工作坊式建模方法,通过跨职能团队(业务专家、产品经理、开发人员、测试人员)的协作,在短时间内快速梳理出完整的业务全景。其核心产出物包括:

  • 领域事件(Domain Event):业务中发生的、对业务有重要意义的事实(如“订单已提交”、“库存已扣减”)。
  • 命令(Command):触发领域事件的操作(如“提交订单”、“扣减库存”)。
  • 聚合(Aggregate):一组具有内聚性的实体和值对象,是事务一致性的边界。
  • 外部系统(External System):与当前系统交互的第三方服务或遗留系统。
  • 用户(User/Actor):发起命令的角色。
实践建议:事件风暴工作坊建议控制在 8-12 人,使用不同颜色的便利贴(如橙色=领域事件、蓝色=命令、粉色=外部系统、绿色=用户),在长条白纸上按时间轴从左到右排列。整个过程通常需要 2-4 小时。

3.2 从领域事件到限界上下文

事件风暴完成后,团队会得到一张覆盖完整业务流的事件全景图。接下来,需要根据以下原则对领域事件进行分组,识别出限界上下文:

  1. 语言一致性:同一组内使用的业务术语含义必须唯一,不存在歧义。
  2. 事务边界:需要保持强一致性(ACID)的聚合应属于同一个限界上下文。
  3. 变化频率:变化速率和原因相似的业务逻辑倾向于放在同一个上下文中。
  4. 团队结构:遵循康威定律,限界上下文通常对应一个独立团队负责的微服务。

以下表格展示了在电商场景中,通过事件风暴识别出的典型限界上下文及其对应的领域事件示例:

限界上下文 典型领域事件 核心业务术语
订单上下文 订单已创建、订单已支付、订单已取消 订单、订单项、收货地址
库存上下文 库存已扣减、库存已释放、库存不足 SKU、库存量、仓库
支付上下文 支付已发起、支付已成功、支付已退款 交易流水、支付渠道、对账单
物流上下文 包裹已发货、包裹已签收、配送异常 运单、物流商、配送站
用户上下文 用户已注册、用户已认证、用户等级变更 账户、会员等级、积分

3.3 核心域、支撑域与通用域的划分

识别出限界上下文后,需要进一步将其归类为三种域类型,以指导资源投入和架构决策:

  • 核心域(Core Domain):企业最核心的竞争力所在,是业务差异化的来源。需要投入最多的资源进行自研和持续优化。
  • 支撑域(Supporting Subdomain):支撑核心业务运转,但本身不构成核心竞争力。通常需要定制开发,但复杂度低于核心域。
  • 通用域(Generic Subdomain):行业通用能力,有成熟的开源或商业解决方案。优先考虑采购或使用现成产品,避免重复造轮子。
判断标准:问业务专家一个问题——“如果这个系统出问题了,公司会损失多少钱?如果换成竞争对手的系统,用户能感知到区别吗?” 如果损失巨大且用户能明显感知,则属于核心域;如果损失可控且用户无感知,则可能是通用域。

以下 SVG 图展示了通过事件风暴识别出的限界上下文及其域类型归属:

事件风暴识别限界上下文与域类型 核心域 订单上下文 定价上下文 促销上下文 差异化竞争力 高投入自研 支撑域 库存上下文 物流上下文 支付上下文 支撑核心业务 定制开发 通用域 用户上下文 通知上下文 认证上下文 行业通用能力 采购/开源 事件风暴工作坊产出 领域事件 → 命令 → 聚合 → 用户 → 外部系统 分组原则 1. 语言一致性:同一上下文内术语无歧义 2. 事务边界:强一致性操作放在同一上下文 3. 变化频率:变化原因相同的逻辑聚合在一起

3.4 实战案例:电商平台域划分

以一个典型的 B2C 电商平台为例,通过事件风暴识别出的限界上下文及其域类型划分如下:

限界上下文 域类型 划分理由 推荐策略
订单上下文 核心域 订单流程是电商的核心体验,涉及复杂的业务规则(拆单、合并、退款) 自研,持续投入
促销上下文 核心域 促销策略(满减、秒杀、优惠券)是平台吸引用户的关键差异化能力 自研,高优先级
库存上下文 支撑域 需要与订单紧密配合,但逻辑相对标准化,存在行业最佳实践 自研,复用模式
支付上下文 通用域 对接支付宝、等成熟支付渠道,核心逻辑由第三方提供 集成 SDK,轻量封装
用户上下文 通用域 注册、登录、密码管理等功能有成熟的开源方案(如 Keycloak) 采购或开源方案
常见误区:不要将所有与“用户”相关的功能都归入通用域。如果用户等级体系、会员权益是平台的核心竞争力(如京东 Plus、淘宝 88VIP),则这部分应划入核心域。通用域只包含那些“换一家供应商用户完全无感知”的能力。

3.5 限界上下文与微服务边界

识别出限界上下文后,每个限界上下文通常对应一个独立的微服务。但需要注意以下映射规则:

  • 一对一映射:一个限界上下文对应一个微服务,这是最理想的情况。
  • 一对多映射:当限界上下文内部存在明显的性能差异或部署频率差异时,可以拆分为多个微服务(如将“订单查询”与“订单写入”分离)。
  • 多对一映射:对于非常简单的支撑域或通用域,可以将多个限界上下文合并为一个微服务(如将“通知”和“短信”合并)。

以下 SVG 图展示了限界上下文与微服务之间的映射关系:

限界上下文 → 微服务映射模式 一对一映射 订单上下文 订单微服务 推荐模式 一对多映射 库存上下文 库存写入微服务 库存查询微服务 读写分离场景 多对一映射 通知上下文 短信上下文 消息微服务 简单域合并 映射决策因素 • 团队规模:每个微服务由 2-8 人团队维护 • 部署频率:变化频繁的部分独立部署 • 数据存储:不同上下文使用独立数据库 • 通信方式:同步调用 vs 事件驱动

3.6 识别过程中的常见陷阱

陷阱一:过度拆分
将“订单创建”和“订单查询”拆成两个微服务,但两者共享同一个数据库,导致分布式事务和跨服务查询的复杂度剧增。正确做法:先保持一个限界上下文,当确实存在性能瓶颈时再考虑拆分。
陷阱二:忽略上下文映射
识别出限界上下文后,没有定义上下文之间的映射关系(如合作关系、防腐层、开放主机服务),导致服务间耦合严重。每个限界上下文必须明确其与外部上下文的集成方式。
陷阱三:术语污染
在“订单上下文”中使用“用户”表示买家,在“物流上下文”中使用“用户”表示收货人,导致模型混乱。必须为每个上下文中的同名术语建立明确的上下文映射表。

3.7 小结

通过事件风暴识别限界上下文是 DDD 建模的核心环节。关键产出包括:

  • 一张完整的领域事件全景图,覆盖所有核心业务流程。
  • 一组清晰的限界上下文,每个上下文拥有统一的语言和事务边界。
  • 明确的域类型划分(核心域、支撑域、通用域),指导资源投入和架构决策。
  • 初步的微服务边界建议,为后续的模块拆分和接口设计奠定基础。