SRP 实操:如何找到变化原因
单一职责原则的难点从来不是定义,而是找出「变化原因」。可操作的做法是看三类线索:谁提出需求(干系人)、改动以什么形式进入(工单类型)、数据来自哪里(上游系统)。把同一原因引起的改动聚进一个模块,不同原因之间画边界——边界的位置由变化节奏决定,而不是由代码相似度决定。
基本信息
| 线索 | 干系人 / 工单类型 / 数据来源 |
|---|---|
| 方法 | 列举近半年的修改记录,按原因聚类 |
| 输出 | 模块边界与所有权候选 |
| 验证 | 两个原因是否会同时改?同时改说明边界画错了 |
找变化原因的步骤
- 取近半年该模块的提交与工单,逐条标注「为什么改」
- 把原因归类:口径调整、样式变更、数据源迁移、性能修复
- 统计每类的频率与参与人,频率高且参与人不同的一类就是一个候选边界
- 检查当前代码里这些原因是否交织在同一个方法里
- 按原因切出模块,先做接口划分,再决定是否物理拆包
- 命名时用变化原因而不是技术手段(报表口径模块,而非 Util 模块)
按原因聚类示例
按原因聚类示例
ReportService 的历史修改(近半年):
- 财务口径调整 ×7 → 报表口径模块
- PDF 导出样式 ×5 → 渲染模块
- 数据源迁移 ×3 → 取数模块
- 性能优化 ×1 → 暂不单独成模块
结论:一个类同时承载三种变化原因,
口径与样式还分别由不同干系人提出 → 拆三个边界三类线索的提问
| 线索 | 提问 | 边界含义 |
|---|---|---|
| 干系人 | 谁会要求改这里? | 不同要求方 → 不同模块 |
| 工单类型 | 改动的形式是什么? | 口径 / 样式 / 集成各不相同 |
| 数据来源 | 数据从哪来? | 上游系统变化不应牵动业务规则 |
| 发布节奏 | 多久改一次? | 高频变动部分需隔离 |
只看当前代码很难判断职责:静态结构看起来都很合理。翻改动记录是更可靠的证据来源——变化原因只有从历史里才看得见。
按人员分工直接切代码是常见误区:组织结构会调整,职责不会。分工作为线索可以,作为边界依据则会在人员变动后留下难以理解的模块划分。