code-comment
——注释经常成为代码质量中被忽视的部分。烂注释比没有注释更危险,因为它会主动误导。
一、核心原则:注释权责对齐作用域
注释的内容必须严格对齐当前方法/类/字段的作用域。 非必要不在注释中超出本作用域,避免未来项目变更时注释腐化,变成误导他人的"屎山"。
具体禁止两类越界:
- 向上溯源:写明谁调用了我、是不是唯一入口、由哪个上游保证了入参非空等。
- 向下探索:写明我的产物流向哪里、被哪些下游消费、对哪些消费方有/无影响等。
错误案例 1:方法 javadoc 向上溯源
/**
* 搜索推送新模型的唯一入口:本应用所有推往搜索的 item 数据请求都收敛于此方法。
* 调用来源:定时全量(FullSyncSchedulerJob)、binlog 增量(ItemBinlogConsumer)、
* 手工后门(JobController#itemSyncBackDoor)。
*
* @param itemIds 待推送的条目 id 列表,为空时直接返回
*/
public void handleItemSearchData(List<Long> itemIds) { ... }
"唯一入口""都收敛于""调用来源""手工后门"——全部超出本方法权责,向上探索调用链。一旦新增/删除调用方,这些注释立刻过时误导人。
正确写法(聚焦本方法做什么):
/**
* 处理待推送的搜索条目数据:按 itemId 拉取明细、构建搜索文档并推送。
*
* @param itemIds 待推送的条目 id 列表,为空时直接返回
*/
public void handleItemSearchData(List<Long> itemIds) { ... }
错误案例 2:字段注释向下探索消费链路
/**
* 内容地区归属:domestic(国内)/ overseas(海外)
* 影响评估:本字段仅做单向序列化输出,输出去向为 databus topic ItemSearch-T
* (SearchPublishService)及 FTP 文件(FtpScheduler);新增本字段对现有调用方
* 无破坏性影响,老的消费方按需取用、忽略未知字段即可。
*/
private String areaOwner;
"输出去向""消费方""对调用方无破坏性影响"——向下探索了字段的消费链路。下游一旦调整,注释即腐化。
正确写法(只描述字段语义):
/**
* 条目地区归属:domestic(国内)/ overseas(海外)。
*/
private String areaOwner;
错误案例 3:行内注释跨方法引用 / 溯源
// itemBaseInfo 非空由上游 buildItemSearchList 过滤保证(null 项不会进入本方法)
// 内容地区归属:当前不读库,直接兜底国内 domestic,与主链路 reduceItemSearchByItem 保持一致
"由上游 xxx 过滤保证""与主链路 xxx 保持一致"——既向上溯源又横向引用其他方法。
正确写法:
// 条目地区归属:[注: 截至 2026-06-18] 不读库,直接兜底国内 domestic
二、五条强制约束
专注当前作用域:仅基于当前方法/类/字段的代码逻辑、入参、出参生成注释。严禁使用"唯一入口""都收敛于""调用来源""手工后门""由上游 xx 保证""与主链路 xx 一致""下游消费方""对调用方无影响"等描述外部调用链或横向引用其他方法的词汇。
架构现状必须带时间戳:如果确有必要在注释中说明会随项目演进而变化的现状(如"暂不读库直接兜底""目前仅支持 X 品类""临时方案"等),必须加时间标记,格式固定为
[注: 截至 YYYY-MM-DD](日粒度,不要用月粒度)。例如:// 条目地区归属:[注: 截至 2026-06-18] 不读库,直接兜底国内 domestic判定要点:描述的是"会过期的阶段性状态"才加时间戳;描述"稳定的代码逻辑/字段语义/确定的数据来源"则不需要。例如"当前条目""当前日期"这类代码逻辑指代(指运行时正在处理的对象)不是时间概念,不用加。
禁止硬编码行号:注释(尤其测试注释)中严禁出现"第 327 行""见第 948 行"等具体行号。代码一改行号即错,是高频腐化源。需要指向某处时,用方法名/字段名引用(如
SearchService#buildItemSearchBackdoor、ItemDoc#getAreaOwner),不写行号。禁止过度脑补:严禁根据方法名/字段名自行猜测并生成未在当前代码块中体现的业务逻辑。不确定业务含义时,宁可只描述代码行为,也不要臆造业务背景。
测试注释同样适用:以上约束对单元测试注释一视同仁。测试 javadoc 推荐结构化描述「场景 / 覆盖目标 / 预期」,但同样不写行号、不堆砌"主链路""后门"等措辞,覆盖目标用方法名引用。
三、鼓励主动补充注释
约束是为了"不写坏注释",不是为了"少写注释"。在不违反上述约束的前提下,鼓励主动为以下情形补注释:
- 非显而易见的取舍:为什么选 A 方案而非 B、为什么兜底某个默认值、为什么这里要判空。
- 边界条件与坑点:空集合/空指针的处理、越界风险、并发假设、幂等性。
- 复杂逻辑的意图:一段不直观的算法/正则/位运算在"做什么、为什么"。
- 有意的"反常"代码:看起来像 bug 实则有意为之的写法,注明原因避免被"好心改错"。
补注释时牢记:写"为什么",而非复述"做了什么"(做了什么看代码即可)。
四、提交前自检清单
写完 / 改完注释,逐条过:
- 没有向上溯源(调用方、唯一入口、上游保证)
- 没有向下探索(产物去向、下游消费方、对调用方的影响)
- 没有横向引用其他方法做对比("与 xx 保持一致")
- 描述阶段性现状的,已加
[注: 截至 YYYY-MM-DD](日粒度) - 没有硬编码行号,指向他处用方法名/字段名引用
- 没有脱离代码事实的业务脑补
- 复杂逻辑/关键取舍/边界坑点已主动补注释,且写的是"为什么"
- 测试注释同样满足以上各条