整洁代码Skill clean-code

整洁代码技能用于提升软件代码质量,专注于编写易于理解、维护和扩展的代码。它涵盖命名规范、函数设计、错误处理、单元测试、类结构、注释管理、代码重构等方面,基于Robert C. Martin的清洁代码原则。适用于软件开发人员、架构师和测试工程师,旨在提高团队协作效率和代码可维护性。SEO关键词:代码整洁、编程规范、软件设计、代码重构、单元测试、错误处理、类设计、命名约定、代码质量、软件开发最佳实践。

架构设计 0 次安装 0 次浏览 更新于 3/9/2026

name: clean-code description: 在编写、审查或重构代码时使用。适用于命名变量或函数、结构化类、处理错误、编写测试,或当代码感觉复杂或难以理解时。基于Robert C. Martin的《Clean Code》。

整洁代码

概述

整洁代码读起来像写得好的散文。每个名称都揭示意图。每个函数都讲述一个故事。每个类都有单一目的。目标不仅仅是让代码工作——而是让代码能被其他人快速理解、安全修改和自信扩展。

“整洁代码总是看起来像是关心它的人写的。” — Michael Feathers

“当每个例程都大致符合你的预期时,你就知道你在编写整洁代码了。” — Ward Cunningham

童子军规则: 让代码比你找到时更整洁。每次提交都应该提高质量,即使只是轻微改进。小的改进会累积。

章节参考

本技能提供概述和快速参考。详细指导和示例,请参见章节文件:

  • chapters/names.md - 有意义的名称(意图揭示、可搜索、可发音)
  • chapters/functions.md - 函数(小、做一件事、参数少)
  • chapters/comments.md - 注释(为什么避免、什么是可接受的)
  • chapters/objects-and-data.md - 对象和数据结构(德米特法则、DTO)
  • chapters/error-handling.md - 错误处理(异常、空值处理、特殊案例模式)
  • chapters/tests.md - 单元测试(TDD、F.I.R.S.T.、清洁测试)
  • chapters/classes.md - 类(SRP、内聚性、OCP、DIP)
  • smells-and-heuristics.md - 完整代码异味参考(66个异味及解释)

快速参考:名称

名称应揭示意图并可搜索。

规则 坏例子 好例子
揭示意图 d elapsedTimeInDays
避免误导信息 accountList(不是List) accounts
做区分 a1, a2 source, destination
可发音 genymdhms generationTimestamp
可搜索 7 MAX_CLASSES_PER_STUDENT
类名 = 名词 Process Customer, Account
方法名 = 动词 data postPayment(), save()

避免: 在类名中使用ManagerProcessorDataInfo——它们暗示职责不清晰。

关键洞察: 如果你需要注释来解释变量是什么,就重命名它。

快速参考:函数

大小和作用域

  • 理想: 4-10行,很少超过20行
  • 缩进级别: 永远不要超过一或两级
  • 做一件事 — 如果你能提取另一个函数,且名称不重复,那么它做得太多了

参数

数量 指导
0 最好
1
2 可接受
3+ 避免——封装到对象中

标志参数(布尔值)很丑。 它们宣告函数做两件事。拆分它:

# 坏
def render(is_suite: bool): ...

# 好
def render_for_suite(): ...
def render_for_single_test(): ...

关键规则

  • 命令查询分离: 做某事或回答某事,不要同时做
  • 无副作用: 如果checkPassword()也初始化会话,它就在撒谎
  • 优先异常而非错误码: 分离正常路径和错误处理
  • 提取try/catch块: 错误处理是一件事

快速参考:注释

注释充其量是必要的邪恶。注释的正确用途是弥补我们在代码中表达自己失败的地方。

删除这些注释

  • 冗余 — 重复代码所说的
  • 日志/变更日志 — 使用git
  • 注释掉的代码 — 一种恶行,git记得
  • 噪音// 默认构造函数, // 增加i
  • 关闭大括号} // 结束if意味着嵌套太多

可接受的注释

  • 法律声明
  • 意图解释(为什么,不是是什么)
  • 后果警告(// 需要30分钟
  • TODO(但清理它们)
  • 澄清外部库行为

规则: 当你感到想写注释时,先尝试重构代码,使注释变得不必要。

快速参考:错误处理

错误处理很重要,但如果它掩盖了逻辑,那就是错的。

规则 详情
使用异常而非返回码 分离算法和错误处理
提供上下文 包括失败的操作和失败类型
包装第三方API 最小化依赖,启用模拟
使用特殊案例模式 返回处理特殊案例的对象(空列表、默认值)
不要返回null 创造工作,招致NullPointerException
不要传递null 比返回null更糟——默认禁止它
# 坏 - 到处都是null检查
if employees is not None:
    for e in employees:
        total += e.pay

# 好 - 返回空集合而非null
for e in get_employees():  # 如果没有,返回[]
    total += e.pay

快速参考:类

单一职责原则(SRP)

一个类应该有一个,且只有一个,改变的理由。

测试:

  • 你能推导出简洁的名称吗?(避免ManagerProcessorSuper
  • 你能在25个词内描述它,而不使用“如果”、“和”、“或”、“但是”吗?

内聚性

方法应该使用类的实例变量。当方法围绕某些变量聚类但不围绕其他变量时,类应该拆分。

开闭原则(OCP)

类应该对扩展开放,但对修改关闭。通过子类化添加新行为,而不是修改现有代码。

依赖倒置原则(DIP)

依赖抽象,而非具体细节。注入依赖以提高可测试性。

# 坏 - 没有网络无法测试
class Portfolio:
    def __init__(self):
        self.exchange = TokyoStockExchange()

# 好 - 可注入、可测试
class Portfolio:
    def __init__(self, exchange: StockExchange):
        self.exchange = exchange

快速参考:测试

TDD三定律

  1. 直到你有失败的测试,才写生产代码
  2. 不写超过足以失败的测试
  3. 不写超过足以通过的生产代码

F.I.R.S.T.原则

  • 快速 — 快速运行,以便经常运行
  • 独立 — 不互相依赖
  • 可重复 — 在任何环境中相同结果
  • 自验证 — 布尔输出(通过/失败)
  • 及时 — 在生产代码之前编写

清洁测试

  • 可读性至关重要
  • 使用构建-操作-检查模式
  • 创建领域特定测试语言
  • 每个测试一个概念(不一定一个断言)

警告: 测试代码和生产代码一样重要。如果你让测试腐烂,你的代码也会腐烂。

对象 vs 数据结构

概念 隐藏 暴露 容易添加…
对象 数据 函数 新类型
数据结构 数据 新函数

一切都是对象的想法是神话。 有时你想要简单的数据结构,带有操作它们的程序。

德米特法则

一个方法应该只调用以下对象的方法:

  • 类本身
  • 它创建的对象
  • 作为参数传递的对象
  • 持有在实例变量中的对象

不要调用允许函数返回的对象上的方法(火车残骸):

# 坏
output_dir = ctxt.get_options().get_scratch_dir().get_absolute_path()

# 好 - 告诉对象做工作
bos = ctxt.create_scratch_file_stream(class_file_name)

最关键异味

来自第17章的完整列表,这些是最重要的:

G5:重复

软件中所有邪恶的根源。 每次重复都是错过的抽象机会:

  • 相同代码 → 提取到函数
  • 重复switch/if-else → 多态性
  • 相似算法 → 模板方法或策略模式

G30:函数应该做一件事

如果你能从它中提取另一个函数,那么原始函数就做了超过一件事。

N1:选择描述性名称

名称是使代码可读的90%。花时间明智选择。

F1:太多参数

零最好,然后一,二,三。更多需要理由。

F3:标志参数

布尔参数意味着函数做两件事。拆分它。

G9:死代码

未执行的代码。删除它——版本控制记得。

G11:不一致性

如果你以一种方式做某事,所有类似的事情都以相同方式做。

C5:注释掉的代码

一种恶行。立即删除它。

手艺

“编写整洁代码需要纪律性地应用无数小技巧,通过艰苦获得的‘清洁感’。代码感是关键。”

整洁代码不是机械地遵循规则写出来的。它来自驱动纪律的价值观——关心手艺、尊重代码读者,并以专业工作为荣。

你如何编写整洁代码? 初稿笨拙——长函数、嵌套循环、任意名称、重复。你精炼:拆出函数、更改名称、消除重复、缩小方法。没有人从一开始就写出整洁代码。

让软件工作和让它清洁是不同的活动。我们大多数人头脑中空间有限,所以我们首先专注于让代码工作。问题是,太多人认为一旦程序工作,我们就完成了。 我们未能切换到组织和清洁。我们转向下一个问题,而不是回去将过载的类拆分成解耦单元。

不要。回去。清理它。让它比你找到时更好。