Skip to content

耦合取舍 = 保留有益的,消除有害的 ​

解决什么问题:跨模块 / 跨服务的耦合有好有坏—— 不是所有耦合都应该消除,保留有益的耦合,消除有害的耦合。

业务问题 ​

真实场景 ​

场景 1:完全消除耦合

架构师:"我们要消除所有耦合!"

后果:
- 用户模型在 5 个服务里各定义一份
- 订单服务、支付服务、推荐服务各自定义"用户"
- 用户属性变更要在 5 个服务同步修改
- 实际耦合没消除,反而更糟(数据不一致)

→ "完全消除耦合"是个陷阱

场景 2:完全不消除耦合

架构师:"我们要快速开发,跨服务调用没问题"

后果:
- 订单服务直接读支付服务的数据库
- 支付服务改表结构 → 订单服务挂掉
- 跨服务耦合导致一个改动影响多个服务

→ "完全不消除耦合"导致雪崩

场景 3:识别有益的耦合

跨 BC 共享"用户 ID":
- 这是必需的耦合
- 通过 Shared Kernel 共享
- 改 ID 类型必须协调

跨 BC 共享"用户偏好":
- 这不是必需的耦合
- 每个 BC 维护自己的"用户偏好"
- 互不影响

→ 正确的耦合取舍 = 保留必需的,消除不必需的

失败的典型做法 ​

做法 1:盲目追求"零耦合"

✗ 每个服务完全独立
✗ 不共享任何模型

后果:
- 数据不一致
- 重复开发
- 维护成本高

做法 2:完全不设计耦合

✗ 跨服务直接调用
✗ 跨服务直接读数据库

后果:
- 耦合度高
- 一个改动影响多个服务
- 雪崩风险

做法 3:耦合标准不一致

✗ 这个服务用 Shared Kernel
✗ 那个服务用 ACL
✗ 没有统一标准

后果:
- 跨 BC 协作混乱
- 新人无法理解

控制论视角 ​

数学原型 ​

钱学森《工程控制论》Ch 6 §6.7:

"受控对象中的相互关联并不总是有害的。我们必须在设计中明确哪些耦合是必须的,哪些是有益的,哪些是有害的。有些耦合作用是有益的——它帮助我们实现整体目标;而有些耦合是有害的——它增加了系统复杂度,降低了可靠性。"

钱学森 §6.3 互不影响原则:

"设法确定控制矩阵的元素...才能使规定的控制信号只影响和它们相应的受控量,而不影响其余的受控量。"

控制论解法 ​

耦合的四种类型:

类型 1:必需耦合
  定义:业务规则强制要求的耦合
  例:订单必须关联用户 ID
  处理:保留(Shared Kernel)

类型 2:有益耦合
  定义:能提升整体性能的耦合
  例:订单服务和库存服务共享数据,提升库存准确性
  处理:保留(明确共享 + 同步机制)

类型 3:中性耦合
  定义:可有可无的耦合
  例:跨 BC 共享某些辅助数据
  处理:可保留可消除(按团队偏好)

类型 4:有害耦合
  定义:增加复杂度但不带来价值的耦合
  例:跨 BC 直接读数据库
  处理:消除(ACL / 异步事件)

与业务的对应 ​

控制论概念软件工程
互不影响原则限界上下文(BC 边界)
必需耦合强制业务关系(如订单-用户)
有益耦合共享内核(Shared Kernel)
有害耦合需要消除(ACL / 解耦)
协调偏差跨 BC 协作机制

核心概念 ​

定义 ​

耦合取舍:识别跨模块 / 跨服务的耦合类型,保留必需和有益的,消除有害的。

四种耦合类型 ​

类型含义处理方式软件工程对位
必需耦合业务规则强制要求必须保留强制业务关系
有益耦合能提升整体性能保留 + 明确管理Shared Kernel
中性耦合可有可无按团队偏好内部协议
有害耦合增加复杂度必须消除ACL / 异步

关键属性 ​

属性含义
业务驱动耦合取舍由业务关系决定
价值导向保留有价值的,消除无价值的
显式管理不是"自然发生",而是显式决策
可演化业务变化时重新评估耦合

耦合取舍的判断标准 ​

问 4 个问题:

1. 这个耦合是业务必需的吗?
   → 是 → 必需耦合 → 保留
   → 否 → 进入下一题

2. 这个耦合能提升整体性能/质量吗?
   → 是 → 有益耦合 → 保留 + 管理
   → 否 → 进入下一题

3. 消除这个耦合的复杂度 vs 保留的成本?
   → 消除更简单 → 有害耦合 → 消除
   → 保留更简单 → 中性耦合 → 按团队偏好

4. 未来业务变化时,这个耦合会变成什么?
   → 更必需 → 保留
   → 变成有害 → 提前消除

工程实践 ​

步骤 1:识别所有跨 BC 耦合 ​

工具:Context Map

例:
- 订单 BC ←→ 支付 BC:调用支付接口
- 订单 BC ←→ 库存 BC:查询库存
- 订单 BC ←→ 用户 BC:查询用户信息
- 推荐 BC ←→ 用户 BC:查询用户偏好

每个耦合 = 一行 Context Map

步骤 2:判断耦合类型 ​

逐个判断:

订单 ←→ 支付:
  - 业务必需?✅ 是
  - 提升性能?✅ 是(同步支付确保订单状态)
  → 必需耦合 + 有益耦合 = 保留(明确接口)

订单 ←→ 库存:
  - 业务必需?✅ 是
  - 提升性能?⚠️ 部分(强一致会延迟)
  → 必需耦合 + 中性 = 异步事件(最终一致)

订单 ←→ 用户:
  - 业务必需?✅ 是(订单必须关联用户)
  - 但只需用户 ID,不需要完整用户信息
  → 必需耦合(弱)= 共享 ID

推荐 ←→ 用户:
  - 业务必需?❌ 否
  - 但能提升推荐质量?✅ 是
  → 有益耦合 = 通过 ACL 转换(推荐模型的用户表示)

步骤 3:设计耦合管理方式 ​

必需耦合:
  → Shared Kernel(共享内核)
  → 明确接口
  → 同步协调

有益耦合:
  → Shared Kernel / Context Map 标注
  → 定期 review(耦合是否仍然有益)
  → 必要时重新设计

中性耦合:
  → 文档化(让团队知道)
  → 不强制管理

有害耦合:
  → ACL(防腐层)
  → 异步事件
  → 同步复制

步骤 4:建立耦合健康度监控 ​

监控指标:

耦合密度:
- 跨 BC 调用次数 / BC 内调用次数
- 健康范围:< 0.2

耦合变更频率:
- 跨 BC 接口的变更次数
- 健康范围:低频(每个接口 < 1 次/月)

耦合失败影响:
- 一个 BC 的耦合失败影响多少 BC
- 健康范围:≤ 1 个 BC(隔离)

常见反模式 ​

反模式 1:盲目追求"零耦合" ​

症状:
- 每个服务完全独立
- 不共享任何模型

后果:数据不一致 / 重复开发
正解:保留必需耦合

反模式 2:完全不设计耦合** ​

症状:
- 跨服务直接调用
- 跨服务直接读数据库

后果:雪崩风险 / 改动影响多个服务
正解:显式管理耦合

反模式 3:耦合标准不一致** ​

症状:
- 有时 Shared Kernel
- 有时 ACL
- 没有规则

后果:跨 BC 协作混乱
正解:建立耦合决策标准

工程实例 ​

实例 1:电商系统的耦合取舍 ​

识别所有耦合:

| 耦合 | 必需? | 有益? | 类型 | 处理 |
|---|---|---|---|---|
| 订单-支付 | ✅ | ✅ | 必需+有益 | Shared Kernel |
| 订单-库存 | ✅ | ⚠️ | 必需+中性 | 异步事件 |
| 订单-用户 | ✅(仅ID) | ❌ | 必需(弱) | 共享 ID |
| 推荐-用户 | ❌ | ✅ | 有益 | ACL |
| 推荐-订单 | ❌ | ⚠️ | 中性 | 文档化 |
| 支付-账户 | ✅ | ✅ | 必需+有益 | Shared Kernel |

实施:
- 必需+有益 → 强接口 + 同步调用
- 必需(弱)→ 共享 ID
- 有益 → ACL
- 中性 → 文档化

实例 2:跨团队协作的耦合取舍 ​

A 团队(订单)和 B 团队(库存)的协作:

选项 1:库存数据同步复制到订单
  - 类型:有益耦合
  - 优势:订单服务快速响应,不依赖库存服务
  - 劣势:数据可能不一致
  - 处理:定期同步 + 最终一致性

选项 2:订单实时调用库存
  - 类型:必需耦合(强)
  - 优势:数据一致
  - 劣势:库存故障影响订单
  - 处理:熔断 + 降级(库存不可用时,订单仍可下单)

取舍:
- 高一致性要求场景 → 选项 2
- 高可用要求场景 → 选项 1
- 折中 → 选项 1 + 关键场景选项 2

性能指标 ​

耦合健康指标 ​

指标设计目标衡量方法
耦合密度< 0.2跨 BC 调用 / BC 内调用
耦合变更频率< 1 次/月(每接口)接口变更次数
耦合失败隔离率一个 BC 故障不影响其他故障演练
耦合显式率100% 耦合都有 Context Map 标注已标注耦合 / 总耦合

监控设计 ​

关键监控:
- 跨 BC 调用次数(按 BC 对)
- 跨 BC 调用延迟
- 跨 BC 失败率
- 耦合变更日志

告警分级:
- P2:耦合密度 > 0.3
- P1:耦合失败率 > 1%
- P0:耦合导致级联故障

边界判断 ​

何时不用 ​

场景 1:业务极简

- 单进程应用
- 没有 BC 划分

→ 不需要耦合分析

场景 2:业务完全确定

- 所有耦合都已设计
- 业务稳定

→ 不需要持续 review

场景 3:单一团队

- 所有 BC 由一个团队维护
- 没有跨团队协作

→ 不需要 Context Map

与其他方法论的边界 ​

相邻概念区别
限界上下文限界上下文关注"边界划分";本方法论关注"耦合取舍"
跨上下文协作跨上下文协作关注"协作模式";本方法论关注"取舍决策"
三难困境三难困境关注"性能取舍";本方法论关注"耦合取舍"

何时升级(更精细的耦合管理) ​

当以下情况出现时,考虑升级:

1. 跨 BC 耦合 > 30% → 重新划分 BC
2. 耦合变更频率高 → 稳定化机制
3. 跨团队协作冲突 → 协商机制
4. 业务规模指数增长 → 自动化耦合分析

关键洞察 ​

钱学森 §6.7 原话:"受控对象中的相互关联并不总是有害的。有些耦合作用是有益的——它帮助我们实现整体目标。"

软件工程的耦合取舍智慧:

不是"零耦合" = 好的架构而是"正确的耦合" = 好的架构

必需耦合保留(Shared Kernel) 有害耦合消除(ACL) 中性耦合可灵活

架构师的成熟标志 = 能识别哪些耦合该留,哪些该走。

相关链接 ​

IDDD 对位 ​

  • 耦合 = BC 间依赖 → 9 种 BC 关系(Ch 3):Shared Kernel 强耦合,ACL 弱耦合
  • 解耦 = 用集成成熟度 → 集成成熟度模型(Ch 13):用事件解耦
  • 内聚 = BC 内一致性 → BC:高内聚低耦合

核心:耦合取舍 = BC 关系选择——不是消除耦合,是选择合适的耦合方式。

从名家方法论与工程化思路中蒸馏出自己的工程体系。