mcpField
C
clean-code-guard

clean-code-guard

github.com/amelnagdy测试与质量1.3k4.7k 次安装17 周前更新
代码仓库

关于 clean-code-guard

clean-code-guard 是用于审查生成或修改代码的便携式指令 Skill,适用于编码 Agent 和代码审查场景。它将通用代码质量原则与针对 AI 生成代码的检查结合,不依赖 MCP 服务或本地工具。

主要功能

  1. 01生成代码的守护式检查
  2. 02编写时应用质量规则
  3. 03结构化代码审查报告
  4. 04提供 SOLID 与 DRY 等参考
  5. 05交付前自检

适用场景

  1. 01提交或合并前检查代码改动
  2. 02按规则审查代码并报告问题
  3. 03编写代码时持续遵循质量约束

安装

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

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

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

包含的文件

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

agents/
openai.yaml
references/
ai-failure-modes.md
comments-and-formatting.md
dry-kiss-yagni.md
naming-and-functions.md
review-checklist.md
solid.md
sources.md

详细介绍

clean-code-guard

你正在审查即将发布的生成代码或变更代码。请在首次实现后将以下规则作为守护检查来应用;一旦此技能启用,在同一会话中后续的每次代码变更都要继续应用这些规则,并在每次编辑后重新运行交付前自检,而不要因为技能先前已加载就退回到未经守护检查的输出。如果用户在编写代码之前明确调用此技能,编写代码时也要遵循相同规则,并在交付前运行自检。

兼容性

这是一项可移植的指令技能。它不需要 MCP 服务、网络访问、API 密钥、Shell 命令、本地可执行文件或捆绑脚本。它可用于任何支持 SKILL.md 和直接链接的 references/ 文件的运行时;agents/openai.yaml 是轻量级显示元数据。

此技能不能替代项目的代码检查工具、格式化工具、类型检查器或测试运行器。请使用项目自带工具进行机械式验证;使用此技能对代码质量和审查进行判断。

如何使用此技能

此技能有三种模式——根据用户的请求选择。

守护检查模式(推荐):生成、编辑、重构或修复代码后,根据以下始终适用的规范检查差异或目标文件。提交、合并或展示工作成果前,先修复违规之处。

实时模式(明确调用):用户在进行高风险代码编辑前调用此技能时,编写代码的同时应用相同规范,然后运行交付前自检清单。如果违反任何规则,在向用户展示之前先修复。

审查模式(用户要求审查、审计、批评或评价代码时触发):根据 references/review-checklist.md 检查目标文件,并生成结构化的问题报告。除非用户要求,否则在审查模式下不要编辑代码。

在以上所有模式中,规则正文都位于 references/ 中。遇到以下情况时,请阅读相关参考文件:

  • 遇到自己不完全记得缘由的规则。
  • 用户对某条规则提出异议,而你需要引用其来源。
  • 处于审查模式,需要完整清单。
  • 正在审查的代码涉及某项具体原则(例如,子类化 → references/solid.md;去重 → references/dry-kiss-yagni.md)。

参考文件如下:

示例

  • 编码 Agent 实现一个端点:在成果被展示或提交之前,对 diff 使用 guard-pass 模式。
  • 用户问"审查这个 PR"或"我应该合并这个吗?":使用审查模式,并报告来自 references/review-checklist.md 的发现;除非被要求,否则不要编辑。
  • 用户问"用 clean-code-guard 实现这个端点":在编写过程中使用实时模式,然后在交付前运行自检。
  • 用户问"重构这个函数,保持行为不变":完全保留可观察行为,并将任何缺陷修复视为单独的变更。

成功标准

当编写代码的任务避开了所列的失败模式,代码审查任务产出带有具体证据的按优先级排序的发现,并且重构在用户未明确要求行为变更时保持行为不变,此技能即为生效。对于 frontmatter 排除项所涵盖的概念性、CI、git 工作流、散文、数据分析和测试运行任务,它应保持沉默。

此技能为何存在

大模型生成的代码具有可衡量的、系统性的失败模式,通用的"遵循整洁代码"指令无法捕捉到。以下是有已发表研究支持的示例:

  • 代码重复增长了 8 倍,在被跟踪的代码库中,2021 年至 2024 年间(GitClear 2025 报告)。
  • 包幻觉率平均为 19.6%,跨越 16 个模型(Spracklen 等,USENIX Security '25)。
  • 大模型经常将高风险操作包裹在宽泛的 catch-all 处理程序中,从而吞掉错误(Karpathy)。
  • AI Agent "尽管测试失败仍宣称成功",通过返回硬编码的 fixture 值(Fowler,Patterns for Reducing Friction)。
  • 在 AI 辅助的提交中,函数规模从 142 增至 267 LoC,圈复杂度从 4.2 增至 8.1(GitClear)。

经典原则(Clean Code、SOLID、DRY/KISS/YAGNI)仍然是基础——但此技能增加了大多数规则包所遗漏的AI 专属层。

始终适用的强制要求

以下是每次代码变更时都要遵循的规则。它们是强制性的,而非建议。

函数与命名
  1. 名称揭示意图。 在没有限定词的情况下,绝不使用 data、data2、result、result_final、item、temp、value、obj、info、helper、manager、utils 或 handle_*/process_*/do_*。名称必须回答它为何存在以及它做什么。(Clean Code 第 2 章)
  2. 函数保持小巧。 目标 ≤20 行,一个抽象层级,只做一件事。如果你能提取出一个名称不会重述其函数体的函数,那么父函数就在做不止一件事。(Clean Code 第 3 章)
  3. 四个参数是硬性上限。 到了五个,停下来并引入请求/配置对象(record、struct、DTO 或等效物)。绝不使用布尔标志参数——改为拆分成两个函数。
  4. 没有输出参数。 一个函数要么返回值(查询),要么有副作用(命令)。绝不两者兼有。命令名称使用动词;查询名称使用名词或 getter 风格的名称。(CQS)
注释与结构
  1. 注释解释为什么,绝不解释是什么。 删除任何对其下方代码行进行转述的注释。删除步骤编号脚手架注释。删除被注释掉的代码——版本控制是存在的。(Clean Code 第 4 章)
  2. 匹配文件现有的风格。 在编写之前,阅读你正在编辑的文件以及至少一个相邻文件。镜像其大小写、导入顺序、错误处理、日志记录以及 HTTP/DB 客户端的选择。不要引入第二种模式。
SOLID
  1. 每个模块只服务一个参与者。 一个类应当只对一个利益相关方群体(会计、认证、报表)负责。如果两个不相关的子系统都伸手进入同一个类,就把它拆开。(SRP,Uncle Bob 2014)
  2. 通过新增代码扩展,而非修改代码。 如果新增一个变体需要在现有函数中再加一个类型标签分支,那就要先重构成注册表、策略或[多态]分派。(OCP)
  3. 子类不得拒绝父类的契约。 绝不要通过重写方法来表示"未实现"或"不支持的操作"。绝不要在重写中加强前置条件或削弱后置条件。如果你需要那样做,说明继承关系是错的。(LSP)
  4. 抽象应随客户端而居,而非随实现而居。 当你引入接口、协议或抽象契约时,把它放在消费它的包中,而不是放在具体类旁边。(DIP)
DRY、KISS、YAGNI
  1. 删除重复的 知识,而非重复的 文本。 两个看起来相似但编码了不同规则的函数并不违反 DRY。同一条规则在代码 + 文档 + schema 中被表达出来才算违反。(Pragmatic Programmer,"DRY")
  2. 错误的抽象比重复更糟。 如果一个抽象已经为每个调用方的特殊情况累积了分支,就把它重新内联回调用方,然后删除死分支,再重新抽象。(Sandi Metz,"The Wrong Abstraction")
  3. 复杂度上限:圈复杂度 ≤10,嵌套深度 ≤5。 在超出之前先重构。(McCabe 1976)
  4. 不要任何推测性的东西。 没有当下调用方,就不要可选参数、配置标志、环境变量、功能开关、接口、工厂或基类。如果你发现自己正在添加 enable_*、use_*_v2 或 *_mode,删掉它,直接交付具体行为。(Fowler,"Yagni")
AI 专属护栏 —— 最高杠杆的部分
  1. 绝不用宽泛的兜底处理吞掉错误。 只捕获你能从中恢复的特定错误类型。如果无法恢复,就让错误向上传播。禁止在 catch 处理程序中返回 null/none/空成功,除非函数契约明确记载了该行为。(Karpathy)
  2. 守住边界;信任契约。 在信任边界处 —— 外部输入、请求/API 载荷、反序列化或跨进程数据、任何来自不可信来源的内容 —— 都要校验,即使正常路径看起来没问题。在边界内部,不要为声明类型或调用方契约已排除该情况的值添加 null 检查或运行时类型检查。判断是否需要防护的标准不是“这理论上会不会出错”,而是“不可信数据能否到达这里”。(arXiv 2409.19182)
  3. 验证每一个导入和外部调用。 在调用某个库的方法之前,确认它存在于所安装的版本中(阅读包源码、检查 lockfile,或导入并检查)。不要基于 API “应该”长什么样来生成代码。(USENIX Security '25)
  4. 生产代码中不得硬编码“成功”返回或 mock 数据。 绝不要从规格说明其执行真实工作的函数中返回 {"status": "ok", ...} 或预制数据。如果无法实现,就用该语言的未实现或不受支持操作机制显式失败,并如实说明。绝不要为了让测试通过而禁用、跳过或削弱测试。(Fowler,Claude Code issue #6984)
  5. 重新推导,不要从相似代码复制。 当你想复制一个函数再修改时,停下来。从规格说明重新推导。差一错误和错误 null 语义的缺陷几乎总是通过从相似代码复制引入的。(arXiv 2411.01414)
  6. 在编写之前先枚举边界情况。 对于任何范围、差一、null/空/单元素/多元素、奇偶或 unicode/字节边界,先在注释中写出情况列表。在继续之前,在代码中覆盖每一种情况。
  7. 交付前清除死代码。 运行 linter 或 grep 检查未使用的导入、未使用的符号、不可达分支和“以防万一”的导出。移除它们。今天没有任何东西调用的函数不能为了“将来某天”而保留。
  8. 先读后写。 在不熟悉的仓库中写入之前,阅读你将编辑的文件、一个相邻文件,以及任何项目规则文件(CLAUDE.md、AGENTS.md、README 的“约定”部分)。使用项目现有的辅助函数、错误类型和日志。
  9. 几行代码能覆盖的,不要新增依赖。 在添加包之前,检查标准库、已安装的依赖,以及几行本地代码能否完成任务。新依赖是永久的维护和供应链暴露面;只有当它承载你不应重新实现的真正复杂性(密码学、解析、时区 —— 仅为示例,并非穷举)时才添加,绝不要为了省十行代码而添加。参见 references/dry-kiss-yagni.md。
底线 —— 绝不要为了简单而削减这些

第 16 条规则在边界内部信任契约;即使你删除了推测(14)、防御性防护(16)和死代码(21),以下条目仍然保留。移除其中任何一条都是行为变更,而不是清理 —— 保留它,或标记出来并询问。

  • 每个信任边界处的校验与净化 —— 外部输入、请求/API 载荷、反序列化或跨进程数据。
  • 防止数据丢失的错误处理。
  • 安全措施 —— 授权、输出转义、参数化查询、密钥处理。
  • 用户明确要求的行为。 随口提及 ≠ 要求,但不要丢弃已被要求的内容。
重构纪律
  1. 重构时保持可观察行为不变。 当用户要求你清理、简化或重构现有代码时,不要改变契约——相同的输入产生相同的输出,抛出相同的异常,产生相同的副作用,保持相同的顺序保证。如果你在重构时发现了一个 bug,单独标记出来,并在修改前先询问。重构的定义是*“对软件内部结构的修改,使其更易于理解、修改成本更低,同时不改变其可观察行为”*(Fowler,《重构》)。Bug 修复和重构是两种操作——绝不要把它们捆绑到同一次修改中。

交付前自检

在向用户展示你编写或编辑的代码之前:

  1. 将准则 1–24 逐条对照你的 diff 检查。修正每一处违规。
  2. 对于新函数,清点:行数 ≤ 20?参数 ≤ 4?复杂度感觉 ≤ 10?命名是否揭示意图?
  3. 对于新注释,问自己:它解释的是为什么吗?如果它解释的是是什么,删掉它。
  4. 对于新的错误处理:捕获的错误类型是否具体?处理逻辑除了静默返回之外,是否还做了别的事情?
  5. 对于新的抽象(接口、工厂、基类、注册表):今天是否存在第二个具体的使用者?如果没有,就内联它。
  6. 你是否阅读了你所编辑的文件以及至少一个相邻文件?你的风格是否匹配?
  7. 是否存在任何硬编码的 "ok" 返回值或桩数据?如果有,替换为真实实现,或显式返回未实现/不支持操作的失败。
  8. 如果这是一次重构:你是否改变了可观察行为?如果是,你捆绑了一个 bug 修复——把它拆分出来并询问用户。

如果你无法对每项检查都回答“是”,请在交付前修正。

在守卫检查通过后,将其展示出来,让用户能看到它已运行(守卫通过模式和实时模式——review 模式通过其自身的发现格式报告)。将每项修正列为 <file>[:<line>] — <what changed>,如果行号不稳定则省略行号,然后以一行收尾:clean-code-guard: <N> fixed, <M> flagged for author——如果没有任何触发,则为 clean-code-guard: clean。只报告你实际做出的修改;绝不要估算质量分数或百分比——不存在基准,因此这样的数字是凭空捏造的。这只是在报告本次检查;它不会阻止展示或提交。

当用户对某条规则提出异议时

引导他们查看相关 references/ 文件中的来源名称,仅在需要 URL 时才使用 references/sources.md。这些规则是站得住脚的——它们来自一手来源(Uncle Bob、Fowler、Hunt & Thomas、McCabe、Metz),以及 2024–2026 年关于大模型代码生成的已发表研究。如果用户有特定于其情境的理由要覆盖某条规则(例如某个构造函数确实需要 8 个参数来处理一个配置 DTO),请在代码注释中记录该例外,注明被覆盖的原则、原因以及重新审视的触发条件——即应重新考虑它的情形。没有重新审视触发条件的例外注释,本身就会成为下一次检查中的一项发现:没有出口的权衡只是被推迟的债务。

故障排除

  • 如果任务是概念性的而非产出代码的,不要应用此技能; 直接回答该概念。
  • 如果 review 模式开始产生仅针对风格的反馈,请使用 references/review-checklist.md,并优先关注行为 bug、脆弱性 和可维护性风险。
  • 如果某条规则与某个明确的项目约定冲突,请遵循项目 约定,并且仅当该例外会让未来的维护者感到意外时,才记录它。
  • 如果该技能感觉过于宽泛,请优先使用 frontmatter 中的排除项;不要向这个通用守卫技能中添加 特定于运行时的规则。

本技能不做什么

  • 运行 linter 或静态分析。这些是工具层面的关注点;本技能关注的是写什么和看什么。
  • 强制执行特定语言的格式化工具或 linter 偏好。以项目的样式工具为准。
  • 替代测试。整洁的代码能通过测试;没有整洁的代码测试就无法通过,但没有测试的整洁代码同样是一种缺陷。

评论

支持 Markdown