single-responsibility-principle

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Single Responsibility Principle (SRP)

单一职责原则(SRP)

Overview

概述

A class should have only one reason to change.
Every module, class, or function should have responsibility over a single part of functionality. If you can describe what a class does using "AND", it has too many responsibilities.
一个类应该只有一个变更理由。
每个模块、类或函数都应该只负责单一功能领域的部分。如果你能用“和”来描述一个类的功能,说明它承担了过多职责。

When to Use

适用场景

  • Creating any new class, module, or service
  • Adding methods to existing classes
  • Reviewing code that "does multiple things"
  • Feeling pressure to "just add it here"
  • 创建任何新类、模块或服务
  • 向现有类添加方法
  • 评审“身兼数职”的代码
  • 迫于压力想“直接加在这里”的时候

The Iron Rule

铁律

NEVER add functionality that introduces a second reason to change.
No exceptions:
  • Not for "it's faster this way"
  • Not for "it's just one more method"
  • Not for "refactoring would take too long"
  • Not for "my tech lead said so"
  • Not for "it's already in production"
Violating SRP under pressure is still violating SRP.
绝不添加会引入第二个变更理由的功能。
无一例外:
  • 不要以“这样更快”为借口
  • 不要以“只是多一个方法”为借口
  • 不要以“重构太费时间”为借口
  • 不要以“技术主管这么说”为借口
  • 不要以“已经上线了”为借口
迫于压力违反SRP仍然是违反SRP。

Detection: The "AND" Test

检测方法:“和”测试

Describe your class in one sentence. If it contains "AND", split it.
DescriptionVerdict
"Handles user authentication"✅ Single responsibility
"Handles authentication AND sends emails"❌ Two responsibilities
"Manages orders AND processes payments AND tracks inventory"❌ Three responsibilities
用一句话描述你的类。如果句子里包含“和”,就拆分它。
描述结论
“处理用户认证”✅ 单一职责
“处理认证和发送邮件”❌ 两个职责
“管理订单、处理支付和跟踪库存”❌ 三个职责

Detection: Reasons to Change

检测方法:变更理由清单

List why this class might need to change:
typescript
// ❌ 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() {} }
列出这个类可能需要变更的理由:
typescript
// ❌ 错误示例:UserManager - 4个变更理由
class UserManager {
  login() {}           // 认证逻辑变更
  updateProfile() {}   // 个人资料需求变更  
  sendEmail() {}       // 邮件服务商变更
  trackAnalytics() {}  // 数据分析需求变更
}

// ✅ 正确示例:按职责拆分
class AuthService { login() {} }
class ProfileService { updateProfile() {} }
class NotificationService { sendEmail() {} }
class AnalyticsService { track() {} }

Pressure Resistance Protocol

抗压指南

When pressured to violate SRP, follow this:
当你迫于压力要违反SRP时,请遵循以下步骤:

1. Time Pressure

1. 时间压力

"Just make it work quickly"
Response: Creating a god class takes the same time as creating focused classes. The "quick" solution creates technical debt that costs 10x more later.
Action: Create separate classes. It's not slower.
“先快速搞定就行”
回应: 创建一个全能类和创建多个专注类所花的时间是一样的。这种“快速”方案会产生技术债务,后续成本会是现在的10倍。
行动: 创建独立的类。并不会更慢。

2. Sunk Cost Pressure

2. 沉没成本压力

"The class already exists, just add to it"
Response: Adding to a bloated class makes it worse. The fact that it's already wrong doesn't justify making it more wrong.
Action: Create a new focused class. Refactor the existing one if time permits.
“这个类已经存在了,直接加进去就行”
回应: 向臃肿的类添加功能只会让情况更糟。它本身就设计不合理,不能成为继续错下去的理由。
行动: 创建一个新的专注类。如果时间允许,重构现有类。

3. Authority Pressure

3. 权威压力

"My tech lead said put it all in one class"
Response: Respectfully push back with evidence. If overruled, document your concern and comply—but NEVER silently create god classes.
Action:
"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. Scope Creep

4. 范围蔓延

"While you're in there, also add X"
Response: New functionality = new class (or existing appropriate class).
Action: "X belongs in its own service. I'll create XService."
“既然你已经在改了,顺便把X也加上吧”
回应: 新功能应该对应新类(或已有合适的类)。
行动: “X应该属于独立的服务。我会创建XService。”

Red Flags - STOP and Reconsider

危险信号——立即停止并重新考虑

If you notice ANY of these, you're about to violate SRP:
  • Adding a method unrelated to the class's core purpose
  • Class file exceeds 200 lines
  • Class has more than 5-7 public methods
  • You need section comments to navigate the class
  • Multiple developers would edit this class for unrelated features
  • Class name contains "Manager", "Handler", "Processor", "Service" with no specific domain
All of these mean: Split the class.
如果你注意到以下任何一种情况,说明你即将违反SRP:
  • 添加与类核心用途无关的方法
  • 类文件超过200行
  • 类有5-7个以上的公共方法
  • 需要用分段注释来导航类的内容
  • 多个开发人员会因不相关的功能修改这个类
  • 类名包含“Manager”“Handler”“Processor”“Service”但没有具体领域限定
出现以上任何一种情况都意味着:拆分这个类。

Refactoring Existing Violations

重构现有违规代码

When you encounter an existing god class:
  1. Don't make it worse - Never add more responsibilities
  2. Extract on touch - When modifying, extract the part you're touching
  3. Document debt - If you can't refactor now, create a ticket
typescript
// Found: OrderService with 500 lines handling orders, payments, inventory, emails

// ❌ WRONG: Add shipping logic to OrderService
// ✅ RIGHT: Create ShippingService, note that OrderService needs refactoring
当你遇到一个全能类时:
  1. 不要雪上加霜 - 绝不要添加更多职责
  2. 触达即提取 - 修改时,提取你正在处理的部分
  3. 记录债务 - 如果现在无法重构,创建一个工单
typescript
// 现状:OrderService有500行代码,处理订单、支付、库存、邮件

// ❌ 错误:向OrderService添加物流逻辑
// ✅ 正确:创建ShippingService,记录OrderService需要重构

Common Rationalizations (All Invalid)

常见借口(全不成立)

ExcuseReality
"It's faster to put it in one class"It's not. You type the same code either way.
"Small classes are over-engineering"Small classes are correct engineering.
"It's just one more method"That's how god classes start. Every time.
"We can refactor later"You won't. Tech debt compounds.
"The class is already big"That's a reason to stop, not continue.
"It's related functionality"Related ≠ same responsibility.
"Section comments help navigate"If you need navigation, class is too big.
借口真相
“放在一个类里更快”并没有。两种方式敲的代码量一样。
“小类是过度设计”小类是正确的工程设计。
“只是多一个方法而已”全能类都是这么开始的。每次都是。
“我们以后可以重构”你们不会的。技术债务会不断累积。
“这个类已经很大了”这是停止的理由,不是继续的理由。
“这是相关功能”相关≠同一职责。
“分段注释有助于导航”如果需要导航,说明类太大了。

Quick Reference

速查表

SymptomAction
Class does X AND YSplit into XService and YService
Adding unrelated methodCreate new class
File > 200 linesLook for extraction opportunities
Multiple reasons to changeOne class per reason
"Manager/Handler/Processor" nameBe more specific or split
症状行动
类做X和Y拆分为XService和YService
添加不相关方法创建新类
文件超过200行寻找提取机会
多个变更理由一个理由对应一个类
类名是“Manager/Handler/Processor”更具体命名或拆分

The Bottom Line

核心结论

One class. One responsibility. One reason to change.
When pressured to violate this: push back, document, or create the right structure anyway.
God classes are never the answer, regardless of time pressure, existing code, or authority demands.
一个类。一个职责。一个变更理由。
当迫于压力要违反这一原则时:提出反对、记录情况,或者无论如何都创建正确的结构。
无论时间压力、现有代码情况或权威要求如何,全能类永远不是解决方案。