code-comments
Code Comments · 代码注释指南
帮助团队编写真正有价值的代码注释——解释"为什么",而不是"是什么"。
触发关键词: 写注释、加注释、注释规范、注释审查、comment、docstring、JSDoc、注释怎么写
核心原则
解释 Why,不解释 What。
注释的唯一价值是传达代码本身无法传达的信息:设计决策、业务背景、非直觉行为、已踩过的坑。
注释前先问自己:
✅ 这解释了为什么代码这样写吗?
✅ 这段背景知识读者不看注释会知道吗?
❌ 这只是把代码翻译成自然语言吗?→ 删掉它
三类读者:
- AI 助手(每次只看单个文件)
- 不了解上下文的队友
- 六个月后的自己
流程
注释任务进度:
- [ ] 明确任务类型(新增注释 / 审查现有注释 / 制定规范)
- [ ] 确认目标语言 / 框架
- [ ] 识别需要注释的层级(文件头 / 函数 / 内联 / 架构 / TODO)
- [ ] 按层级逐一编写或审查
- [ ] 输出注释规范摘要(可选)
注释层级
一、文件头注释
每个文件开头说明:这个文件是什么、它在整个系统里扮演什么角色、为什么这样设计。
模板:
// {文件名}
//
// {一句话描述职责}
//
// 为什么这样设计:{设计决策或背景}
// 与其他模块的关系:{依赖方 / 被依赖方}
示例(TypeScript):
// UserAuthContext.tsx
//
// 管理全应用的认证状态,包裹根组件为所有子组件提供
// 登录状态、用户信息和认证方法。
//
// 为什么用 Context 而不是 Redux:Auth 状态读多写少,
// 会话期间几乎不变。Context 避免了 actions/reducers 的仪式感。
// 相关文件:authApi.ts(网络请求), useAuth.ts(消费 hook)
示例(Python):
# retry_policy.py
#
# 处理网络请求的自动重试逻辑。
# 使用带抖动的指数退避,避免服务器恢复后的"惊群效应"。
#
# 被 api_client.py 和 background_sync.py 使用。
# 错误分类逻辑见 network_error.py。
二、函数 / 方法注释
记录契约(contract),不记录实现细节。
包含:
- 副作用(网络请求、文件写入、状态变更)
- 返回值的含义,特别是模糊边界情况
- 非直觉的参数约束或边界条件
- 函数达成什么(不是怎么做到的)
跳过:简单 getter、一眼能看懂的单行、有描述性名字的私有辅助函数
示例(TypeScript JSDoc):
/**
* 根据重量和目的地计算运费。
*
* 分层计价:< 1 磅走固定费率,1-5 磅走区域费率,> 5 磅触发货运计算。
*
* 对于不支持配送的地址返回 $0 而不是抛出异常——
* 调用方如需区分"免运费"和"不可配送",应先调用 canShipTo()。
*
* @param weightLbs - 包裹重量(磅)
* @param zipCode - 目的地邮政编码
* @returns 运费(美元),不可配送时返回 0
*/
function calculateShipping(weightLbs: number, zipCode: string): number
示例(Python docstring):
def sync_user_preferences(user_id: str, prefs: dict) -> SyncResult:
"""
将本地偏好变更推送到服务器,并拉取远端变更。
冲突解决策略:安全类设置服务端优先,UI 偏好本地优先。
完整冲突矩阵见 PREFERENCES.md。
应用切换到前台时自动调用,也可从"设置 → 立即同步"手动触发。
"""
三、内联注释
谨慎使用,只在以下情况出现:
- 非直觉的实现选择(绕过 bug、性能权衡)
- 魔法数字的含义
- 看似错误但实际正确的代码
示例:
// 防抖 300ms 避免每次击键都请求 API。
// 300ms 在用户测试中感觉流畅,同时减少约 80% 的请求量。
const debouncedSearch = useMemo(
() => debounce(executeSearch, 300),
[executeSearch]
);
# 优先处理最旧的任务。新任务更可能再次被修改,
# 放到最后处理可减少无效计算。
queue.sort(key=lambda x: x.created_at)
// 这里强制解包是安全的——viewDidLoad 保证 storyboard 已连接此 outlet。
// 如果为 nil 应该立即崩溃,而不是之后静默失败。
let tableView = tableView!
四、架构决策注释
当代码体现了重要的设计决策,需要说明权衡取舍。
格式:
// ARCHITECTURE NOTE: {标题}
//
// {决策内容}
//
// 好处:...
// 代价/权衡:...
示例:
// ARCHITECTURE NOTE: 购物车使用事件溯源
//
// 购物车状态从事件(添加、删除、修改数量)重建,而非直接存储。
// 好处:
// - 可向用户展示完整购物历史
// - 可重放事件用于调试
// - 可对历史操作追溯应用促销
//
// 权衡:读取当前状态需要重放所有事件。
// 用 Redis 缓存计算结果(5 分钟 TTL)保证读性能。
// 缓存失效逻辑在 CartEventHandler.ts 中。
五、TODO / FIXME / HACK
必须可追溯,包含:原因、负责人(可选)、关联 issue(推荐)。
// ✅ 好的 TODO
// TODO(@alice): Safari 14 修复 flex bug 后删除此 workaround。
// 跟踪 issue: #892
// TODO: 等后端接口稳定后移除此兜底逻辑。
// 后端接口预计 Q2 上线,见 BE-456。
// HACK: 绕过 iOS 16 Safari 的 flexbox 渲染 bug。
// Bug 已在 iOS 17 修复,最低版本升级后可删除。
// FIXME: 用户快速切换时有竞态条件,需要取消 in-flight 请求。
// 复现步骤见 issue #1024。
// ❌ 没用的 TODO
// TODO: fix this(没有原因,没有追踪)
注释审计
当用户要求审查现有代码注释质量时,按以下六个维度评分(每项 0-10 分):
| 维度 | 检查内容 |
|---|---|
| Why not What | 注释解释原因而非复述代码;无废话注释 |
| 密度合理 | 注释/代码行比在 15-20% 之间;不过多也不缺失 |
| 无禁止内容 | 无作者名/日期;无历史变更记录;无注释掉的死代码 |
| 文档质量 | 函数注释与签名匹配;参数/返回值有描述 |
| 时效性 | 注释与代码行为一致;无过时引用 |
| 清理遗留 | 无无上下文的 TODO;无 deprecated 残留;无注释掉的代码块 |
输出格式:
注释质量审计报告
================
总分:X.X / 10
维度得分:
Why not What : X/10 [问题数: N]
密度合理 : X/10 [实际比例: X%,目标 15-20%]
无禁止内容 : X/10 [问题数: N]
文档质量 : X/10 [问题数: N]
时效性 : X/10 [问题数: N]
清理遗留 : X/10 [问题数: N]
主要问题(按严重程度):
🔴 CRITICAL file:line 描述
🟠 HIGH file:line 描述
🟡 MEDIUM file:line 描述
🔵 LOW file:line 描述
改进建议:
1. [最优先] ...
2. ...
禁止事项
| 禁止 | 原因 |
|---|---|
// 循环遍历用户列表 |
代码已经说了这件事 |
// i 加 1 |
完全废话 |
// 2024-01-15 张三修改:... |
这是 git 的工作 |
| 注释掉的大段代码 | 用 git,不用注释回收站 |
// TODO: fix |
没有上下文和追踪的 TODO 毫无意义 |
| 注释值而非引用常量名 | 值改变时注释不会跟着改,产生误导 |
写作风格
- 用普通话 / 简明英文,别堆术语
- 主动语态:「此函数验证…」而非「验证由…执行」
- 具体不含糊:「重试 3 次,间隔 1 秒指数退避」> 「处理重试」
- 有时效性的内容标明删除条件:绕过 bug 的 workaround 应注明何时可删
- 引用常量名而非重复其值,防止值变更后注释过时
输出规范
完成注释编写或审查后:
- 内联到代码中(首选):直接把注释加在对应位置
- 注释规范摘要(团队用途):可输出 Markdown 规范文档,保存为
COMMENTS_GUIDE.md - 审计报告(审查模式):保存为
comments-audit-{YYYY-MM-DD}.md
More from paulgung/ths-skills
four-knowns
对指定技术领域进行"四个知道"系统性调研,覆盖横向(行业趋势、竞争对手、政策监管、技术发展)和纵向(学术前沿、工业水平、工程架构、自身定位)八个维度。当用户要求进行技术调研、行业分析、竞品分析、技术选型、趋势研究时使用。
10performance optimizer
Optimize application performance and scalability. Use when investigating slow applications, scaling bottlenecks, or improving response times. Covers profiling, caching, database optimization, and frontend performance.
1