mcpField
C
clean-code

clean-code

github.com/mindrally开发289132 次安装3 周前更新
代码仓库

关于 clean-code

面向开发者的编码 Skill,强调代码易读、易维护,并避免为假设需求增加抽象。它提供从界定改动范围、选择简单实现到测试和交付前检查的工作流程。

主要功能

  1. 01将改动限定在请求范围内
  2. 02优先选择简单实现
  3. 03使用体现用途的命名
  4. 04保持函数职责单一
  5. 05测试行为与边缘情况
  6. 06交付前检查改动范围

适用场景

  1. 01审查拟议的代码改动
  2. 02实现范围明确的功能或修复
  3. 03重构时减少不必要的抽象

安装

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

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

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

详细介绍

整洁代码

这项技能涵盖如何编写易于阅读和修改的代码,以及同样重要的内容——避免以“最佳实践”之名过度设计,让代码更难阅读和修改。这两方面同样重要:整洁代码就是简洁的代码,而不只是装饰得很漂亮的代码。

编写或审查代码的工作流

  1. 明确变更范围 — 准确找出需求。动手之前,先记下哪些内容不在范围内。
  2. 优先尝试最简单的方案 — 优先采用直接、清晰的实现,而不是通用或可配置的方案,除非当前确有具体需求需要这样做。
  3. 根据用途命名 — 在编写函数主体或确定类型结构之前,选择能体现意图的名称。
  4. 让函数各司其职 — 如果需要用注释解释函数的作用,就拆分它。
  5. 有意识地消除重复 — 只有在确实出现重复之后才提取共用逻辑(参见下文的三次原则),不要提前处理。
  6. 编写或更新测试 — 覆盖新增行为及其引入的边缘情况。
  7. 交付前确认范围 — 确认只修改了需求涉及的代码,检查是否有更简单的方案,并确认没有触及未要求修改的文件。

有意义的名称

  • 变量、函数和类的名称应该能直接体现其用途。
  • 名称应该说明某项内容为何存在以及如何使用,而不只是描述其类型或内容(activeUserIds,而不是 list1)。
  • 避免使用缩写,除非它们在相关领域中广为人知(id、url 可以;usrCfgTmp 不行)。

用常量替代魔法数字

  • 将硬编码的值替换为命名常量(MAX_RETRY_COUNT = 3,而不是在后面的三个调用位置直接写 3)。
  • 使用能说明值的用途,而不只是描述值本身的常量名称。
  • 将常量放在文件顶部;如果多个文件共用,则放在专用的常量模块中。

有用的注释

  • 不要注释代码的作用;应通过命名和结构让代码自我说明。
  • 使用注释解释为何要以某种方式实现,尤其是代码中看不出原因时(例如规避库的缺陷,或非显而易见的顺序要求)。
  • 为公共 API、真正复杂的算法以及不明显的副作用编写说明。

单一职责

  • 每个函数只做一件事。
  • 函数应足够小且专注,无需滚动页面就能理解。
  • 如果需要用注释解释函数的作用,就应该将它拆分为命名清晰的子函数。

DRY — 不要重复自己

  • 只有在确实出现重复之后才将重复代码提取为可复用函数,不要预先设想重复。
  • 通过恰当的抽象共享通用逻辑——使用共用函数或模块,而不是稍作修改后复制粘贴。
  • 对每一项业务逻辑或配置值维护唯一事实来源。

封装

  • 将实现细节隐藏在清晰的接口之后;调用方不应需要了解某项内容的工作原理才能使用它。
  • 将嵌套条件逻辑移入命名清晰的函数或保护子句中,避免深层的 if/else 嵌套。
// 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;
}

清晰的结构

  • 将相关代码放在一起(某项功能的组件、钩子和样式应放在同一目录中,而不是按文件类型分散存放)。
  • 按照对领域的理解,以合乎逻辑的层级组织代码。
  • 在整个代码库中采用一致的文件和文件夹命名规范。

避免过度设计

  • 只修改要求修改的内容。首先选择能满足需求的最简单方案。
  • 如果不确定合适的抽象层级,请先询问,而不是猜测并选择更复杂的方案。
  • 不要修改未要求修改的代码,即使它看起来可以改进也是如此——顺手重构无关函数会扩大审查范围和改动风险。
  • 不要在没有明确、当前需求的情况下添加抽象(接口、工厂、插件系统、配置层)。单一实现不需要为了“以防”以后出现第二个实现而添加接口——这是投机性通用设计(YAGNI:“你不会需要它”)。
  • 不要为了一个现有代码几行就能解决的问题引入新依赖。
  • 小改动不要重写整个文件——与重写整个文件相比,有针对性的差异更容易审查,也更安全。
  • 如果根据周边代码的保证,某些情况不可能发生,就不要为这些情况添加错误处理——针对不可能状态编写防御性代码会增加阅读成本,却不会提升安全性。
三次原则
  • 某种模式第一次和第二次出现时,允许重复。
  • 第三次出现时再提取抽象,此时共享逻辑的实际形态已经清晰——在只有一两个实例时就提取,往往会误判真正共享的内容。
过度设计的迹象
  • 某个配置选项一直只被设为一个值。
  • 某个接口只有一个实现,也没有需要第二个实现的测试替身。
  • 一个通用的 options 对象不断增加字段,只为满足假设中的未来调用方。
  • 在还没有两种策略可供切换之前,就引入插件/策略模式。

代码质量维护

  • 持续进行小步重构,而不是把清理工作推迟到专门的“重构冲刺”。
  • 及早修复技术债务,此时你仍清楚代码为何如此编写。
  • 在你正在处理的范围内,让代码比接手时更整洁——但这并不意味着可以重构无关文件。

测试

  • 修复错误前先编写一个会失败的测试,以验证修复有效,并防止错误悄然复发。
  • 保持测试易读、易维护——如果测试比被测代码更难理解,那它就没有完成自己的职责。
  • 明确测试边界情况和错误条件,而不只是测试正常路径。

版本控制

  • 编写清晰、具体的提交信息,说明为何进行这项更改。
  • 将更改拆分为小而专注的提交——每个提交只包含一个逻辑上的更改。
  • 使用能描述工作内容、而非作者或日期的有意义的分支名称。

交付前检查清单

  • 只修改了要求修改的代码——没有触及无关文件。
  • 没有在缺乏当前具体需求的情况下添加抽象。
  • 没有添加与现有功能重复的依赖。
  • 已考虑并排除了更简单的方案,而非直接跳过。
  • 新行为有测试覆盖,其中至少包含一个边界情况。

评论

支持 Markdown