代码润色
一种基于约束的协议,用于规范化代码注释并执行安全、不改变语义(non-semantic)的清理工作。本技能的存在基于一个事实:人工编写的代码常常带有随意、过时或缺失的注释,而我们的目标是在完全不触及行为的前提下,使文档达到专业水准。
本文件是自包含的。执行本协议时无需依赖任何其他技能文件。
首要原则
注释与非语义性清理是本技能的职责。逻辑绝非职责。任何会改变代码实际行为——而不仅仅是文字表述或排版方式——的改动,都超出了本技能的范围,无论该修正看起来有多么"显然正确"。
适用场景
在以下情况下应用本技能:
- 用户希望对现有代码进行"清理"、"专业化"或"润色"
- 代码正在为代码评审、交接、开源发布或文档撰写做准备
- 一个文件中混杂着人工撰写和 AI 撰写的注释,需要统一为同一种专业语气
- 注释已过时、缺失、冗余,或语气过于随意(如发泄、占位符、内部玩笑)
- 用户希望改进注释,但明确不希望改动逻辑
在以下情况下不要应用本技能:
- 用户希望修复 bug 或改变行为(这是另一项工作——逻辑修改不在此处范围内)
- 用户希望进行完全的重写或架构重组
- 唯一需求是新增功能或新特性
阶段 0 — 完整通读
在动手编辑之前,请通读整个文件(如果代码库较大,则通读相关模块的全文——而不仅仅是当前函数)。阅读过程中不要边读边写注释或清理。脱离完整上下文写出来的注释只能算是猜测,而猜测正是"专业注释"走向错误的根源。
需要识别:
- 文件所使用语言的惯用注释/文档字符串规范(JSDoc、Python docstrings、Rust 的
///、XML 文档注释等) - 文件内已有的注释风格——遵循现有风格,而不是引入外部约定
- 任何承载真实且非显而易见信息的注释(竞态条件、针对外部 bug 的变通方案、"请勿重排序"的警告、业务规则的合理性说明等)
阶段 1 — 注释审计
在动手修改之前,先将每一条既有注释归入以下类别:
| 类别 | 示例 | 处理方式 |
|---|---|---|
| 无效/情绪化 | // wtf is this、// idk why but it works |
抹除情绪化语气,提取下方的真实信息并以专业语气重写;若确实不含任何信息则直接删除 |
| 占位符 | // fix later、// TODO hack |
将其转换为格式规范的 TODO: 注释,并清晰陈述实际问题;若已过时或已解决则移除 |
| 死代码注释 | 大段被注释掉的代码块 | 直接删除,除非周围上下文明确表示这是有意保留的内容(例如有文档说明的兜底方案)——此类情况应向用户标记,而不是默默删除 |
| 冗余 | i++ // increment i |
删除——代码本身已经表达了此意 |
| 过时/错误 | 注释描述的行为与代码当前实际行为不符 | 重写以匹配当前行为。向用户标记这条注释曾是过时的,不要默默修复了事 |
| 有价值但欠规范 | // careful, this breaks if you call it twice, learned that the hard way |
保留其信息内容,重写其语气。绝不能因为措辞随意就删除有实际价值的警告 |
| 缺失 | 复杂逻辑、不直观的业务规则或无文档字符串的公共 API | 新增注释。简单明了、自身可解释的代码行不必过度注释 |
阶段 2 — 非语义性清理
范围严格限定在不改变行为的改动:
- 统一的缩进与空白
- 与文件其余部分一致的花括号/方括号风格
- 移除确凿的死代码(不可达分支)——仅在毫无歧义时执行,并在总结中标记
- 拆分过长的行以提升可读性
- 为提升清晰度对局部变量重命名,仅允许针对私有/局部作用域的名称,仅在该改进毫无歧义时进行——任何跨文件被引用或对外导出的标识符不得擅自重命名,必须事先明确指出
超出上述范围的任何操作——重排逻辑、抽取函数、更改控制流、修改算法——均超出本技能的范畴。
阶段 3 — 注释重写/新增
对每一条被触及或新增的注释,遵循以下标准:
- 解释为什么,而不是解释做了什么。 代码本身已经展示了做了什么;注释要立足之地,就在于说明意图、取舍或非显而易见的约束。
- 使用该语言惯用的文档格式来为函数、类和公共 API 编写注释(JSDoc、docstrings、
///等)——若文件中已存在约定,则遵循既有约定。 - 保持简洁。 不堆砌、不复述显而易见的内容、不写凑字数的句子。
- 不得使用非正式语域。 不要玩笑、不要发泄、不要第一人称的旁白("我觉得这样能跑通是因为...")。
- 不得使用 AI 风格的标志性措辞。 避免诸如"本函数负责..."或"请注意..."之类的填充式开头,也不要滥用破折号。像一位严谨的高级工程师那样,朴素而直接地书写。
- 不要杜撰行为。 如果你不确定某段代码为何这样做,就只陈述代码本身做了什么,而不是编造一个看似合理的理由。
阶段 4 — 校验
在交付结果之前:
- 确认编辑后文件的逻辑与原文件在行为上完全一致——允许的差异仅限于注释和空白,以及阶段 2 中所做的有限清理
- 从头到尾完整地重读 diff,而不是孤立地只看被修改的行,以免遗漏任何意外改变原义的改动
- 若重写后的注释丢失了原文中存在的信息(包括以非正式语气陈述的信息),即视为失败——需要回溯并保留该信息
阶段 5 — 结果汇报
向用户汇报时,应给出总结而不是直接丢回一份静默的 diff:
- 重写了、新增了或删除了多少条注释,各自出于何种原因
- 任何被标记为"非正式但包含真实警告"的注释——确认其信息已被完整保留
- 任何已删除的死代码或过时注释,逐条列出
- 任何你无法确定而选择保留原状的内容
示例
无效/情绪化 → 专业
// before
// ugh this took forever to figure out. api rate limits us super hard in prod so we have to do exponential backoff here. just leave it alone
function retryFetch(url, attempts) { ... }
// after
// Uses exponential backoff to handle aggressive API rate-limiting in production.
function retryFetch(url, attempts) { ... }
冗余 → 删除
# before
count += 1 # increment count by 1
# after
count += 1
有价值但欠规范 → 重写语气,保留信息
# before
# careful, this breaks if you call it twice, learned that the hard way
# after
# Not idempotent: calling this more than once per session corrupts the
# cache index. Callers must guard against duplicate invocation.
缺失 → 新增
// before
public double calculate(double base, int tier) {
return base * (tier > 2 ? 0.85 : 1.0);
}
// after
/**
* Applies the loyalty discount. Tiers above 2 qualify for a 15% discount;
* this threshold matches the current pricing policy, not a technical limit.
*/
public double calculate(double base, int tier) {
return base * (tier > 2 ? 0.85 : 1.0);
}
过时/错误 → 修正并标记
// before
// returns nil if user not found
func GetUser(id string) (*User, error) { ... } // now returns ErrNotFound instead
// after
// Returns ErrNotFound if the user does not exist.
func GetUser(id string) (*User, error) { ... }
// (flagged to user: original comment was stale — function used to return nil,
// now returns a named error)
安全与防护说明
本技能绝不会:
- 修改程序逻辑、控制流或算法行为
- 重构代码结构(抽取/内联函数、重排执行顺序、改变架构)
- 在未经明确确认的情况下重命名任何公开的、对外导出的或被跨文件引用的标识符
- 仅因注释语气随意就将其删除,而不先检查其中是否包含真实信息
- 在无法从上下文获知真实原因时,为某条注释杜撰一个理由——只陈述确有依据的内容
局限性
- 无法验证运行时行为——阶段 4 只是基于通读的 diff 核对,并非实际运行测试。对于非平凡文件,应用本技能后用户仍应运行真实的测试套件进行验证。
- 对模糊情况的判断(例如"这段死代码是有意保留还是被遗忘的")默认采用标记而非猜测的处理方式——这意味着部分清理工作需要由人类快速给出 yes/no,而不是默默完成。
- 本技能不能取代 linter 或 formatter——阶段 2 的清理刻意保持保守,不会强制执行完整的代码风格规范(例如最大行长度规则、import 排序规则),除非这些规则从文件其余部分可轻松推断。
- 注释质量的边界取决于能否从上下文推断出代码的真实意图。如果"为什么"确实无法从文件中还原(缺乏领域知识、没有提交历史、没有可参考的工单),那么诚实的产出是一条描述做了什么的注释,而非一个自信却虚构的为什么。
- 对于大型文件或不熟悉的代码库,阶段 0 漏看上下文并因此影响注释措辞的风险会上升——在阶段 5 的汇报中标明不确定性,而不要把把握不高的重写呈现为板上钉钉的结论。