关于 writing-code-comments
面向开发者的代码注释编写技能,默认不添加注释,并说明如何只保留代码无法表达的背景,例如原因、警告或外部引用。
主要功能
- 01判断注释是否补充背景
- 02删除代码复述与过时历史
- 03保留原因说明与警告
- 04提供注释风格指引
适用场景
- 01审查代码变更中的注释
- 02判断是否需要添加注释
- 03修改注释以提高清晰度
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ posthog --skill writing-code-comments安装后在 Claude Code 中输入/writing-code-comments确认已加载。
详细介绍
编写代码注释
在添加或编辑任何注释之前先运行此流程。默认不写注释。命名清晰的优秀代码本身就能承载大部分含义;只有当注释能告诉读者代码本身无法表达的内容时,它才值得存在。
关口:一个问题
在编写注释之前,先回答:
这条注释告诉了未来的读者什么代码本身没有表达的信息?
如果答案是“它只是在复述代码做了什么”,删掉它。改为重命名变量或提取函数。
值得保留的注释回答的是代码无法表达的 为什么:
- ✅
# ATOMIC_REQUESTS is off, so wrap the two writes that must commit together - ✅
// Stripe sends the amount in cents; the rest of our system uses dollars - ✅
# Kept in sync with the enum in migrations/0042; update both
删除这些
复述代码的叙述
- ❌
counter += 1上方的# increment the counter - ❌
for user of users上方的// loop over users - ❌
return result上方的# return the result
如果一段代码需要靠叙述才能被理解,解决办法是拆成更小的函数和更好的命名,而不是加注释。
变更历史和聊天上下文
永远不要记录代码是如何演变成现在这样的。那属于提交信息和 PR 描述,在那里它与 diff 关联且可被搜索。放在源码里只是噪音,而且会立刻过时。
- ❌
# previously used a set here, switched to a list for ordering - ❌
// per PR #1234/# as discussed/# changed because the old way broke - ❌
# AI: generated this helper/// agent: refactored - ❌ 在迁移早已完成之后仍留在代码里的
# TODO(2024-01): remove after migration
易过期的测量值和当前状态标记
测量出的耗时、计数和速率会悄无声息地腐烂:没有任何机制强制它们更新,而一个腐烂的数字会误导下一个估算超时或分片数量的人。“currently” / “today” 这类限定词也是如此,因为去掉它们句子陈述的是同一个事实。要陈述这个数字所代表的持久关系。
- ❌
# skip the ~20 min build,而持久的事实是构建很昂贵 - ❌
# ci-backend runs ~28m, so 60m ≈ one red result,而不写“按最慢工作流的完整运行时长来设置” - ❌
# no story currently opts into webkit snapshots,去掉 “currently” 后陈述的是同一个事实 - ❌
# ~20 minutes in June, past 25 by July,因为趋势叙述属于变更历史
可以保留的数字:
- 带日期的快照:
# as of August 2024, Homebrew ships 4.13.2(日期让过时变得可见) - 对相邻代码字面量的复述:
300旁边的# runs that took >5 min (300 seconds)(它会随代码一起更新) - 平台常量:
# GitHub's comment size limit (~64KB) - 目标或预算:
# Target: ~15 min per shard(这是策略,不是测量值) - 有出处的证据:
# 30% peak memory observed on 16-core runs (#46853)(链接标明了日期)
注释掉的代码
删掉它;如果以后需要,版本历史里有。注释掉的代码对下一个读者来说是模棱两可的,他无法判断这是一条笔记、一个回滚方案,还是一个意外。
冗余的文档字符串和类型复述
- ❌ 用散文重复函数名的文档字符串:
get_user_by_id上的"""Gets the user by id.""" - ❌ 在已有类型的字段上写
# type: string - ❌ Python 测试文档注释(本仓库的约定是不写;测试名称本身就说明了问题)
保留这些
- 代码中不明显的 为什么:一个变通方案、一个性能权衡、一个规范上的怪癖、一个顺序约束。
- 关于存在于别处之后果的 警告:“修改这里会破坏缓存键”、“调用方依赖它是已排序的”。
- 指向读者无法从仓库中重建的上下文的 指引:指向规范、工单的链接,或某个令人意外的取值被选定的原因。
风格
像写技术文档那样写注释:明确且精确。说明推理过程,让读者不必自行推断。长度本身不是目标,无论长短:不要为了显得简洁而删减注释,也不要为了显得详尽而堆砌内容。把需要说的说清楚,然后停下。
- 明确且技术化。 说明原因与结果。指明实际的条件、取值和后果。读者不应需要从一句提示中重构你的推理。
- 大体使用 ASD-STE100 简化技术英语。 使用主动语态、简单时态、每句一个意思,并保持术语一致。
- 让长度随内容而定。 一行能覆盖就用一行;推理需要更多空间就用更多。简洁和冗长都不是目标。
- 不要用破折号。 要避免的迹象是用破折号连接的两段式短语,例如
# do the thing — it's faster。改用真正的连接词("because"、"so that"、"which means"、"to avoid")。 - 解释为什么,而不是是什么。 是什么在代码里;为什么通常不在。
- 在移动或重构代码时保留现有注释,除非改动使它们不再正确。不要仅仅因为你在迁移函数,就把已有的“为什么”丢掉。
- 与周围的密度保持一致。 不要给一个本来没有注释的文件逐行添加注释;也不要把一个注释完善的模块删得干干净净。
破折号的解决办法是连接词,而不是更多的字。破折号去掉后,简短的注释就没问题:
- ❌
# batch here — avoids N+1 - ✅
# batch here to avoid an N+1 against posthog_organizationmembership
当你想要写注释时
按顺序尝试:(1) 一个更好的命名,(2) 一个更小的函数,(3) 一个类型。只有当这些都承载不了含义时,才去写注释。