什么是发散式变化
发散式变化指同一个类因为多种不相关的原因被反复修改:数据库字段变了改它,税费规则变了也改它。它与霰弹式修改互为镜像——那里是一个原因要改很多地方,这里是多个原因挤在一个地方。处方是按变化原因拆分,让每一类变化只影响一个模块。
基本信息
| 典型信号 | 同一文件出现在差异很大的多类需求中 |
|---|---|
| 处方 | 提取类、拆分阶段 |
| 目标 | 一个模块只对一类变化负责 |
| 反向对照 | 霰弹式修改:一个变化要改很多地方 |
| 判断依据 | 这两类修改为什么会撞在同一个文件里 |
典型使用场景
- 一个服务类同时负责参数校验、定价计算与数据写入
- 报表类既管取数逻辑又管排版输出
- 定时任务里混着业务规则与通知发送
- 实体类同时承担持久化映射与业务行为
- 控制器里混入权限判断与响应格式拼装
拆分示例
拆分示例
// 之前:OrderService 同时承担校验、定价、持久化三类变化
// 之后:按变化原因拆开
class OrderValidator { } // 校验规则变化时只改这里
class Pricer { } // 定价策略变化时只改这里
class OrderRepository { } // 存储方式变化时只改这里拆分依据
| 依据 | 例子 | 说明 |
|---|---|---|
| 变化原因 | 校验、定价、持久化各自变化 | 按原因拆,不按技术层次硬拆 |
| 变更频率 | 某部分每周改、某部分每年改 | 高频部分独立出来更稳 |
| 使用方 | 不同角色关心不同部分 | 便于按需替换与单独测试 |
拆分前先记录一段时间内这个类被修改的原因,按原因聚类。凭直觉拆出的模块常常只是把代码切碎,耦合仍然留在原处。
不要按技术层次硬拆(全都拆成工具类):缺乏领域含义的碎片更难复用,调用方要在多个类之间来回跳。