npx skills add https://github.com/wondelai/skills --skill clean-code一种严谨的代码编写方法,旨在传达意图、减少意外并拥抱变化。在编写新代码、审查拉取请求、重构遗留系统或提供代码质量改进建议时,应用这些原则。
代码被阅读的次数远多于被编写的次数。为读者优化。 每一个命名选择、函数边界和格式决策,要么增加清晰度,要么增加成本。阅读代码与编写代码的时间比远超过 10:1。让代码更易于阅读,也就使其更易于编写、调试和扩展。
基础: 整洁的代码并非机械地遵循规则——而是关乎对技艺的用心。一个整洁的代码库读起来就像精心撰写的散文:名称揭示意图,函数逐步讲述故事,黑暗角落里没有潜伏的意外。童子军规则适用:总是让代码比你发现时更整洁。
目标:10/10。 在审查或编写代码时,根据对以下原则的遵守程度,给出 0-10 的评分。10/10 表示完全符合所有准则;较低的分数表示存在需要解决的差距。始终提供当前分数以及达到 10/10 所需的具体改进建议。
编写能够清晰沟通并适应变化的代码的六项准则:
核心理念: 名称应揭示意图,避免误导,并使代码读起来像散文。如果一个名称需要注释来解释,那么这个名称就是错误的。
为何有效: 名称是最普遍的文档形式。一个精心选择的名称消除了阅读实现细节的需要。一个糟糕的名称迫使每个读者去逆向工程作者的意图。
关键见解:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
fetchretrieveget代码应用:
| 上下文 | 模式 | 示例 |
|---|---|---|
| 变量 | 揭示意图的名称 | elapsedTimeInDays 而非 d 或 elapsed |
| 布尔值 | 谓词短语 | isActive、hasPermission、canEdit |
| 函数 | 动词 + 名词描述动作 | calculateMonthlyRevenue() 而非 calc() |
| 类 | 名词描述职责 | InvoiceGenerator 而非 InvoiceManager |
| 常量 | 可搜索,全大写带上下文 | MAX_RETRY_ATTEMPTS = 3 而非行内 3 |
| 集合 | 复数名词或描述性短语 | activeUsers 而非 list 或 data |
核心理念: 函数应该小巧,只做一件事,并把它做好。理想的函数长度为 4-6 行,接受零到两个参数,并在单一抽象层级上操作。
为何有效: 小函数易于命名、理解、测试和重用。当一个函数只做一件事时,它的名称可以精确描述它的功能,从而无需阅读函数体。长函数隐藏错误、难以测试,并会随时间积累职责。
关键见解:
代码应用:
| 上下文 | 模式 | 示例 |
|---|---|---|
| 长函数 | 提取为命名的步骤 | validateInput(); transformData(); saveRecord(); |
| 标志参数 | 拆分为两个函数 | renderForPrint() 和 renderForScreen() 而非 render(isPrint) |
| 深层嵌套 | 提取内部代码块 | 将嵌套的 if/for 体移到命名函数中 |
| 多重返回 | 顶部使用卫语句 | 对错误情况提前返回,单一成功路径 |
| 多个参数 | 引入参数对象 | new DateRange(start, end) 而非 report(start, end, format, locale) |
| 副作用 | 使副作用显式化 | 将 checkPassword() 重命名为 checkPasswordAndInitSession() 或进行分离 |
核心理念: 注释是在代码中未能表达自己的失败。好的代码是自文档化的。当注释必要时,它们应该解释 为什么,而不是 是什么。格式创建了使代码易于扫描的视觉结构。
为何有效: 注释会腐坏。代码会变化但注释通常不会,从而产生比没有文档更糟的误导性文档。整洁的格式——一致的缩进、概念间的垂直间距以及逻辑排序——让开发者像读者扫描报纸一样扫描代码:先看标题,需要时再看细节。
关键见解:
代码应用:
| 上下文 | 模式 | 示例 |
|---|---|---|
| 解释"是什么" | 用更好的名称替换 | 将 // check if eligible 重命名为 isEligible() |
| 解释"为什么" | 保留为注释 | // RFC 7231 requires this header for proxies |
| 注释掉的代码 | 删除它 | 相信版本控制会记住 |
| 文件组织 | 报纸隐喻 | 高层函数在顶部,细节在下面 |
| 相关代码 | 垂直分组 | 在同一文件中保持调用者靠近被调用者 |
| 团队格式 | 一次性约定规则 | 使用自动化格式化工具(Prettier、Black、gofmt) |
核心理念: 错误处理是与业务逻辑分离的关注点。使用异常而非返回码,为每个异常提供上下文,并且永远不要返回或传递 null。
为何有效: 返回码迫使调用者立即检查,用错误检查逻辑污染了正常路径。异常让你可以将正常路径与错误处理分离,使两者都更易于阅读。返回 null 迫使每个调用者添加 null 检查,而一个缺失的检查就会产生一个远离源头的 NullPointerException。
关键见解:
代码应用:
| 上下文 | 模式 | 示例 |
|---|---|---|
| 返回 null | 返回空集合或 Optional | return Collections.emptyList() 而非 return null |
| 错误码 | 用异常替换 | throw new InsufficientFundsException(balance, amount) |
| 第三方 API | 用适配器包装 | PortfolioService 包装供应商 API,转换异常 |
| null 参数 | 使用断言快速失败 | Objects.requireNonNull(user, "user must not be null") |
| 特例 | 空对象模式 | 使用具有默认行为的 GuestUser 而非 null 检查 |
| 错误中的上下文 | 包含操作 + 状态 | "Failed to save invoice #1234 for customer 'Acme'" |
核心理念: 测试是一等代码。它们必须整洁、可读,并以与生产代码相同的纪律进行维护。脏测试比没有测试更糟——它们变成了拖慢每次变更的负担。
为何有效: 整洁的测试作为可执行的文档,精确展示了系统预期的行为方式。它们为重构提供了安全网,并为每次变更提供了回归检查。没有测试,每次修改都是一个潜在的 bug。有了脏测试,每次修改都需要费力地理解难以理解的测试代码。
关键见解:
代码应用:
| 上下文 | 模式 | 示例 |
|---|---|---|
| 测试结构 | 准备-执行-验证 | 设置、执行、验证——清晰分离 |
| 测试命名 | 场景 + 预期行为 | shouldRejectExpiredToken 而非 test1 |
| 共享设置 | 提取构建器/工厂 | aUser().withRole(ADMIN).build() |
| 多个场景 | 参数化测试 | 一个测试方法,多个输入/输出对 |
| 不稳定测试 | 移除外部依赖 | 模拟时间、网络、文件系统 |
| 测试可读性 | 领域特定辅助函数 | assertThatInvoice(inv).isPaidInFull() |
核心理念: 代码异味是更深层次设计问题的表面指标。学会快速识别它们并应用有针对性的重构。并非每个异味都需要立即处理,但忽视它们会积累技术债务。
为何有效: 异味是启发式方法——它们指向可能的问题,而无需深入分析。一个能够快速识别"这个函数参数太多"或"这个类有依恋情结"的开发者,可以进行有针对性的改进,而不是模糊的"清理"工作。
关键见解:
代码应用:
| 上下文 | 模式 | 示例 |
|---|---|---|
| 重复 | 提取共享逻辑 | 通用验证 → validateEmail() 辅助函数 |
| 长参数列表 | 引入参数对象 | SearchCriteria 分组相关参数 |
| 依恋情结 | 将方法移到数据所属的类 | order.calculateTotal() 而非 calculator.total(order) |
| 死代码 | 删除它 | 移除未使用的函数、不可达的分支 |
| 魔法数字 | 命名常量 | MAX_LOGIN_ATTEMPTS = 5 而非裸 5 |
| 霰弹式修改 | 合并相关变更 | 将分散的逻辑分组到单个模块中 |
| 错误 | 为何失败 | 修复方法 |
|---|---|---|
| 缩写名称 | 节省几秒编写时间,耗费数小时阅读时间 | 使用完整、描述性的名称;IDE 有自动补全 |
| "聪明"的单行代码 | 写起来令人印象深刻,调试起来不可能 | 扩展为具有清晰名称的可读步骤 |
| 用注释代替重构 | 注释会腐坏;代码才是真相 | 提取命名良好的函数,而不是写注释 |
| 捕获通用异常 | 连同预期错误一起吞掉 bug | 捕获特定异常,让意外异常传播 |
| 没有错误路径测试 | 正常路径工作,边界情况崩溃 | 测试每个分支、边界和失败模式 |
| 过早优化 | 为了微小的性能而掩盖意图 | 先写整洁的代码,再优化测量到的瓶颈 |
| 上帝类 | 一个类,2000 行,做所有事情 | 应用单一职责原则——按职责拆分 |
| 没有测试的重构 | 没有安全网来捕获回归 | 在重构前编写特征化测试 |
| 不一致的约定 | 每个文件都感觉像不同的代码库 | 约定风格,用 linter 和格式化工具强制执行 |
| 到处返回 null | null 检查像病毒一样传播 | 使用 Optional、空集合或空对象模式 |
审计任何代码库:
| 问题 | 如果答案为否 | 行动 |
|---|---|---|
| 你能在不阅读函数体的情况下理解每个函数吗? | 名称未揭示意图 | 重命名函数以描述其功能 |
| 所有函数都在 20 行以下吗? | 函数做太多事情 | 将子操作提取到命名的辅助函数中 |
| 是否存在零个注释掉的代码块? | 死代码造成混淆 | 删除它们——版本控制有历史记录 |
| 错误处理与业务逻辑分离了吗? | try-catch 块污染了主流程 | 提取错误处理;使用异常而非返回码 |
| 每个类都有单一职责吗? | 类积累了不相关的职责 | 拆分为具有清晰名称的专注类 |
| 每个公共方法都有测试吗? | 变更没有安全网 | 在进行进一步更改前添加测试 |
| 测试名称是否描述了行为? | 测试失败时难以理解 | 重命名为 shouldDoXWhenY 模式 |
| 重复出现次数低于 3 次吗? | 复制粘贴传播 bug | 提取到共享函数或模块中 |
| 魔法数字是否被命名常量替换? | 意图隐藏在原始值后面 | 提取具有描述性名称的常量 |
| 你能在 10 秒内运行所有测试吗? | 慢测试阻碍运行它们 | 模拟外部依赖,拆分集成测试 |
本技能基于 Robert C. Martin 关于软件工艺的开创性指南:
Robert C. Martin ("Bob 大叔") 是一位软件工程师、讲师和作家,自 1970 年以来一直从事编程工作。他是敏捷宣言的合著者,也是 Uncle Bob Consulting LLC 和 Clean Coders 的创始人。他的著作——《Clean Code》(2008)、《The Clean Coder》(2011)、《Clean Architecture》(2017) 和《Clean Agile》(2019)——塑造了整整一代开发者对代码质量、专业责任和软件设计的思考方式。Martin 以其坚定的立场而闻名,他认为开发者是必须对其工作质量负责的专业人士,并且唯一快速前进的方式就是做好。
每周安装量
235
代码仓库
GitHub 星标数
255
首次出现
2026年2月23日
安全审计
安装于
codex226
opencode226
gemini-cli225
kimi-cli225
github-copilot225
amp225
A disciplined approach to writing code that communicates intent, minimizes surprises, and welcomes change. Apply these principles when writing new code, reviewing pull requests, refactoring legacy systems, or advising on code quality improvements.
Code is read far more often than it is written. Optimize for the reader. Every naming choice, function boundary, and formatting decision either adds clarity or adds cost. The ratio of time spent reading code to writing code is well over 10:1. Making code easier to read makes it easier to write, easier to debug, and easier to extend.
The foundation: Clean code is not about following rules mechanically -- it is about caring for the craft. A clean codebase reads like well-written prose: names reveal intent, functions tell a story one step at a time, and there are no surprises lurking in dark corners. The Boy Scout Rule applies: always leave the code cleaner than you found it.
Goal: 10/10. When reviewing or writing code, rate it 0-10 based on adherence to the principles below. A 10/10 means full alignment with all guidelines; lower scores indicate gaps to address. Always provide the current score and specific improvements needed to reach 10/10.
Six disciplines for writing code that communicates clearly and adapts to change:
Core concept: Names should reveal intent, avoid disinformation, and make the code read like prose. If a name requires a comment to explain it, the name is wrong.
Why it works: Names are the most pervasive form of documentation. A well-chosen name eliminates the need to read the implementation. A poorly chosen name forces every reader to reverse-engineer the author's intent.
Key insights:
fetch, retrieve, and getCode applications:
| Context | Pattern | Example |
|---|---|---|
| Variables | Intention-revealing name | elapsedTimeInDays not d or elapsed |
| Booleans | Predicate phrasing | isActive, hasPermission, canEdit |
| Functions | Verb + noun describing action | calculateMonthlyRevenue() not |
See: references/naming-conventions.md
Core concept: Functions should be small, do one thing, and do it well. The ideal function is 4-6 lines long, takes zero to two arguments, and operates at a single level of abstraction.
Why it works: Small functions are easy to name, easy to understand, easy to test, and easy to reuse. When a function does one thing, its name can describe exactly what it does, eliminating the need to read the body. Long functions hide bugs, resist testing, and accumulate responsibilities over time.
Key insights:
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Long function | Extract into named steps | validateInput(); transformData(); saveRecord(); |
| Flag argument | Split into two functions | renderForPrint() and renderForScreen() not render(isPrint) |
| Deep nesting | Extract inner blocks | Move nested if/for bodies into named functions |
See: references/functions-and-methods.md
Core concept: A comment is a failure to express yourself in code. Good code is self-documenting. When comments are necessary, they should explain why , never what. Formatting creates the visual structure that makes code scannable.
Why it works: Comments rot. Code changes but comments often do not, creating misleading documentation that is worse than no documentation. Clean formatting -- consistent indentation, vertical spacing between concepts, and logical ordering -- lets developers scan code the way readers scan a newspaper: headlines first, details on demand.
Key insights:
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Explaining "what" | Replace with better name | Rename // check if eligible to isEligible() |
| Explaining "why" | Keep as comment | // RFC 7231 requires this header for proxies |
| Commented-out code | Delete it | Trust version control to remember |
| File organization | Newspaper metaphor | High-level functions at top, details below |
| Related code | Group vertically | Keep caller near callee in the same file |
See: references/comments-formatting.md
Core concept: Error handling is a separate concern from business logic. Use exceptions rather than return codes, provide context with every exception, and never return or pass null.
Why it works: Return codes force the caller to check immediately, cluttering the happy path with error-checking logic. Exceptions let you separate the happy path from error handling, making both easier to read. Returning null forces every caller to add null checks, and a single missing check produces a NullPointerException far from the source.
Key insights:
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Null returns | Return empty collection or Optional | return Collections.emptyList() not return null |
| Error codes | Replace with exceptions | throw new InsufficientFundsException(balance, amount) |
| Third-party APIs | Wrap with adapter | PortfolioService wraps vendor API, translates exceptions |
| Null arguments | Fail fast with assertion | Objects.requireNonNull(user, "user must not be null") |
See: references/error-handling.md
Core concept: Tests are first-class code. They must be clean, readable, and maintained with the same discipline as production code. Dirty tests are worse than no tests -- they become a liability that slows every change.
Why it works: Clean tests serve as executable documentation, showing exactly how the system is intended to behave. They provide a safety net for refactoring and a regression check for every change. Without tests, every modification is a potential bug. With dirty tests, every modification requires fighting through incomprehensible test code.
Key insights:
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Test structure | Arrange-Act-Assert | Setup, execute, verify -- clearly separated |
| Test naming | Scenario + expected behavior | shouldRejectExpiredToken not test1 |
| Shared setup | Extract builder/factory | aUser().withRole(ADMIN).build() |
| Multiple scenarios | Parameterized tests | One test method, multiple input/output pairs |
| Flaky tests | Remove external dependencies | Mock time, network, file system |
See: references/testing-principles.md
Core concept: Code smells are surface indicators of deeper design problems. Learn to recognize them quickly and apply targeted refactorings. Not every smell requires immediate action, but ignoring them accumulates technical debt.
Why it works: Smells are heuristics -- they point toward likely problems without requiring deep analysis. A developer who can quickly identify "this function has too many arguments" or "this class has feature envy" can make targeted improvements instead of vague "cleanup" efforts.
Key insights:
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Duplication | Extract shared logic | Common validation → validateEmail() helper |
| Long parameter list | Introduce parameter object | SearchCriteria groups related params |
| Feature envy | Move method to data's class | order.calculateTotal() not calculator.total(order) |
| Dead code | Delete it | Remove unused functions, unreachable branches |
See: references/code-smells.md
| Mistake | Why It Fails | Fix |
|---|---|---|
| Abbreviating names | Saves seconds writing, costs hours reading | Use full, descriptive names; IDEs autocomplete |
| "Clever" one-liners | Impressive to write, impossible to debug | Expand into readable steps with clear names |
| Comments instead of refactoring | Comments rot; code is the truth | Extract well-named function instead of commenting |
| Catching generic exceptions | Swallows bugs along with expected errors | Catch specific exceptions, let unexpected ones propagate |
| No tests for error paths | Happy path works, edge cases crash | Test every branch, boundary, and failure mode |
| Premature optimization | Obscures intent for marginal performance | Write clean code first, optimize measured bottlenecks |
| God classes |
Audit any codebase:
| Question | If No | Action |
|---|---|---|
| Can you understand each function without reading its body? | Names don't reveal intent | Rename functions to describe what they do |
| Are all functions under 20 lines? | Functions do too many things | Extract sub-operations into named helpers |
| Are there zero commented-out code blocks? | Dead code creating confusion | Delete them -- version control has history |
| Is error handling separate from business logic? | Try-catch blocks cluttering main flow | Extract error handling; use exceptions not return codes |
| Does every class have a single responsibility? | Classes accumulate unrelated duties | Split into focused classes with clear names |
| Is there a test for every public method? | No safety net for changes | Add tests before making further changes |
| Are test names descriptive of behavior? | Tests are hard to understand when they fail | Rename to shouldDoXWhenY pattern |
This skill is based on Robert C. Martin's seminal guide to software craftsmanship:
Robert C. Martin ("Uncle Bob") is a software engineer, instructor, and author who has been programming since 1970. He is a co-author of the Agile Manifesto and the founder of Uncle Bob Consulting LLC and Clean Coders. His books -- Clean Code (2008), The Clean Coder (2011), Clean Architecture (2017), and Clean Agile (2019) -- have shaped how an entire generation of developers think about code quality, professional responsibility, and software design. Martin is known for his uncompromising stance that developers are professionals who must take responsibility for the quality of their work, and that the only way to go fast is to go well.
Weekly Installs
235
Repository
GitHub Stars
255
First Seen
Feb 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex226
opencode226
gemini-cli225
kimi-cli225
github-copilot225
amp225
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
106,200 周安装
calc()| Classes | Noun describing responsibility | InvoiceGenerator not InvoiceManager |
| Constants | Searchable, all-caps with context | MAX_RETRY_ATTEMPTS = 3 not 3 inline |
| Collections | Plural nouns or descriptive phrases | activeUsers not list or data |
| Multiple returns | Guard clauses at top | Early return for error cases, single happy path |
| Many arguments | Introduce parameter object | new DateRange(start, end) not report(start, end, format, locale) |
| Side effects | Make effects explicit | Rename checkPassword() to checkPasswordAndInitSession() or separate |
| Team formatting | Agree on rules once | Use automated formatters (Prettier, Black, gofmt) |
| Special cases | Null Object pattern | GuestUser with default behavior instead of null checks |
| Context in errors | Include operation + state | "Failed to save invoice #1234 for customer 'Acme'" |
| Test readability | Domain-specific helpers | assertThatInvoice(inv).isPaidInFull() |
| Named constants |
MAX_LOGIN_ATTEMPTS = 5 not bare 5 |
| Shotgun surgery | Consolidate related changes | Group scattered logic into a single module |
| One class, 2000 lines, does everything |
| Apply SRP -- split by responsibility |
| Refactoring without tests | No safety net to catch regressions | Write characterization tests before refactoring |
| Inconsistent conventions | Every file feels like a different codebase | Agree on style, enforce with linters and formatters |
| Returning null everywhere | Null checks spread like a virus | Use Optional, empty collections, or Null Object pattern |
| Is duplication below 3 occurrences? | Copy-paste spreading bugs | Extract into shared function or module |
| Are magic numbers replaced with named constants? | Intent is hidden behind raw values | Extract constants with descriptive names |
| Can you run all tests in under 10 seconds? | Slow tests discourage running them | Mock external deps, split integration tests |