注释写了等于没写,问题出在这几处
函数上面工工整整写着「处理订单数据」,是我自己半年前留下的注释。我盯着它看了很久,想知道金额是分还是元、超时走哪条分支,也想弄明白代码注释写了等于没写怎么回事。
它一个字都没帮到我,问题通常不是态度,是写的位置和内容不对。
一、代码注释写了等于没写怎么回事:复述代码在做什么
最常见的无效注释,是把代码翻译一遍。代码写的是给状态加一,注释写的是「状态加一」。
这种注释的唯一作用是增加阅读量。它的根本问题在于:代码会改,注释不会跟着改,于是它从没用变成误导。
判断方式很直接:把这条注释删掉,你会不会少知道一件事?不会,那它就是废话。
更麻烦的是它还会稀释信号——真正有用的注释混在里面,读者会一起跳过。
二、真正该写的是「为什么」,不是「是什么」
我现在只在一种情况下写注释:这段代码看起来可以更简单,但因为有某个原因不能更简单。
比如这里必须多一次判断,是因为上游的历史数据存在不干净的情况;比如这里不能提前返回,是因为要保证某个清理动作一定执行。
这类信息代码本身表达不了,删掉之后下一个人(包括半年后的我)一定会想把它「优化」掉。注释是拿来挡住未来的错误改动的。
写这种注释有个技巧:把「原因」和「后果」一起写。只写原因,别人可能觉得不重要;写上改了会怎样,他才会停手。
三、注释和代码不一致,比没有注释更糟
没有注释,人会去读代码;有一句过时的注释,人会先信它。
我遇到过一次典型的:注释说这个字段可以为空,代码里已经加了非空校验。我照着注释写了一版调用逻辑,测试直接挂了。
过时的注释是一种主动误导。所以改代码的时候,我会顺手看一眼附近的注释,对不上就删掉或者改掉。代码注释写了等于没写怎么回事,很多答案就在这种不一致里。
顺手看一眼的成本几乎为零,但它能挡住后面一连串的误判。
四、注释被当成补丁,掩盖了命名问题
还有一种情况:注释在替一段代码道歉。
比如注释写「这里临时处理一下,后面要改」,而这段「临时」已经存在很久了。这种注释不是信息,是欠条。
大多数需要注释解释的变量名和函数名,其实应该被改名。名字说清楚了,注释就不用写了。
改名的成本通常比写一句准确的注释更低,而且改名之后,所有调用处都会跟着变。
五、代码注释写了等于没写怎么回事:自检方式是删掉之后再读一遍
我现在的做法很土:写完注释之后,把它删掉,再读一遍那段代码。
如果读起来毫无损失,说明这条注释不该存在;如果读起来会丢掉一个重要前提,那它就值得留着。
判断一条注释好不好,标准是它删掉之后你会不会犯错。代码注释写了等于没写,说到底就是没通过这一条。
六、止损清单:我现在怎么处理旧注释
第一,看到复述代码的,直接删;第二,看到和代码不一致的,先改代码注释,再确认代码本身是不是写错了;第三,看到「临时」「待优化」这种,要么立刻处理,要么变成一个真正的待办;第四,需要在关键逻辑处补的,只补「为什么」。
处理完这几类,注释量通常会变少,但可读性会明显变好。注释的价值不在于多,在于每一条都在拦一个坑。这也是代码注释写了等于没写怎么回事最容易被忽略的一面。
常见问题
Q:注释写了等于没写是怎么回事?
A:多半是注释在复述代码,而没有提供代码本身表达不了的信息。把重点从「这段代码做什么」换到「为什么必须这样写」,注释才有价值。
Q:代码改动了,旧注释要不要一起改?
A:要,而且优先级很高。过时的注释会误导后来的人,危害比完全没有注释更大。改代码时顺手看一眼附近的注释,对不上就改或删。
Q:什么样的代码不需要注释?
A:命名清楚、结构直白的代码不需要。如果你需要通过注释才能解释一个函数在做什么,先考虑改名和拆分,而不是先写注释。
相关阅读
本文作者西米,37 岁程序员,一个人加五个 AI 员工在跑一家公司。踩过的坑和真实账本都写在公众号「西米分享」。
完整代码、踩坑清单与最新进展,都在公众号。
📱 关注公众号「西米分享」