mcpField
C
clean-code

clean-code

github.com/ratacat开发58359 次安装37 周前更新
代码仓库

关于 clean-code

面向软件开发者的整洁代码技能,汇总可读、易测试代码的实践,涵盖命名、函数、注释、错误处理、类、测试与代码异味,并附有章节索引。

主要功能

  1. 01体现意图的命名
  2. 02小而专注的函数
  3. 03注释与错误处理建议
  4. 04类设计与内聚原则
  5. 05测试与 TDD 实践
  6. 06代码异味参考

适用场景

  1. 01检查代码可读性问题
  2. 02重构过大的函数和类
  3. 03改进单元测试结构
  4. 04识别重复代码与死代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ratacat/claude-skills --skill clean-code

安装后在 Claude Code 中输入/clean-code确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

chapters/
classes.md
comments.md
error-handling.md
functions.md
names.md
objects-and-data.md
tests.md

详细介绍

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 - 错误处理(异常、null 处理、特例模式)
  • chapters/tests.md - 单元测试(TDD、F.I.R.S.T.、整洁的测试)
  • chapters/classes.md - 类(SRP、内聚性、OCP、DIP)
  • smells-and-heuristics.md - 完整的代码异味参考(66 种异味及其说明)

快速参考:名称

名称应揭示意图,并便于搜索。

规则不佳良好
揭示意图delapsedTimeInDays
避免误导accountList(实际不是 List)accounts
做出区分a1, a2source, destination
易于发音genymdhmsgenerationTimestamp
便于搜索7MAX_CLASSES_PER_STUDENT
类名 = 名词ProcessCustomer, Account
方法名 = 动词datapostPayment(), save()

避免: 在类名中使用 Manager、Processor、Data、Info——这些名称暗示职责不明确。

关键见解: 如果你需要用注释解释变量是什么,不如直接重命名它。

快速参考:函数

大小和范围
  • 理想长度: 4-10 行,通常不超过 20 行
  • 缩进层级: 最多一到两层
  • 只做一件事 — 如果你能提取出另一个名称不重复描述原意的函数,那么当前函数做得太多了
参数
数量建议
0最佳
1良好
2可以接受
3+避免——封装到对象中

标志参数(布尔值)很糟糕。 它们表明函数要做两件事。应将其拆分:

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

# Good
def render_for_suite(): ...
def render_for_single_test(): ...
关键规则
  • 命令查询分离: 要么执行操作,要么回答问题,不能两者兼做
  • 无副作用: 如果 checkPassword() 还会初始化会话,它就是在说谎
  • 优先使用异常而非错误码: 将正常流程与错误处理分开
  • 提取 try/catch 块: 错误处理是一件独立的事

快速参考:注释

注释充其量是必要之恶。正确使用注释,是为了弥补我们无法用代码清楚表达自己的不足。

删除以下注释
  • 冗余注释 — 重述代码已经表达的内容
  • 日志/变更记录 — 使用 git
  • 注释掉的代码 — 这是糟糕的做法,git 会记住
  • 噪声注释 — // default constructor、// increment i
  • 右花括号注释 — } // end if 意味着嵌套层级太多
可以接受的注释
  • 法律声明
  • 解释意图(为什么,而不是什么)
  • 提示后果(// takes 30 minutes)
  • TODO(但要及时清理)
  • 澄清外部库的行为

规则: 当你想要添加注释时,先尝试重构代码,让注释变得多余。

快速参考:错误处理

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

规则详情
优先使用异常,而不是返回码将算法与错误处理分开
提供上下文包含失败的操作和失败类型
封装第三方 API最大限度减少依赖,支持模拟
使用特例模式返回能处理特例的对象(空列表、默认值)
不要返回 null会带来额外工作,还可能引发 NullPointerException
不要传入 null比返回 null 更糟——默认情况下禁止这样做
# Bad - null checks everywhere
if employees is not None:
    for e in employees:
        total += e.pay

# Good - return empty collection instead of null
for e in get_employees():  # Returns [] if none
    total += e.pay

快速参考:类

单一职责原则(SRP)

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

检验:

  • 你能为它取一个简洁的名称吗?(避免使用 Manager、Processor、Super)
  • 你能在不使用“如果”“和”“或”“但是”的情况下,用 25 个词描述它吗?
内聚性

方法应该使用类的实例变量。如果某些方法围绕特定变量聚集,而不使用其他变量,就应该拆分类。

开闭原则(OCP)

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

依赖倒置原则(DIP)

依赖抽象,而不是具体细节。注入依赖以便于测试。

# Bad - can't test without network
class Portfolio:
    def __init__(self):
        self.exchange = TokyoStockExchange()

# Good - injectable, testable
class Portfolio:
    def __init__(self, exchange: StockExchange):
        self.exchange = exchange

快速参考:测试

TDD 三定律
  1. 在编写失败的测试之前,不要编写生产代码
  2. 编写的测试不要超过足以让测试失败的范围
  3. 编写的生产代码不要超过足以让测试通过的范围
F.I.R.S.T. 原则
  • 快速(Fast) — 快速运行,这样你就能经常运行
  • 独立(Independent) — 彼此之间不要相互依赖
  • 可重复(Repeatable) — 在任何环境中结果都相同
  • 自验证(Self-Validating) — 输出布尔结果(通过/失败)
  • 及时(Timely) — 在编写生产代码之前立即编写
整洁的测试
  • 可读性至关重要
  • 使用 构建-操作-检查 模式
  • 创建特定于领域的测试语言
  • 每个测试一个概念(不一定只有一个断言)

警告: 测试代码和生产代码同样重要。如果任由测试腐坏,你的代码也会腐坏。

对象与数据结构

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

认为一切都是对象的想法是个误区。 有时,你需要的是简单的数据结构,以及对其进行操作的过程。

迪米特法则

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

  • 类自身
  • 它创建的对象
  • 作为参数传入的对象
  • 保存在实例变量中的对象

不要调用允许使用的方法所返回对象的方法(链式调用灾难):

# Bad
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)

最关键的代码异味

在第 17 章的完整列表中,以下是最重要的几项:

G5:重复

软件领域万恶之源。 每处重复都意味着错失了一次抽象机会:

  • 相同代码 → 提取为函数
  • 重复的 switch/if-else → 多态
  • 相似算法 → 模板方法或策略模式
G30:函数应该只做一件事

如果你能从中提取出另一个函数,说明原函数做的不止一件事。

N1:选择描述性名称

名称决定了代码可读性的 90%。花时间慎重选择。

F1:参数过多

零个最好,其次是一个、两个、三个。更多参数则需要给出理由。

F3:标志参数

布尔参数意味着函数在做两件事。将其拆分。

G9:死代码

不会执行的代码。删除它——版本控制会记住。

G11:不一致

如果某件事采用一种方式处理,所有类似的事情也都应采用相同方式。

C5:注释掉的代码

令人厌恶。立即删除。

精工之道

“编写整洁的代码,需要有纪律地运用无数细小技巧,而这份纪律源于经过艰苦培养的‘整洁感’。代码感是关键。”

整洁的代码不是机械地遵循规则写出来的,而是源自推动我们践行规范的价值观——热爱精工、尊重代码的读者,并为专业的工作成果感到自豪。

怎样才能写出整洁的代码? 初稿总是笨拙的——函数很长、循环嵌套、名称随意、代码重复。你需要不断打磨:拆分函数、修改名称、消除重复、缩短方法。没人能从一开始就写出整洁的代码。

让软件正常运行与让代码保持整洁,是两项不同的工作。我们大多数人的脑力有限,所以会先专注于让代码正常运行。问题在于,我们当中有太多人认为,程序能运行就算完工了。 我们没有转而关注组织结构和整洁性,而是继续处理下一个问题,没有回头把臃肿的类拆分为彼此解耦的单元。

别这样做。回过头来。把代码整理好。让它比你接手时更好。

评论

支持 Markdown