关于 single-responsibility-principle
single-responsibility-principle 是一项编程技能,指导开发者让每个类、模块或函数只承担一项职责,并识别何时应拆分功能,避免加入无关职责。
主要功能
- 01遵循单一职责规则
- 02识别多个变更原因
- 03发现过大的类的迹象
- 04提取职责明确的组件
适用场景
- 01设计新类或新模块
- 02审查含无关方法的类
- 03重构已有的臃肿类
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yanko-belov/ code-craft --skill single-responsibility-principle安装后在 Claude Code 中输入/single-responsibility-principle确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
user-system/AnalyticsService.tsAuthenticationService.tsindex.tsNotificationService.tsProfileService.ts详细介绍
单一职责原则(SRP)
概述
一个类应该只有一个变更理由。
每个模块、类或函数都应该只负责一项功能。 如果你需要用“并且”来描述一个类的职责,那它承担的职责就太多了。
适用场景
- 创建任何新类、模块或服务
- 向现有类添加方法
- 审查“做多件事”的代码
- 感觉自己忍不住想“就加在这里吧”
铁律
NEVER add functionality that introduces a second reason to change.
绝无例外:
- 不能因为“这样更快”
- 不能因为“只多加一个方法”
- 不能因为“重构要花太长时间”
- 不能因为“我的技术负责人这么说”
- 不能因为“它已经上线了”
在压力下违反 SRP,依然是在违反 SRP。
检测: “并且”测试
用一句话描述你的类。如果其中包含“并且”,就拆分它。
| 描述 | 判定 |
|---|---|
| “处理用户身份验证” | ✅ 单一职责 |
| “处理身份验证并发送电子邮件” | ❌ 两项职责 |
| “管理订单并处理付款,还跟踪库存” | ❌ 三项职责 |
检测:变更理由
列出这个类可能需要变更的原因:
// ❌ BAD: UserManager - 4 reasons to change
class UserManager {
login() {} // Auth logic changes
updateProfile() {} // Profile requirements change
sendEmail() {} // Email provider changes
trackAnalytics() {} // Analytics requirements change
}
// ✅ GOOD: Split by responsibility
class AuthService { login() {} }
class ProfileService { updateProfile() {} }
class NotificationService { sendEmail() {} }
class AnalyticsService { track() {} }
抗压应对流程
当有人施压要求违反 SRP 时,请按以下方式处理:
1. 时间压力
“先快速让它能用”
回应: 创建一个上帝类,耗时并不比创建职责明确的类少。这个“快速”方案会造成技术债,日后代价可能高出 10 倍。
行动: 创建独立的类。并不会更慢。
2. 沉没成本压力
“这个类已经存在了,直接加进去就行”
回应: 往臃肿的类里添加内容,只会让它更糟。它已经有问题,不代表可以让问题变得更严重。
行动: 创建一个职责明确的新类。如果时间允许,再重构现有类。
3. 权威压力
“我的技术负责人说把所有内容都放在一个类里”
回应: 以证据为依据,礼貌地提出异议。如果对方仍坚持,就记录你的顾虑并照做,但绝不要默默创建上帝类。
行动:
"I'd recommend splitting this because [specific reason].
If we keep it together, we'll likely need to refactor when [consequence].
Should I proceed with the split, or document this as tech debt?"
4. 范围蔓延
“既然你已经在改这里,也顺便加上 X”
回应: 新功能 = 新类(或已有的合适类)。
行动: “X 应该属于独立的服务。我会创建 XService。”
危险信号 - 停下并重新考虑
如果你注意到以下任意情况,说明你正要违反 SRP:
- 添加与类核心用途无关的方法
- 类文件超过 200 行
- 类有超过 5-7 个公共方法
- 你需要用分节注释才能浏览这个类
- 多位开发者会因互不相关的功能而修改这个类
- 类名包含“Manager”、“Handler”、“Processor”或“Service”,但没有具体的领域限定
这些情况都意味着:拆分类。
重构现有违规代码
遇到现有的上帝类时:
- 不要让情况更糟 - 绝不要添加更多职责
- 修改时顺手拆分 - 修改时,拆出你正在处理的部分
- 记录技术债 - 如果现在无法重构,就创建一个工单
// Found: OrderService with 500 lines handling orders, payments, inventory, emails
// ❌ WRONG: Add shipping logic to OrderService
// ✅ RIGHT: Create ShippingService, note that OrderService needs refactoring
常见的自我辩解(都不成立)
| 借口 | 事实 |
|---|---|
| “放在一个类里更快” | 并非如此。无论哪种方式,输入的代码都一样。 |
| “小类属于过度设计” | 小类才是正确的工程实践。 |
| “只多加一个方法” | 上帝类每次都是这样开始的。 |
| “以后可以重构” | 你不会重构。技术债会不断累积。 |
| “这个类已经很大了” | 这正是应该停下的理由,而不是继续的理由。 |
| “这些功能相关” | 相关 ≠ 相同职责。 |
| “分节注释有助于浏览” | 如果需要导航,说明类太大了。 |
快速参考
| 症状 | 操作 |
|---|---|
| 一个类执行 X 和 Y | 拆分为 XService 和 YService |
| 添加无关方法 | 创建新类 |
| 文件超过 200 行 | 寻找拆分机会 |
| 有多个修改原因 | 每个原因对应一个类 |
| 名称中含有“Manager/Handler/Processor” | 使用更具体的名称或拆分类 |
归根结底
一个类。一项职责。一个修改原因。
当有人施压要求违反这一原则时:提出异议、记录情况,或仍然创建合理的结构。
无论时间压力、现有代码还是权威要求如何,巨型类都不是答案。