第2章 业务模块识别方法:用例驱动、领域分析、事件风暴、上下文映射
模块划分的起点不是代码层次,而是业务边界的识别。不同的识别方法会从不同视角发现同一业务域内的聚合边界、职责分配与通信模式。本章将四个主流方法——用例驱动、领域分析、事件风暴、上下文映射——并列为等价候选人,并从架构师的视角对比它们在边界划定、分层拆分、组件职责、数据流/控制流/信任链路上的不同侧重与产出,最后给出选型权衡与落地步骤。
2.1 方法概览与对比
四种方法并非互斥,而是可以在不同阶段组合使用。下表从六个关键维度做快速对照:
| 维度 | 用例驱动 | 领域分析 | 事件风暴 | 上下文映射 |
|---|---|---|---|---|
| 核心输入 | 用户故事 / 用例图 | 领域专家知识 / 通用语言 | 业务事件 / 命令 / 聚合 | 已有系统 / 团队 / 接口协议 |
| 边界产出 | 系统用例边界 | 限界上下文 (Bounded Context) | 事件边界 + 聚合根 | 上下文映射图 + 协作模式 |
| 分层视角 | 自顶向下 (用户 → 系统) | 核心域 ↔ 支撑域 ↔ 通用域 | 自底向上 (事件 → 命令 → 聚合) | 跨系统分层 (前端/后端/第三方) |
| 组件职责清晰度 | 按用例划分,易散落 | 按领域概念聚合,内聚高 | 按事件溯源,职责明确 | 按集成契约,边界严格 |
| 数据流/控制流 | 用户交互触发流程 | 领域事件 + 仓储模型 | 事件 → 命令 → 读取模型 | RPC / 消息 / REST 契约 |
| 信任链路 | 依赖用例排序 | 领域层不依赖基础设施 | 事件总线解耦上下游 | 防腐层 + 开放主机服务 |
注意:四种方法产出的“边界”粒度可能不同。用例驱动易产出“功能模块”,领域分析产出“业务上下文”,事件风暴产出“事件聚合”,上下文映射产出“系统边界”。架构师需要合并这些产出形成统一的模块划分方案。
2.2 方法详解与架构要点
2.2.1 用例驱动 (Use-Case Driven)
起源自 RUP 与 UML,强调从用户目标出发,逐步分解出系统应提供的功能单元。每个用例对应一个相对独立的业务能力,模块边界由用例间的数据依赖与执行顺序决定。
- 边界划定: 识别参与者和主要场景,一个用例一个服务(或微服务)的做法容易导致服务过多,建议按用例组聚合。
- 分层与职责: 表现层、应用层(用例编排)、领域层(业务规则)、基础设施层。用例驱动容易让应用层变胖,需注意领域逻辑下沉。
- 数据流: 输入 DTO → 应用服务 → 领域对象 → 仓储;控制流跟随用例步骤。
- 风险点: 忽视非功能需求,用例间共享数据易导致耦合;建议配合接口契约提前定义边界。
2.2.2 领域分析 (Domain Analysis)
源于 DDD(领域驱动设计),通过通用语言与领域专家协作,识别出核心域、支撑域、通用域,并进一步划分限界上下文。每个上下文内部独立建模,上下文之间通过上下文映射确定依赖方向。
- 边界划定: 按业务概念一致性划分,避免将“订单”拆到两个上下文中。
- 组件职责: 每个上下文包含自己的实体、值对象、领域服务、仓储接口;基础设施适配器在外部。
- 信任链路: 上下文之间只依赖接口(开放主机服务 / 防腐层),不允许直接依赖领域对象。
- 选型权衡: 领域分析需要高领域知识投入,适合核心业务复杂度高的系统;对于简单 CRUD 场景可能过度设计。
2.2.3 事件风暴 (Event Storming)
以业务事件为起点,通过工作坊形式让所有角色(领域专家、开发、测试)一起在墙上贴便签,逐步梳理出命令、聚合、读模型与外部系统。事件风暴天然产出事件驱动架构的模块边界。
- 边界划定: 根据事件归属的聚合边界划分模块,一个聚合或一组相关聚合构成一个限界上下文。
- 数据流/控制流: 事件 → 命令处理 → 状态变更 → 发布新事件。流程清晰,适合微服务之间的异步通信。
- 风险点: 容易产生过多细粒度事件,需要事件版本化策略;另外工作坊耗时较长,需要充分准备。
2.2.4 上下文映射 (Context Mapping)
不关注单个上下文内部的建模,而是专攻上下文之间的协作关系。常用模式包括:<%----%>合作关系、<%----%>共享内核、<%----%>客户-供应商、<%----%>防腐层、<%----%>开放主机服务。
- 边界划定: 已有的系统边界或团队边界决定了映射关系,新模块按映射模式插入。
- 信任链路: 防腐层是典型的信任边界,下游模块通过适配器隔离上游变化。
- 落地步骤: 映射现有系统 → 识别瓶颈 → 选择映射模式 → 签订接口契约(包括数据格式、一致性级别、SLA)。
- 验收标准: 每个上下文映射关系有明确的接口文档与测试套件,上下游可以独立部署。
架构经验: 推荐组合使用领域分析 + 事件风暴来发现内部上下文,然后用上下文映射来固化边界间契约。用例驱动可作补充验证,确保用户视角的完整性。
2.3 四种方法在模块划分中的关系
下图以统一视角展示四种方法如何围绕同一个业务域产出不同层次的边界与依赖方向:
2.4 选型权衡与风险点
| 场景 | 推荐方法 | 核心风险 | 缓解策略 |
|---|---|---|---|
| 全新创新项目,领域知识不明确 | 事件风暴 + 领域分析 | 工作坊成本高,产出不稳定 | 分阶段进行,先核心后支撑 |
| 已有单体系统微服务拆分 | 上下文映射 + 用例驱动 | 过度依赖代码静态分析,忽略业务语义 | 结合领域专家访谈校准边界 |
| 标准化业务系统(如CRM) | 用例驱动为主 | 服务粒度随意,缺少领域分层 | 设定最小用例组大小(3~5个用例) |
| 跨组织多系统集成 | 上下文映射为主 | 契约频繁变更,缺乏测试 | 契约优先 + Consumer-Driven Contract |
- 风险点1:边界模糊 — 不同方法产出的边界冲突。解决:建立一个边界决策矩阵,以业务变更频率、数据一致性要求、团队自治权为权重投票。
- 风险点2:忽略信任链路 — 只划了边界没定义依赖方向,导致循环依赖。解决:在上下文映射图上标注依赖方向箭头,并用接口契约锁定。
- 风险点3:过度工程 — 对简单业务流程也做DDD。解决:用用例驱动快速验证,只在复杂核心域投入领域分析。
2.5 落地步骤与验收标准
落地步骤(适用于大多数项目中前期)
- 统一通用语言: 召集业务方与开发方,定义核心术语,产出词汇表。
- 事件风暴工作坊(可选/推荐): 用橙、蓝、绿便签分别标记事件、命令、聚合,形成初始聚合边界。
- 领域分析精化: 对每个聚合分配核心/支撑/通用标签,识别出上下文的候选。
- 上下文映射: 绘制所有上下文的依赖关系,选择映射模式(防腐层/开放主机等),并初步定义接口契约(事件/API)。
- 用例验证: 跑用户故事,确认每个用例的端到端流程可以跨越上下文完成,且依赖方向一致。
- 模块拆分决策: 将限界上下文映射为模块,决定部署单元(微服务/模块库/分层)。
- 签订接口契约: 确定第一个版本的接口定义(REST/gRPC/事件Schema),并固化到仓储。
验收标准
- 每个模块有唯一的限界上下文边界,不存在一个业务概念跨两个模块实现的现象。
- 模块之间的依赖方向无循环,且符合信任链路(下游依赖上游接口,而非实现)。
- 每个模块的组件职责明确:应用服务、领域模型、基础设施适配器职责分割清晰。
- 数据流:从输入到输出经过的每个模块都能在上下文映射图中找到对应的接口。
- 控制流:业务事件在模块间的传递顺序与事件风暴的流程一致。
- 接口契约已版本化,并通过契约测试(如Pact或Spring Cloud Contract)验证。
小贴士: 在实际项目中,这四种方法不一定要完整跑一遍。可以根据团队成熟度、业务复杂度、时间限制裁剪。但上下文映射这一步几乎是所有微服务架构的必经之路,因为它直接决定了模块之间的通信成本与耦合度。