### 第2章 业务域与模块边界识别:领域驱动设计、限界上下文划分、业务能力映射
#### 2.1 为什么模块边界必须从业务域出发?
在软件架构中,模块划分最致命的错误是“技术驱动”。许多团队以持久层、缓存层、消息层来划分模块,这会导致高度耦合、牵一发而动全身。模块边界是**业务能力的自然映射**,而非技术实现的物理分割。只有从业务域(Domain)出发,识别出独立的业务能力边界(即限界上下文),才能保证模块的高内聚与低耦合。
**核心原则:业务域 → 业务子域 → 限界上下文 → 模块边界**
- **业务域**:企业或系统所服务的核心业务领域(如电商、金融交易、医疗)。
- **业务子域**:业务域中的主要能力领域(如订单、支付、库存)。
- **限界上下文**:领域驱动设计(DDD)中明确划分的职责边界,子域内的业务逻辑与数据模型在此内保持完整性,不对外泄露。
- **模块边界**:限界上下文在代码层面的直接映射,即一个独立的模块(Module)或微服务。
---
#### 2.2 限界上下文的二维划分法
限界上下文并非简单的“功能模块”,而是包含**数据模型**与**业务规则**的完整自治单元。划分时需同时考虑**业务逻辑内聚**与**数据完整性**两个维度。
**表 2-1:限界上下文划分二维评估矩阵**
| 维度 | 考察点 | 高内聚标志 | 低内聚标志(需拆分) |
|------|--------|------------|----------------------|
| **业务逻辑内聚** | 该上下文内的业务规则是否紧密关联? | 一个业务事件通常在一个上下文内完成 | 多个上下文频繁协作才能完成单一业务事件 |
| **数据完整性** | 改变业务规则时,是否只需要修改该上下文的数据模型? | 数据模型变更仅影响本上下文 | 数据模型变更需要同步修改多个上下文的数据结构 |
| **团队协作耦合** | 开发团队是否可以独立迭代该上下文? | 团队间只需协商接口契约 | 团队间需要频繁对齐内部实现细节 |
**划分步骤:**
1. **识别业务事件**:列出所有关键业务场景(如“用户下单”、“支付成功”、“库存扣减”)。
2. **聚合业务事件**:将强关联事件及其对应的数据对象聚合成一个候选上下文。
3. **验证数据一致性**:检查候选上下文内是否包含完整的业务数据快照(避免跨上下文读取)。
4. **标注信任边界**:每个限界上下文应只信任自己内部的数据源,对外依赖通过接口进行。
---
#### 2.3 业务能力映射:从业务到模块的转化方法
业务能力映射(Business Capability Mapping)是将业务域分解为可操作、可量化的能力单元,并以此为基准确立模块边界。该方法不依赖技术实现细节,适用于新旧系统集成、微服务拆分等场景。
**关键产出物:能力全景图**
能力全景图通常以分层方式展示:
- **核心域**:系统最独特的、具有竞争优势的业务能力(如推荐引擎、定价算法)。
- **支撑域**:支持核心域运行的通用能力(如用户管理、权限、日志)。
- **通用域**:可对外采购或复用的能力(如邮件通知、支付网关)。
**映射步骤:**
1. **业务域分解**:将业务域按业务功能逐步分解为最小的可描述单元(如“订单”可分解为“创建订单”、“取消订单”、“修改订单地址”)。
2. **能力分类与分组**:将高度依赖同一组业务数据的单元归并到同一组,形成候选能力域。
3. **边界划分决策**:针对候选能力域,结合团队规模、交付节奏、数据一致性要求,确定是否拆分为独立模块。
---
#### 2.4 模块边界识别的典型风险点
**工作风险1:过度拆解(微服务大爆炸)**
> 每个业务事件都独立成为一个限界上下文,导致模块间依赖链过长,分布式事务失控。
> **防范策略**:合并高频协作、低事务一致性的上下文,优先保证业务内聚。
**工作风险2:共享内核污染**
> 多个模块共享同一个“公共模型层”,实际上形成了隐性耦合。
> **防范策略**:强制每个限界上下文内维护独立的数据模型副本,通过防腐层适配。
**工作风险3:业务能力映射与团队组织不匹配**
> 分配给A团队维护的能力域,实际需要B团队的核心数据访问权限。
> **防范策略**:能力映射应同时参考康威定律,尽量与团队结构对齐。
---
#### 2.5 内联 SVG:业务域到模块边界映射流程
> **图 2-1**:业务域通过分解为业务子域后,再经过业务能力映射、边界决策与分组,最终定义出限界上下文及其对应的模块边界。
---
#### 2.6 落地步骤与验收标准
**表 2-2:业务域与模块边界识别落地清单**
| 步骤 | 活动 | 产出物 | 关键检查点 |
|------|------|--------|------------|
| 1 | 业务域勘探 | 业务域清单 | 是否覆盖所有核心业务? |
| 2 | 业务子域与事件风暴 | 限界上下文初稿 | 每个上下文是否拥有独立数据模型? |
| 3 | 业务能力映射 | 能力全景图 | 核心域/支撑域/通用域是否清晰? |
| 4 | 边界分组与合并 | 模块定义清单 | 合并后模块是否仍保持内聚? |
| 5 | 接口契约定义 | 模块间依赖矩阵 | 依赖方向是否符合下游依赖上游? |
**验收标准(Checklist):**
- [ ] 每个限界上下文均有明确的业务目标与数据主权。
- [ ] 业务事件在单一上下文内完成的比例 ≥ 80%。
- [ ] 模块间依赖不存在环形依赖。
- [ ] 变更某一模块的数据库表结构,不会导致其他模块直接修改代码。
- [ ] 团队能够根据模块边界自由调整迭代计划,无需等待其他模块发布。
---
实践提示:在大型遗留系统中推行限界上下文划分时,不要追求一次完美。优先识别出核心域中的 1~2 个关键业务子域,先完成该部分的重构映射,积累经验后再逐步推广。一次性全量重构往往导致团队倦怠与边界混淆。
---
#### 2.7 选型权衡:上下文映射 vs. 能力映射
| 方法 | 适用场景 | 优势 | 劣势 |
|------|---------|------|------|
| **限界上下文**(DDD) | 业务逻辑复杂、需要长期演进的中大型系统 | 业务规则与数据模型高度自治,适合微服务 | 学习曲线陡峭,不适合简单 CRUD 系统 |
| **业务能力映射**(能力建模) | 新旧系统集成、遗留系统重构 | 快速产出、团队易于接受 | 容易忽略业务规则深层耦合,导致后来重构 |
**推荐组合**:先通过**业务能力映射**快速建立第一版模块边界骨架,再针对核心模块引入**限界上下文**细化内部逻辑。两个方法不是二选一,而是不同粒度的工具。