注释写了等于没写,问题出在这几处

函数上面工工整整写着「处理订单数据」,是我自己半年前留下的注释。我盯着它看了很久,想知道金额是分还是元、超时走哪条分支,也想弄明白代码注释写了等于没写怎么回事。

它一个字都没帮到我,问题通常不是态度,是写的位置和内容不对。

一、代码注释写了等于没写怎么回事:复述代码在做什么

最常见的无效注释,是把代码翻译一遍。代码写的是给状态加一,注释写的是「状态加一」。

这种注释的唯一作用是增加阅读量。它的根本问题在于:代码会改,注释不会跟着改,于是它从没用变成误导。

判断方式很直接:把这条注释删掉,你会不会少知道一件事?不会,那它就是废话。

更麻烦的是它还会稀释信号——真正有用的注释混在里面,读者会一起跳过。

二、真正该写的是「为什么」,不是「是什么」

我现在只在一种情况下写注释:这段代码看起来可以更简单,但因为有某个原因不能更简单。

比如这里必须多一次判断,是因为上游的历史数据存在不干净的情况;比如这里不能提前返回,是因为要保证某个清理动作一定执行。

这类信息代码本身表达不了,删掉之后下一个人(包括半年后的我)一定会想把它「优化」掉。注释是拿来挡住未来的错误改动的。

写这种注释有个技巧:把「原因」和「后果」一起写。只写原因,别人可能觉得不重要;写上改了会怎样,他才会停手。

三、注释和代码不一致,比没有注释更糟

没有注释,人会去读代码;有一句过时的注释,人会先信它。

我遇到过一次典型的:注释说这个字段可以为空,代码里已经加了非空校验。我照着注释写了一版调用逻辑,测试直接挂了。

过时的注释是一种主动误导。所以改代码的时候,我会顺手看一眼附近的注释,对不上就删掉或者改掉。代码注释写了等于没写怎么回事,很多答案就在这种不一致里。

顺手看一眼的成本几乎为零,但它能挡住后面一连串的误判。

四、注释被当成补丁,掩盖了命名问题

还有一种情况:注释在替一段代码道歉。

比如注释写「这里临时处理一下,后面要改」,而这段「临时」已经存在很久了。这种注释不是信息,是欠条。

大多数需要注释解释的变量名和函数名,其实应该被改名。名字说清楚了,注释就不用写了。

改名的成本通常比写一句准确的注释更低,而且改名之后,所有调用处都会跟着变。

五、代码注释写了等于没写怎么回事:自检方式是删掉之后再读一遍

我现在的做法很土:写完注释之后,把它删掉,再读一遍那段代码。

如果读起来毫无损失,说明这条注释不该存在;如果读起来会丢掉一个重要前提,那它就值得留着。

判断一条注释好不好,标准是它删掉之后你会不会犯错。代码注释写了等于没写,说到底就是没通过这一条。

六、止损清单:我现在怎么处理旧注释

第一,看到复述代码的,直接删;第二,看到和代码不一致的,先改代码注释,再确认代码本身是不是写错了;第三,看到「临时」「待优化」这种,要么立刻处理,要么变成一个真正的待办;第四,需要在关键逻辑处补的,只补「为什么」。

处理完这几类,注释量通常会变少,但可读性会明显变好。注释的价值不在于多,在于每一条都在拦一个坑。这也是代码注释写了等于没写怎么回事最容易被忽略的一面。

常见问题

Q:注释写了等于没写是怎么回事?

A:多半是注释在复述代码,而没有提供代码本身表达不了的信息。把重点从「这段代码做什么」换到「为什么必须这样写」,注释才有价值。

Q:代码改动了,旧注释要不要一起改?

A:要,而且优先级很高。过时的注释会误导后来的人,危害比完全没有注释更大。改代码时顺手看一眼附近的注释,对不上就改或删。

Q:什么样的代码不需要注释?

A:命名清楚、结构直白的代码不需要。如果你需要通过注释才能解释一个函数在做什么,先考虑改名和拆分,而不是先写注释。

相关阅读


本文作者西米,37 岁程序员,一个人加五个 AI 员工在跑一家公司。踩过的坑和真实账本都写在公众号「西米分享」。

完整代码、踩坑清单与最新进展,都在公众号。

📱 关注公众号「西米分享」