注释写得越详细,代码往往越难维护
接手一个老项目时,你可能见过这样的文件:两百行代码,配了六十多行注释,逐行解释“这里把变量加一”“这里调用接口”。新同事读了半天,依然不知道这段逻辑为什么存在。
问题不在注释太少,而在注释写错了内容。
注释和代码各自该负责什么
代码负责说清“是什么”:做什么计算、按什么顺序、处理哪些分支。注释负责说清“为什么”:为什么这样选、绕开了什么坑、有什么外部约束。
一旦注释开始解释“是什么”,它就变成了代码的复述。复述有两个后果:信息冗余,以及必然的腐化——改代码时忘了同步注释,注释就从帮助变成了误导。
值得写下来的三类信息
- 为什么这样做:做过什么对比、放弃了哪条更直观但更慢的路径
- 外部约束:兼容某个老版本、绕开第三方接口的已知缺陷、合规要求
- 看不见的副作用:会修改全局状态、会触发一次额外的网络请求
这三类信息有个共同特征:光读代码看不出来。写下来,未来的人(很可能是你自己)才不用重新推演一遍。
一个真实的例子
有段代码在发起请求前先做了一次二点五秒的等待。注释写的是“等待两秒半”。半年前下一个人把它删掉了,理由很充分:看不出必要性。
结果上线后旧版客户端大面积报错,因为那段时间是绕开对方接口限流窗口的。这段逻辑的真正含义只能靠注释传达:不要动,因为对方在整点的前一秒会拒绝请求。
注释最大的价值,是阻止下一个人做一件看起来合理、实际会出事的事。
一个团队的调整
某后端小组做过一次实验:花两小时把项目里解释“做什么”的注释全部删掉,同时把命名改得更具体。代码量减少了,可读性反而上升。
他们随后定了一条规则:新写的注释必须能回答“为什么不那样做”。这条规则让评审时讨论的重点从格式转到了决策依据,评审的往返次数也随之下降。
三个常见的认知偏差
偏差一是认为注释越详细越专业。详细的复述只会增加维护成本,一份与代码不同步的详细注释比没有注释更危险。
偏差二是用注释代替重构。函数太长、嵌套太深,真正的解法是拆函数,而不是在开头写一段说明。
偏差三是用注释弥补糟糕的命名。`data2` 加上一行注释说明它是退款记录,不如直接命名成 `refundRecords`,让注释回到它该管的地方。
写注释前的三个自问
不看注释,代码能不能看出它在做什么;这段逻辑有没有更直观的写法;三年后的人读到它,会不会因为缺少背景而误删。
三个问题里最后一个最有价值。删除是维护中最危险的动作,而它多数发生在信息缺失的时候。
反过来,如果一段代码存在的原因非常反直觉,注释就不是可选项,而是必要的成本,省下这几行会以故障的形式还回来。
可以立刻做的两件事
打开你最近改过的一个文件,找出所有解释“做什么”的注释,把其中有价值的部分转化成更具体的变量名或函数名,然后删掉注释。
在写下一条新注释时,先问自己:不看注释,光读代码能不能知道它在做什么?如果能,就不写;如果不知道它为什么存在,就写这一句。