clean-code
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClean Code
代码整洁之道
Overview
概述
Clean code reads like well-written prose. Every name reveals intent. Every function tells a story. Every class has a single purpose. The goal isn't just working code—it's code that others can understand quickly, modify safely, and extend confidently.
"Clean code always looks like it was written by someone who cares." — Michael Feathers
"You know you are working on clean code when each routine turns out to be pretty much what you expected." — Ward Cunningham
The Boy Scout Rule: Leave the code cleaner than you found it. Every commit should improve quality, even if just slightly. Small improvements compound.
整洁的代码读起来就像文笔流畅的散文。每个命名都清晰传达意图,每个函数都讲着完整的故事,每个类都有单一职责。我们的目标不只是让代码能运行,更是要让他人能快速理解、安全修改、自信扩展。
“整洁的代码总是看起来出自用心之人之手。”——Michael Feathers
“当你发现每个程序单元都和你预期的差不多时,你就是在和整洁代码打交道。”——Ward Cunningham
童子军规则: 让代码比你接手时更整洁。每次提交都要提升代码质量,哪怕只是微小的改进。小进步会不断积累。
Chapter References
章节参考
This skill provides an overview with quick references. For detailed guidance with examples, see the chapter files:
- - Meaningful Names (intention-revealing, searchable, pronounceable)
chapters/names.md - - Functions (small, do one thing, few arguments)
chapters/functions.md - - Comments (why to avoid, what's acceptable)
chapters/comments.md - - Objects and Data Structures (Law of Demeter, DTOs)
chapters/objects-and-data.md - - Error Handling (exceptions, null handling, Special Case Pattern)
chapters/error-handling.md - - Unit Tests (TDD, F.I.R.S.T., clean tests)
chapters/tests.md - - Classes (SRP, cohesion, OCP, DIP)
chapters/classes.md - - Complete code smells reference (66 smells with explanations)
smells-and-heuristics.md
本内容提供了快速参考概览。如需带示例的详细指导,请查看章节文件:
- - 有意义的命名(传达意图、便于搜索、可读可发音)
chapters/names.md - - 函数设计(短小、单一职责、参数精简)
chapters/functions.md - - 注释规范(应避免的类型、可接受的场景)
chapters/comments.md - - 对象与数据结构(迪米特法则、DTO)
chapters/objects-and-data.md - - 错误处理(异常、空值处理、特殊用例模式)
chapters/error-handling.md - - 单元测试(TDD、F.I.R.S.T.原则、整洁测试)
chapters/tests.md - - 类设计(SRP、内聚性、OCP、DIP)
chapters/classes.md - - 完整代码坏味道参考(66种坏味道及解释)
smells-and-heuristics.md
Quick Reference: Names
快速参考:命名
Names should reveal intent and be searchable.
| Rule | Bad | Good |
|---|---|---|
| Reveal intent | | |
| Avoid disinformation | | |
| Make distinctions | | |
| Pronounceable | | |
| Searchable | | |
| Classes = nouns | | |
| Methods = verbs | | |
Avoid: , , , in class names—they hint at unclear responsibilities.
ManagerProcessorDataInfoKey insight: If you need a comment to explain what a variable is, rename it instead.
命名应清晰传达意图且便于搜索。
| 规则 | 反面示例 | 正面示例 |
|---|---|---|
| 传达意图 | | |
| 避免误导 | | |
| 明确区分 | | |
| 可读可发音 | | |
| 便于搜索 | | |
| 类名用名词 | | |
| 方法名用动词 | | |
应避免: 类名中使用、、、——这些词暗示职责不清晰。
ManagerProcessorDataInfo核心见解: 如果你需要用注释解释变量含义,不如直接重命名它。
Quick Reference: Functions
快速参考:函数
Size and Scope
大小与范围
- Ideal: 4-10 lines, rarely over 20
- Indent level: Never more than one or two
- Do one thing — if you can extract another function with a non-restating name, it's doing too much
- 理想长度: 4-10行,极少超过20行
- 缩进层级: 不超过1-2层
- 单一职责 —— 如果你能提取出另一个名称不重复的函数,说明原函数职责过多
Arguments
参数数量
| Count | Guidance |
|---|---|
| 0 | Best |
| 1 | Good |
| 2 | Acceptable |
| 3+ | Avoid—wrap in object |
Flag arguments (booleans) are ugly. They proclaim the function does two things. Split it:
python
undefined| 数量 | 指导原则 |
|---|---|
| 0 | 最佳 |
| 1 | 良好 |
| 2 | 可接受 |
| 3+ | 应避免——封装为对象 |
标记参数(布尔值)很糟糕,它表明函数在做两件事。应拆分函数:
python
undefinedBad
反面示例
def render(is_suite: bool): ...
def render(is_suite: bool): ...
Good
正面示例
def render_for_suite(): ...
def render_for_single_test(): ...
undefineddef render_for_suite(): ...
def render_for_single_test(): ...
undefinedKey Rules
核心规则
- Command Query Separation: Do something OR answer something, not both
- No side effects: If also initializes a session, it lies
checkPassword() - Prefer exceptions to error codes: Separates happy path from error handling
- Extract try/catch blocks: Error handling is one thing
- 命令查询分离: 要么执行操作,要么返回结果,不可两者兼具
- 无副作用: 如果同时初始化会话,这是一种“欺骗”
checkPassword() - 优先使用异常而非错误码: 将主逻辑与错误处理分离
- 提取try/catch块: 错误处理是单一职责
Quick Reference: Comments
快速参考:注释
Comments are, at best, a necessary evil. The proper use of comments is to compensate for our failure to express ourselves in code.
注释充其量是必要的恶。注释的恰当用途是弥补我们无法用代码清晰表达的不足。
Delete These Comments
应删除的注释
- Redundant — restating what code says
- Journal/changelog — use git
- Commented-out code — an abomination, git remembers
- Noise — ,
// default constructor// increment i - Closing brace — means too much nesting
} // end if
- 冗余注释 —— 重复代码已表达的内容
- 日志/变更记录 —— 用git记录
- 被注释掉的代码 —— 这是糟粕,git会保留历史版本
- 无意义注释 —— 、
// 默认构造函数// 递增i - 闭合括号注释 —— 意味着嵌套层级过深
} // end if
Acceptable Comments
可接受的注释
- Legal notices
- Explanation of intent (why, not what)
- Warning of consequences ()
// takes 30 minutes - TODO (but clean them up)
- Clarifying external library behavior
The Rule: When you feel the urge to comment, first try to refactor the code so the comment would be unnecessary.
- 法律声明
- 意图解释(说明原因而非内容)
- 后果警告(如)
// 执行需30分钟 - TODO注释(但需及时清理)
- 第三方库行为说明
规则: 当你想要写注释时,先尝试重构代码,让注释变得多余。
Quick Reference: Error Handling
快速参考:错误处理
Error handling is important, but if it obscures logic, it's wrong.
| Rule | Details |
|---|---|
| Use exceptions over return codes | Separates algorithm from error handling |
| Provide context | Include operation that failed and type of failure |
| Wrap third-party APIs | Minimizes dependencies, enables mocking |
| Use Special Case Pattern | Return object that handles special case (empty list, default values) |
| Don't return null | Creates work, invites NullPointerException |
| Don't pass null | Worse than returning null—forbid it by default |
python
undefined错误处理很重要,但如果它掩盖了核心逻辑,那就是错误的实现方式。
| 规则 | 细节说明 |
|---|---|
| 优先使用异常而非返回码 | 将算法与错误处理分离 |
| 提供上下文信息 | 包含失败的操作及失败类型 |
| 封装第三方API | 减少依赖,便于Mock测试 |
| 使用特殊用例模式 | 返回处理特殊场景的对象(如空列表、默认值) |
| 不要返回null | 增加额外工作,易引发NullPointerException |
| 不要传递null | 比返回null更糟——默认禁止传递null |
python
undefinedBad - null checks everywhere
反面示例——到处做空值检查
if employees is not None:
for e in employees:
total += e.pay
if employees is not None:
for e in employees:
total += e.pay
Good - return empty collection instead of null
正面示例——返回空集合而非null
for e in get_employees(): # Returns [] if none
total += e.pay
undefinedfor e in get_employees(): # 无数据时返回[]
total += e.pay
undefinedQuick Reference: Classes
快速参考:类
Single Responsibility Principle (SRP)
单一职责原则(SRP)
A class should have one, and only one, reason to change.
Tests:
- Can you derive a concise name? (Avoid ,
Manager,Processor)Super - Can you describe it in 25 words without "if," "and," "or," "but"?
一个类应该有且仅有一个发生变化的原因。
检验方法:
- 能否为类起一个简洁明确的名称?(避免、
Manager、Processor这类模糊名称)Super - 能否用25个单词以内描述类的职责,且不使用“if”、“and”、“or”、“but”?
Cohesion
内聚性
Methods should use the class's instance variables. When methods cluster around certain variables but not others, the class should be split.
类的方法应使用类的实例变量。当方法仅围绕部分变量而非全部变量时,应拆分该类。
Open-Closed Principle (OCP)
开闭原则(OCP)
Classes should be open for extension but closed for modification. Add new behavior via subclassing, not modifying existing code.
类应对扩展开放,对修改关闭。通过子类添加新行为,而非修改现有代码。
Dependency Inversion Principle (DIP)
依赖倒置原则(DIP)
Depend on abstractions, not concrete details. Inject dependencies for testability.
python
undefined依赖抽象而非具体实现。通过依赖注入提升可测试性。
python
undefinedBad - can't test without network
反面示例——无法脱离网络环境测试
class Portfolio:
def init(self):
self.exchange = TokyoStockExchange()
class Portfolio:
def init(self):
self.exchange = TokyoStockExchange()
Good - injectable, testable
正面示例——可注入依赖,便于测试
class Portfolio:
def init(self, exchange: StockExchange):
self.exchange = exchange
undefinedclass Portfolio:
def init(self, exchange: StockExchange):
self.exchange = exchange
undefinedQuick Reference: Tests
快速参考:测试
The Three Laws of TDD
TDD三定律
- Don't write production code until you have a failing test
- Don't write more test than sufficient to fail
- Don't write more production code than sufficient to pass
- 除非有一个失败的测试,否则不编写生产代码
- 不编写超出当前失败所需的测试代码
- 不编写超出通过当前测试所需的生产代码
F.I.R.S.T. Principles
F.I.R.S.T.原则
- Fast — Run quickly so you run them often
- Independent — Don't depend on each other
- Repeatable — Same result in any environment
- Self-Validating — Boolean output (pass/fail)
- Timely — Written just before production code
- Fast(快速) —— 运行速度快,便于频繁执行
- Independent(独立) —— 测试用例之间互不依赖
- Repeatable(可重复) —— 在任何环境下都能得到相同结果
- Self-Validating(自验证) —— 输出布尔结果(通过/失败)
- Timely(及时) —— 编写生产代码前先写测试
Clean Tests
整洁测试
- Readability is paramount
- Use BUILD-OPERATE-CHECK pattern
- Create domain-specific testing language
- One concept per test (not necessarily one assert)
Warning: Test code is just as important as production code. If you let tests rot, your code will rot too.
- 可读性 是首要原则
- 使用 BUILD-OPERATE-CHECK(构建-操作-验证) 模式
- 构建领域特定测试语言
- 每个测试对应一个概念(不一定是一个断言)
警告: 测试代码和生产代码同等重要。如果测试代码腐化,生产代码也会跟着腐化。
Objects vs Data Structures
对象 vs 数据结构
| Concept | Hides | Exposes | Easy to add... |
|---|---|---|---|
| Objects | Data | Functions | New types |
| Data Structures | Nothing | Data | New functions |
The idea that everything is an object is a myth. Sometimes you want simple data structures with procedures operating on them.
| 概念 | 隐藏 | 暴露 | 易于添加... |
|---|---|---|---|
| 对象 | 数据 | 函数 | 新类型 |
| 数据结构 | 无 | 数据 | 新函数 |
“万物皆对象”是误区。 有时你只需要简单的数据结构,以及操作它们的过程。
Law of Demeter
迪米特法则
A method should only call methods of:
- The class itself
- Objects it creates
- Objects passed as arguments
- Objects held in instance variables
Don't call methods on objects returned by allowed functions (train wrecks):
python
undefined方法只能调用以下对象的方法:
- 类自身
- 方法创建的对象
- 方法参数传入的对象
- 类实例变量持有的对象
不要 调用允许调用的函数返回的对象的方法(链式调用的“火车失事”):
python
undefinedBad
反面示例
output_dir = ctxt.get_options().get_scratch_dir().get_absolute_path()
output_dir = ctxt.get_options().get_scratch_dir().get_absolute_path()
Good - tell the object to do the work
正面示例——告诉对象去完成工作
bos = ctxt.create_scratch_file_stream(class_file_name)
undefinedbos = ctxt.create_scratch_file_stream(class_file_name)
undefinedThe Most Critical Smells
最关键的代码坏味道
From Chapter 17's comprehensive list, these are the most important:
来自第17章的完整列表中,以下是最重要的几项:
G5: Duplication
G5: 重复代码
The root of all evil in software. Every duplication is a missed abstraction opportunity:
- Identical code → extract to function
- Repeated switch/if-else → polymorphism
- Similar algorithms → Template Method or Strategy pattern
这是软件领域万恶之源。 每一处重复都是错失的抽象机会:
- 完全相同的代码 → 提取为函数
- 重复的switch/if-else → 用多态替代
- 相似的算法 → 使用模板方法或策略模式
G30: Functions Should Do One Thing
G30: 函数应单一职责
If you can extract another function from it, the original was doing more than one thing.
如果你能从函数中提取出另一个函数,说明原函数职责过多。
N1: Choose Descriptive Names
N1: 选择有意义的命名
Names are 90% of what makes code readable. Take time to choose wisely.
命名决定了代码可读性的90%。花时间选一个好名字。
F1: Too Many Arguments
F1: 参数过多
Zero is best, then one, two, three. More requires justification.
零参数最佳,其次是1个、2个、3个。更多参数需要合理的理由。
F3: Flag Arguments
F3: 标记参数
Boolean parameters mean the function does two things. Split it.
布尔参数意味着函数在做两件事。应拆分函数。
G9: Dead Code
G9: 死代码
Code that isn't executed. Delete it—version control remembers.
未被执行的代码。删除它——版本控制系统会保留历史。
G11: Inconsistency
G11: 不一致性
If you do something one way, do all similar things the same way.
如果一件事用某种方式处理,所有类似的事都应采用相同方式。
C5: Commented-Out Code
C5: 被注释掉的代码
An abomination. Delete it immediately.
这是糟粕。立即删除它。
The Craft
匠艺精神
"Writing clean code requires the disciplined use of a myriad little techniques applied through a painstakingly acquired sense of 'cleanliness.' The code-sense is the key."
Clean code isn't written by following rules mechanically. It comes from values that drive disciplines—caring about craft, respecting readers of your code, and taking pride in professional work.
How do you write clean code? First drafts are clumsy—long functions, nested loops, arbitrary names, duplication. You refine: break out functions, change names, eliminate duplication, shrink methods. Nobody writes clean code from the start.
Getting software to work and making it clean are different activities. Most of us have limited room in our heads, so we focus on getting code to work first. The problem is that too many of us think we are done once the program works. We fail to switch to organization and cleanliness. We move on to the next problem rather than going back and breaking overstuffed classes into decoupled units.
Don't. Go back. Clean it up. Leave it better than you found it.
“编写整洁代码需要自觉运用无数小技巧,而这些技巧来自于辛苦培养出的‘整洁感’。这种代码直觉是关键。”
整洁代码不是机械遵循规则就能写出来的。它源于驱动行为的价值观——重视匠艺、尊重代码的阅读者、为专业工作感到自豪。
如何编写整洁代码? 初稿往往笨拙——函数冗长、循环嵌套、命名随意、代码重复。你需要不断打磨:拆分函数、修改命名、消除重复、精简方法。没人能一开始就写出整洁的代码。
让软件运行起来和让软件整洁是两件不同的事。我们大多数人的思维容量有限,所以先专注于让代码运行。问题在于,太多人认为程序能运行就完工了。 我们没有切换到代码组织和整洁化的工作,而是去处理下一个问题,而非回头把臃肿的类拆分为解耦的单元。
别这么做。回头去整理。把代码清理干净。让它比你接手时更整洁。