SOLID 自检清单怎么用
SOLID 的五个问题化表述比原则本身的定义更好用:这个类为什么会被改?新增同类能力要改哪里?子类替上去行为还成立吗?有没有人被迫实现用不到的方法?依赖方向指向抽象了吗?这些问题的价值在于把设计取舍说出口,而不是给代码打分。
基本信息
| 用途 | 评审对话与设计讨论中的提醒,不是打分工具 |
|---|---|
| 形式 | 五个可回答的问题,每个都有合理例外 |
| 时机 | 评审、拆任务、接手陌生模块时 |
| 产出 | 把结论记录到 PR 描述或 ADR,避免重复讨论 |
清单对应的原则
- 单一职责:本 PR 同时回应了几个「变化原因」
- 开闭原则:新增一个同类实现要触碰几处既有代码
- 里氏替换:换成父类引用后断言是否仍然成立
- 接口隔离:是否存在空实现或抛出不支持的占位方法
- 依赖倒置:业务代码里是否直接 import 了具体基础设施
- 综合判断:哪一条被违反得最严重,而不是哪几条没做到
评审五问
评审五问
1. 本 PR 同时回答了几个「变化原因」?
2. 新增一个同类实现,要触碰几处既有代码?
3. 把子类换成父类引用,断言还成立吗?
4. 有无空实现或抛出不支持的占位方法?
5. 业务代码里 import 了具体基础设施吗?
# 追问一句:哪一条最需要在本 PR 里解决?问题与典型处理
| 问题信号 | 判断 | 处理 |
|---|---|---|
| 一个类有多个变化原因 | 职责过多 | 按变化原因拆边界 |
| 新增实现要改多处分支 | 扩展点未显式化 | 引入注册表或策略选择点 |
| 子类需要空实现 | 接口过宽 | 按调用方需要拆小接口 |
| 业务层直接依赖框架类型 | 依赖方向倒置 | 内层定义接口,外层实现 |
| 抽象只有一个实现且无变化 | 抽象过早 | 先内联,等第二个实现出现 |
清单用于对话与提醒,不用于打分:每条都有合理例外,重点是让权衡显式化。判定的落脚点是「这条原则在当前场景下解决什么问题」,而不是原则本身是否被遵守。
问完要留痕:把结论写进 PR 描述或 ADR,下次遇到同类问题可以直接引用,而不是把同一场讨论重复一遍。