clean-code

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Clean Code

Clean Code(整洁代码)

This skill covers writing code that is easy to read and change, and — just as important — avoiding the over-engineering that makes code harder to read and change in the name of "best practices." Both halves matter together: clean code is simple code, not merely well-decorated code.
本 skill 涵盖如何编写易于阅读和修改的代码,以及同样重要的——避免以“最佳实践”之名进行过度工程,使代码变得更难阅读和修改。两者必须结合:整洁代码就是简单代码,而不只是装饰良好的代码。

Workflow for Writing or Reviewing Code

编写或审查代码的工作流程

  1. Scope the change — Identify exactly what was asked for. Note what's out of scope before writing anything.
  2. Reach for the simplest solution first — Prefer the direct, obvious implementation over a general or configurable one, unless a concrete current need justifies more.
  3. Name things for their purpose — Choose names that reveal intent before writing the body of a function or the shape of a type.
  4. Keep functions single-purpose — If a function needs a comment to explain what it does, split it.
  5. Remove duplication deliberately — Extract shared logic only once it's actually duplicated (see Rule of Three below), not preemptively.
  6. Write or update tests — Cover the new behavior and the edge cases it introduces.
  7. Verify scope before delivery — Confirm only the requested code changed, check for a simpler approach you might have missed, and confirm no unrequested files were touched.
  1. 界定变更范围——准确识别所提出的要求。开始编写任何内容之前,先记录不属于范围的事项。
  2. 优先采用最简单的解决方案——除非存在明确的当前需求作为理由,否则应优先选择直接、显而易见的实现,而不是通用或可配置的实现。
  3. 按用途命名——在编写函数体或定义类型结构之前,选择能够清晰表达意图的名称。
  4. 让函数保持单一用途——如果需要通过注释才能解释函数的作用,就应将其拆分。
  5. 有意识地消除重复——只有在共享逻辑确实出现重复后才提取(参见下方的“三次法则”),不要提前抽象。
  6. 编写或更新测试——覆盖新行为及其引入的边界情况。
  7. 交付前验证范围——确认仅修改了所请求的代码,检查是否遗漏了更简单的方案,并确认没有改动未请求的文件。

Meaningful Names

有意义的命名

  • Variables, functions, and classes should reveal their purpose from the name alone.
  • Names should explain why something exists and how it's used, not just its type or contents (
    activeUserIds
    , not
    list1
    ).
  • Avoid abbreviations unless they're universally understood in the domain (
    id
    ,
    url
    — fine;
    usrCfgTmp
    — not fine).
  • 变量、函数和类应当仅凭名称就能揭示其用途。
  • 名称应说明事物为何存在以及如何使用,而不只是描述其类型或内容(使用
    activeUserIds
    ,而不是
    list1
    )。
  • 除非缩写在所属领域中已被普遍理解,否则应避免使用缩写(
    id
    、
    url
    没问题;
    usrCfgTmp
    则不合适)。

Constants Over Magic Numbers

常量优于魔法数字

  • Replace hard-coded values with named constants (
    MAX_RETRY_COUNT = 3
    , not a bare
    3
    three call sites later).
  • Use descriptive constant names that explain the value's purpose, not just its value.
  • Keep constants at the top of the file or in a dedicated constants module when shared across files.
  • 将硬编码值替换为具名常量(使用
    MAX_RETRY_COUNT = 3
    ,而不是在三处调用点中使用裸
    3
    )。
  • 使用能够说明值之用途的描述性常量名称,而不只是描述其数值。
  • 对于跨文件共享的常量,将其放在文件顶部或专用的 constants 模块中。

Smart Comments

智能注释

  • Don't comment on what the code does — make the code self-documenting through naming and structure instead.
  • Use comments to explain why something is done a certain way, especially when the reason isn't visible in the code (a workaround for a library bug, a non-obvious ordering requirement).
  • Document public APIs, genuinely complex algorithms, and non-obvious side effects.
  • 不要注释代码做了什么——应通过命名和结构让代码具备自我说明能力。
  • 使用注释解释为什么以某种方式完成某项操作,尤其是在代码中无法直接看出原因时(例如规避 library bug,或满足不明显的使用顺序要求)。
  • 为公共 API、真正复杂的算法和不明显的副作用编写文档。

Single Responsibility

单一职责

  • Each function should do exactly one thing.
  • Functions should be small and focused enough to be understood without scrolling.
  • If a function needs a comment to explain what it does, that's a signal to split it into named sub-functions instead.
  • 每个函数应当只做一件事。
  • 函数应保持小巧且聚焦,无需滚动页面即可理解。
  • 如果需要通过注释才能解释函数的作用,就应将其拆分为具名的子函数。

DRY — Don't Repeat Yourself

DRY——不要重复自己(Don't Repeat Yourself)

  • Extract repeated code into reusable functions once the repetition is real, not anticipated.
  • Share common logic through a proper abstraction — a shared function or module, not copy-paste with tweaks.
  • Maintain a single source of truth for any given piece of business logic or configuration value.
  • 只有在重复真实发生之后,而不是提前预判其可能发生时,才将重复代码提取为可复用函数。
  • 通过恰当的抽象共享公共逻辑——使用共享函数或 module,而不是稍作修改后复制粘贴。
  • 对于任何给定的业务逻辑或配置值,应维护单一事实来源。

Encapsulation

封装

  • Hide implementation details behind a clear interface; callers shouldn't need to know how a thing works to use it.
  • Move nested conditionals into well-named functions or guard clauses instead of deep
    if
    /
    else
    trees.
js
// Before
function canCheckout(cart) {
  if (cart.items.length > 0) {
    if (cart.user.isVerified) {
      if (cart.total <= cart.user.creditLimit) {
        return true;
      }
    }
  }
  return false;
}

// After
function canCheckout(cart) {
  const hasItems = cart.items.length > 0;
  const isWithinCreditLimit = cart.total <= cart.user.creditLimit;
  return hasItems && cart.user.isVerified && isWithinCreditLimit;
}
  • 将实现细节隐藏在清晰的 interface 之后;调用者不应需要了解其内部工作方式才能使用。
  • 将嵌套条件逻辑移入命名清晰的函数或 guard clause,而不是形成深层的
    if
    /
    else
    树。
js
// Before
function canCheckout(cart) {
  if (cart.items.length > 0) {
    if (cart.user.isVerified) {
      if (cart.total <= cart.user.creditLimit) {
        return true;
      }
    }
  }
  return false;
}

// After
function canCheckout(cart) {
  const hasItems = cart.items.length > 0;
  const isWithinCreditLimit = cart.total <= cart.user.creditLimit;
  return hasItems && cart.user.isVerified && isWithinCreditLimit;
}

Clean Structure

整洁的结构

  • Keep related code together (a feature's components, hooks, and styles in one directory, not scattered by file type).
  • Organize code in a logical hierarchy that mirrors how the domain is understood.
  • Use consistent file and folder naming conventions across the codebase.
  • 将相关代码放在一起(某个功能的组件、hooks 和样式放在同一目录中,而不是按文件类型分散放置)。
  • 按照与领域理解方式相呼应的逻辑层级组织代码。
  • 在整个 codebase 中使用一致的文件和文件夹命名约定。

Avoiding Over-Engineering

避免过度工程

  • Only change what was asked. The simplest solution that satisfies the request comes first.
  • When the right level of abstraction is unclear, ask rather than guessing toward the more elaborate option.
  • Do not modify unrequested code, even if it looks improvable — a drive-by refactor in an unrelated function expands the review surface and the risk of the change.
  • Do not add abstractions (interfaces, factories, plugin systems, config layers) without a concrete, current need. A single implementation doesn't need an interface "in case" a second one shows up later — that's speculative generality (YAGNI: "You Aren't Gonna Need It").
  • Do not import a new dependency to solve a problem a few lines of existing code already solve.
  • Do not rewrite entire files for small changes — a targeted diff is easier to review and safer to ship than a full-file rewrite.
  • Do not add error handling for scenarios that cannot occur given the surrounding code's guarantees — defensive code for impossible states adds reading cost without adding safety.
  • 只修改所请求的内容。能够满足需求的简单方案始终优先。
  • 当无法确定恰当的抽象层级时,应主动询问,而不是猜测并选择更复杂的方案。
  • 不要修改未请求的代码,即使它看起来可以改进——在无关函数中进行顺手重构会扩大审查范围并增加变更风险。
  • 不要在没有明确的当前需求时添加抽象(interface、factory、plugin system、配置层)。单一实现不需要为了“万一以后出现第二种实现”而预先创建 interface;这属于推测性通用设计(YAGNI:“你不会需要它”)。
  • 不要为了解决几行现有代码即可处理的问题而引入新 dependency。
  • 不要为小改动重写整个文件——有针对性的 diff 比完整重写文件更容易审查,也更安全地交付。
  • 不要为周围代码所保证不会发生的场景添加错误处理——针对不可能状态的防御性代码只会增加阅读成本,无法提升安全性。

Rule of Three

三次法则(Rule of Three)

  • Tolerate duplication the first two times a pattern appears.
  • Extract an abstraction on the third occurrence, once the actual shape of the shared logic is clear — extracting after one or two instances often guesses wrong about what's actually shared.
  • 某种模式在前两次出现时,可以容忍重复。
  • 在第三次出现时提取抽象,此时共享逻辑的实际结构已经清晰——在一两个实例之后就提取,往往会错误判断究竟哪些内容是共享的。

Signs of Over-Engineering

过度工程的迹象

  • A configuration option that has only ever been set to one value.
  • An interface with exactly one implementation and no test double that needs a second.
  • A generic
    options
    object accreting fields for hypothetical future callers.
  • A plugin/strategy pattern introduced before there are two strategies to switch between.
  • 某个配置选项始终只会被设置为同一个值。
  • 某个 interface 恰好只有一个实现,并且没有需要第二种实现的 test double。
  • 通用
    options
    对象不断为假设中的未来调用者添加字段。
  • 在尚不存在两种可切换策略之前,就引入 plugin/strategy 模式。

Code Quality Maintenance

代码质量维护

  • Refactor continuously in small steps rather than deferring cleanup to a dedicated "refactor sprint."
  • Fix technical debt early, while the context for why the code looks the way it does is still fresh.
  • Leave code cleaner than you found it, scoped to the area you're already touching — not as license to refactor unrelated files.
  • 持续以小步骤重构,而不是将清理工作推迟到专门的“重构冲刺”。
  • 及早修复技术债务,趁代码为何呈现当前状态仍然清晰时进行处理。
  • 让代码比发现时更加整洁,但范围仅限于正在修改的区域——这并不意味着可以重构无关文件。

Testing

测试

  • Write a failing test before fixing a bug, so the fix is verified and the bug can't silently regress.
  • Keep tests readable and maintainable — a test that's harder to understand than the code it tests has failed at its job.
  • Test edge cases and error conditions explicitly, not just the happy path.
  • 修复 bug 前先编写失败的测试,以验证修复并防止 bug 悄然回归。
  • 保持测试可读且易于维护——如果测试比它所测试的代码更难理解,就说明测试没有发挥应有作用。
  • 明确测试边界情况和错误条件,而不只是测试正常执行路径。

Version Control

版本控制

  • Write clear, specific commit messages that explain why a change was made.
  • Make small, focused commits — one logical change per commit.
  • Use meaningful branch names that describe the work, not the author or the date.
  • 编写清晰、具体的 commit message,说明进行变更的原因。
  • 使用小巧、聚焦的 commit——每个 commit 包含一项逻辑变更。
  • 使用能够描述工作的有意义分支名称,而不是作者姓名或日期。

Before Delivery Checklist

交付前检查清单

  • Only the requested code changed — no unrelated files touched.
  • No abstraction was added without a concrete need that exists today.
  • No dependency was added that duplicates something already available.
  • A simpler approach was considered and ruled out, not just skipped.
  • New behavior has test coverage, including at least one edge case.
  • 仅修改了所请求的代码——没有改动无关文件。
  • 没有在缺乏今天确实存在的具体需求时添加抽象。
  • 没有添加与现有能力重复的 dependency。
  • 已考虑更简单的方案并说明将其排除的原因,而不是直接跳过。
  • 新行为已有测试覆盖,包括至少一个边界情况。