mcpField
C
code-comments

code-comments

github.com/basmilius开发081 次安装2 天前更新
代码仓库

关于 code-comments

一份语言无关的代码注释指南,说明如何保留、精简或删除注释。帮助开发者留下代码本身无法表达的理由与约束,同时减少重复和过时内容。

主要功能

  1. 01仅保留代码无法表达的信息
  2. 02删除重复或过时的注释
  3. 03重构由注释辩护的代码
  4. 04将长注释精简为关键理由
  5. 05检查文档块与注释位置

适用场景

  1. 01清理现有文件中的注释
  2. 02在代码改动时审查注释
  3. 03使注释符合项目惯例

安装

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

$npx skills add https://github.com/basmilius/skills --skill code-comments

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

详细介绍

代码注释

注释不会参与编译,也没有测试覆盖注释,因此注释会逐渐偏离代码,并在多个文件中不断增多。只保留那些能传达代码本身无法表达的信息。删掉其余注释。

与语言无关:这些规则同样适用于 //、#、/* */、``、文档字符串、PHPDoc 和 JSDoc。如果项目的 CLAUDE.md / AGENTS.md 与此处规则冲突,则以项目文件为准;周边文件中已有的惯例也同样优先。

1. 判断标准

先写代码。然后以一个从未看过这段代码的人的视角重新阅读。只有当你无法从代码本身推断出某些信息时,才添加注释。

注释只有在传达以下信息之一时才有保留价值:

  • 代码中看不出来的原因。 为什么采用这种方案,而不是显而易见的方案。
  • 文件之外的约束。 返回哨兵值的 API、按大小写不敏感方式排序的列,或不附带基础 CSS 的库。
  • 有意做出的偏离。 某段代码看起来有误,但了解故障原因后便会明白。
  • 边界。 这个函数负责清理数据;这次比较有意采用恒定时间。
  • 来源指引。 规范中的段落、需要匹配的旧行为,或已跟踪工作的议题编号。

其他注释一律删除。代码已经说明了它的作用。

// A node id in this set is collapsed; its children are dropped from the rows.
const collapsed = reactive(new Set<number>());

名称说明了它,类型说明了它,用法也说明了它。删除这一行。

2. 如果注释在为代码辩护,就修复代码

如果一段注释需要一整段文字来解释为什么代码可以接受,那它反映的是问题,而不是在记录问题。提取一个命名函数、重命名变量,或拆分分支。困惑消除后,注释也就不再需要。

同样,逐句叙述代码块内容的注释也应如此。放在二十行代码前的 // Build the rows, then sort them,意味着应该把代码拆成两个分别以这些名称命名的函数。

3. 看到就删的注释

复述下一行。 注释和代码说的是同一件事,因此其中一方就是免费的维护负担。

列出正下方的内容。 数据类上的文档块如果列出其字段(“标识、日期范围、是否已归档”),就是在重复下面十行处的属性列表;只要新增字段,它就会过时。

函数内部的分节标题。 // --- validation --- 标出了一处本该改为函数调用的分界。

注释掉的代码。 版本控制会保留它。把它删掉,也包括它遗留下来的空 try { /* ... */ } catch {}。

已经过时的注释。 移动或重新排序代码时,上方的注释往往会留在原处,结果解释起了旁边的新代码。核对注释所述内容与其下方实际代码是否一致。如果注释适用于别处,就把它移过去;如果所指内容已不存在,就删除注释。

五个文件中重复的同一段内容。 被复制的模板注释会让人不再阅读。将每处精简为一行,或把它集中移到所描述的共享对象旁。

4. 精简长注释

大多数长注释都只是一个原因加上对它的重复说明。保留原因。

删掉由原因直接推导出的结果。删掉从未考虑过的替代方案。删掉改述第一句的第二句。删掉修饰词。

// Rounded to roughly ten meters: two people in the same street share a range, and
// a rounding difference should not cost another request. The rounded position is
// what gets measured as well, so the polygon under a key is the one that key
// describes rather than whoever asked for it first.

改为

// Rounded to roughly ten meters, so two people in the same street share a range. The
// rounded position is measured as well, so a key describes the polygon under it.

保留两句有实质作用的话:为什么要舍入,以及为什么测量的也是舍入后的值。

尽量只写一行。只有在第二句传达了第一句没有的信息时,才写两行。只有在涉及真正独立的问题时,才另起一段,例如当前代码必须继续匹配的历史列。

5. 文档块

如果项目会为每个类和函数编写文档(PHPDoc、JSDoc、文档字符串),就遵循这一惯例。保留文档块,并保持简短。

描述要说明名称无法表达的内容。 用一两句话说明这个东西的用途,以及调用方需要了解什么。如果它只是把名称扩写成一个句子,那么删掉描述会更好。

标签承载类型和名称,而非说明文字。 @param int $limit 已经足够完整。只有当说明文字能提供签名无法表达的信息时才添加,例如单位、格式、领域术语、null 的含义或可接受范围。

@param int $requestId                  // nothing to add
@param string $date Date in `Y-m-d` format.
@param int|null $branchId Narrows to this branch and everything below it.
@param float $wtf The werktijdfactor, not the raw stored integer.

数组和对象的形状值得占用篇幅。 @return array{items: Row[], total: int} 或带类型的泛型,都胜过用句子描述同样的结构。

不要描述调用方的环境。 哪个屏幕会调用这个函数、它支撑哪个选项卡、哪个版本添加了它:这些信息在重构后都不会保留。直接说明其行为。

6. 始终保留的内容

  • **待办事项和备注,**需注明负责人和条件: // todo(Bas): drop this once frontend 1.0 is gone. 没有负责人或触发条件的待办事项,只会成为永远无法解决的注释。
  • **许可证和版权声明,**如果项目有使用。
  • 安全边界。 说明为什么比较要采用恒定时间,或为什么要在这里而非调用处转义某个值。
  • **变通方案,**需注明解除方案的版本或条件。Node < 20、until the API returns a proper status。
  • 外部引用。 规范段落、CAO 或法规条款、供应商特有行为、上游问题链接。
  • **有意保持的旧版行为,**包括已不存在的列或端点。没人能从代码中推断出这些信息。

7. 位置和语言

将注释放在所解释内容的正上方,并保持相同缩进。位于一组声明上方的注释应适用于整组声明;如果它只针对其中一项,就将它移到那一项上方。

注释应使用代码库已有的语言,并遵循相应的拼写惯例。注释的详略也应与周围内容一致:一个没有注释的文件,也是在表达其代码需要多少说明。

8. 审查现有文件

先读注释,再读代码,并逐条自问:如果是现在,你还会写这条注释吗?以下三轮检查可以发现大多数问题:

  1. 下一行是否已经表达了同样的内容?删除。
  2. 这条注释是否与下一行有关?移动或删除。
  3. 能否用一半的字数表达这个理由?精简。

对于注释很多的文件,删掉三分之一到一半的注释行是很常见的结果。如果一条都没删,要么文件本来就很精炼,要么检查时不够坦诚。

相关技能

  • unslop - 将同样的思路用于文字:删掉填充内容,保留重点。
  • 仓库的 CLAUDE.md / AGENTS.md - 项目关于注释语言、文档块要求和文件头约定的规则;这些规则优先于本文的默认要求。

评论

支持 Markdown