可读代码编写炸鸡四 (上篇) - 来写注释
大家好,我是多选参数的一员 —— 大炮。
从上一篇开始,我们针对代码可读性的优化范围从
一个变量,一个函数名
扩大到了
多行代码,多个函数
而上一篇炸鸡 审美 中,将这个范围下的优化又分成了两个部分
代码审美
代码注释
所以在讲完代码审美之后,自然而然这一篇炸鸡要讲一讲 代码注释 的可读性优化。
同时上篇炸鸡抛出了一个问题。在本篇炸鸡,应该能找到答案。
关于注释的炸鸡的行文思路如下图所示。
公众号后台回复 「注释」 获得源 pdf 文件
什么时候不需要注释
一般你加入了一个项目组,领你进来的人通常会帮助你熟悉环境,而你可能记得最清楚的便是
xxx 是不能做的,你要注意。
所以在写注释前,先要注意一下什么时候 不需要注释。
1. 代码本身能让阅读者快速判断
我举个最极端的例子:
很明显,这样的代码阅读者能 快速 判断出其功能和意图,注释就是多此一举,为了注释而注释。
所以这时候应该能理解 上一篇炸鸡 抛出的问题了吧?
当然如果遇到这样的一行代码,那么注释是有必要的。
因为虽然阅读者可以通过一定时间的阅读可以得出结果,但是这种 一行嵌套多个方法 的代码可读性已经下降,所以加上注释能帮助阅读者快速理解代码。
当然,这样的代码,也可以利用临时变量将嵌套的函数结果暂存,同时对临时变量恰当命名,也能达到一定的效果,而这个方面的内容在之后的炸鸡会涉及,本篇就不再赘述。
2. 注释没有提供更多的信息
如果只是对一个函数这样的声明注释,那么大可以删去。
亦或者提供更多的信息:
当然,这个已经是下文的内容了。
3. 命名不好
如果你有稍微了解过我之前的几篇关于代码命名的炸鸡,可以理解好的命名已经能提供不少信息。
如下代码所示,myFind
是个不明白其含义的函数命名。
看了注释才明白这个函数的作用,可是如果直接将函数名换成 find2ndAppointChar
,也许会更恰当,而且还省去了注释。
我们可以得到一个不等式:
好的命名 > 坏命名 + 注释
确定为代码写上注释
那么我们已经明确了什么时候不需要注释,那么接下来就需要知道确定要写注释的时候,该怎么写。
如何写注释
1. 记录思想
当我们写注释的时候,可以把当时写这段代码的动机意图,所思所想写下来。大致可以分成两点:
记录内在逻辑算法。
承认代码的瑕疵。
我们利用注释可以记录一段代码的 内在逻辑算法,我们拿前文的例子来说明即可。
当然,我们的代码总会因为一些客观原因并不能尽善尽美,所以完全可以利用注释 提出这段代码的瑕疵。
上述代码我们可以注意到,todo
这样的标签,利用这样的标签可以告诉阅读者关于这段代码的瑕疵。
所以我们可以看到,利用注释,阅读者便能很快地了解你当时的想法和企图,而且这个阅读者很有可能就是未来几个月后的你。
这里插一嘴,如果你用 vscode 编写代码,推荐一个还不错的注释插件 Better Commments
。
利用如图方式提供较为好辨认的提示
2. 提供维护和修改的指导思路
你的代码不一定永远都是你来维护,就好像我之前一段时间接手了好几个别人的写了一半的代码。所以为了方便后来者的维护,我们可以利用注释提供修改思路,减轻后来者的负担。
(当然,你要直接找作者也可以,毕竟算个活注释。)
承认代码瑕疵
在上一点,我们知道了可以通过注释承认代码的瑕疵来记录当时的思想,而承认代码的瑕疵便是为 后来者提供了改进思路。
常量注释
想必各位写代码的时候或多或少的会用到常量。其实很多情况下常量的命名就已经提供了足够的信息了:
那么如果为常量写上注释,那一定是要提供额外的信息,这便是 解释常量值的计算公式 或者 常量值由来与调整范围。
3. 站在阅读者角度
其实写注释就是为了让阅读者方便理解代码,所以写注释一定要站在阅读者的角度。
主要可以分成三个情况:
容易产生疑惑点的解释
实现细节的公布
高级别的抽象解释
前两个情况,其实就是 记录思想 和 提供维护和修改指导思路 两个点涉及的内容。这里主要讲一下第三个情况。
高级别的抽象解释
阅读者通过阅读代码能明白代码在 代码层面的功能,例如循环、查找指定字符等。但是不一定能很快了解这些代码 背后的意图,也就是 高级别的抽象。
如下代码所示,代码层面的含义是 打乱 citys
数组,然后再循环这个数组,其中的元素不等于 lastCityId
则进入逻辑。
但更高级别的抽象其实就是 从已知 citys
中随机选择一个与上次选择不一样的 cityId
。
所以利用注释只解释代码层面,往往是不够的。当阅读者了解代码层面的功能时,不一定能确认这段代码它的原作者意图到底是什么。
如果多了意图的解释,阅读者其实也能通过阅读来判断这段代码是否事与愿违,这其实也为代码多了一层 检查。
4. 调整心态,尝试着写出来
很多时候,我个人也很抵触写注释,写代码累个半死还要再打字写注释,想下手的时候又不知从何开始。
所以写注释前,调整心态还是挺重要的。我们可以尝试以下三步走,来写自己的注释:
先写,不管多啰嗦
看看有没有可以提炼的
不断提炼
我举个栗子,我写了如下的函数和注释。只是为了记录所想。虽然长的要命,但还是写出来了。
然后可以考虑能不能提炼一些内容,因为命名已经是叫做 onDayPassMakeUp
, 命名已经告诉我们一些信息,所以可以删去第一行注释。同时解释内在补偿逻辑时,也可以省一些字句。
这样算是一次提炼了。
不难发现,本篇炸鸡其实主要侧重让编写者能够开始写注释同时确定该怎么写,但是在这一小节我们看到,写出的注释不一定是最恰当的,是存在 优化方向的。
所以下一篇炸鸡就稍微说一说关于 注释的优化方向和优化方法,希望对你有所帮助。
总结
确定了什么时候不该写注释
代码坏味道命名
代码本身能被快速判断功能
注释不能提供更多信息
提供了一些写注释的思路与方法:
记录思想,例如记录函数算法逻辑或者承认代码的瑕疵;还有
todo
、fixme
等标签。提供维护和修改指导思路。承认代码瑕疵与常量注释。
站在阅读者的角度写注释。主要讲了可以利用注释提供高级别的抽象解释,也就是代码背后的意图。
同时写注释,是要不怕麻烦,反复提炼才行。
版权声明: 本文为 InfoQ 作者【多选参数】的原创文章。
原文链接:【http://xie.infoq.cn/article/238a29ab04af3788306f1dd4a】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论 (1 条评论)