编写可读代码(三) 如何编写注释

记得在学习编程伊始,就被一直强调着注释的作用,甚至我还听说有的老师会强制要求学生注释(比方说每个变量必须注释)。诚然,合理恰当的注释有助于别人快速理解我们的代码,也有助于长时间后重拾自己的代码,但不合理的注释往往会浪费我们的时间,甚至为理解代码带来障碍。

一、注释的作用

1,交代代码外的信息

通过注释,我们可以了解一些代码外的信息,如作者,授权信息等,这有利于我们合法的使用源代码。

2,帮助编写代码

对于程序员编写者来说,首先是如何更快更好地写出可用高效的代码。写注释虽然会花费一点时间,但良好的注释可以帮助作者更好地理清思路、记录信息使其暂时忽略旁枝末节而专注于主要逻辑等。良好的利用好注释,可以让作者更快更好的完成代码,同时在一段时间之后,重读代码、修改代码依然可以很快的进入状态。

3,说明代码如何使用

程序员编写的代码往往都是要进行复用的,是自己亦或是他人。代码本身有时难以提供足够的信息来告知如何使用,这时注释就可以来弥补这方面的缺陷。

4,帮助理解代码

有些复杂的任务,代码是晦涩难懂的,但有时又不得不反复关注、优化这部分代码。这时候通过注释来提供额外的信息来解释代码在做什么或者为什么这样做就有必要了。

二、注释可能带来的问题

无用冗余的注释会带来大量的垃圾信息,影响阅读代码的效率,造成时间上的浪费。

含糊的注释、误导性的注释会是读者更加迷惑,反而对阅读代码造成障碍。

三、常见注释的种类

版权注释

版权注释主要包含项目信息,作者信息,日期信息,版权信息、授权协议等。此类注释一般有固定格式,不再赘述

信息性注释

信息性注释是最常见的一种注释。前面说的有的老师会强制要求学生写的注释,主要就是这部分注释。这种注释主要用来说明变量、函数的功能,函数参数的格式等。但这种注释并不是越多越好。相反,在保证可读性的前提下,注释越少越好。

比方说前一篇中的例子:results=Database.all_objects.filter("year <=2011")。如果是别人写好的我们无法修改的函数,那么我们只能通过注释的方式来解释避免理解错误。但若是我们自己编写的函数,就可以通过改名的方式来避免注释,如把filter改为selectWhere(模仿SQL)或者selectWithConditions这样的名字,就很好的解释了代码做的事情。

解释作者意图

有些时候,由于代码执行的任务比较复杂,只看代码做了什么,依然无法理解。这个时候就需要合适的注释来解释写代码时作者的意图,这样,当后续对这部分复杂的代码进行优化或者重构时,就可以充分领悟到当时编写时的情境,从而更快的理解代码。

警告性注释

警告性注释主要是强调函数的一些重要特点。比方说怎样错误使用会造成严重后果。又或者说明代码里有哪些陷阱,在怎样的情况下会出现特殊的反应。还可以添加对代码的一些见解,包括优化信息或者缺陷信息及存在的原因,避免后来者不明情况而浪费时间。

标记注释

标记注释应该只存在于开发的过程中,当正式发布时,源码中不应当有标记注释。标记注释是用来帮助程序员自己来更好的完成编程工作的,把一些枝节的问题记录,使得程序员可以专注于主线逻辑。待主线逻辑完成之后,再回来一一完成标记注释的部分。

标记注释通常有下面几种

TODO注释,标记还没有做,需要后续实现的部分

FIXME注释,标记不能正常运行的代码部分

HACK注释,标记对一个问题不得不采用的比较粗糙的解决方案

XXX注释,标记有重要问题的部分

对于标记性注释,一个团队在编写代码之前,一定要确定一个统一的规范标准。


以上几种类别,都是比较常见并且比较有利于读者理解代码的注释,下面的几类注释则往往会带来额外的负担或代价。

自言自语的注释

这类注释是作者整理自己思路时候留下来的。在编写代码时这类注释有助于作者本人编写代码,但若不能及时在完成代码后移除,则会带来额外的阅读负担。因为这时,这类注释往往是无用的,甚至有时和具体代码是不相符合的。

冗余、内容重复的注释

冗余的注释是最为常见的。还拿前面说的老师要求学生为每个变量加注释为例,有的人可能就会写出这样的注释:

string version;//The version

这个注释实际上就是重新抄写了一遍变量名,没有带来任何新的信息,而且信息的冗余还加大了读者的阅读负担。

对于这类注释,一定要坚决的避免。

误导性的注释

误导性的注释一般是有两种情况,一种是作者写注释的时候使用了有歧义的词句,使读者发生理解错误;另一种则是在代码长期维护演化的过程中,注释没有及时更新,使得注释与代码不匹配,使得注释会起到误导的作用。

日志性注释

日志性注释也是比较常见的一种注释方式。当维护代码的结束的时候,在代码的注释上加上日期以及维护了哪些内容。这些信息是有意义的,但这些信息并不应当放到注释里。我们应该利用好版本控制系统来维护代码。

定位注释

代码编写者在写代码的时候,为了让自己快速找到某部分代码的位置,会添加类似这样的注释。但这样的注释在阅读代码时是没有任何意义的,而且对于作者本身,这样的注释多了也会造成新的障碍。比较合理的方式是采用可检索的命名方式,合理的重构函数,使得定位某一个代码块变得很容易。

关闭括号注释

while(){
<span style="white-space:pre">	</span>for(;;){
<span style="white-space:pre">	</span>}//end for
<span style="white-space:pre">	</span>...
}//end while
这样的注释其实已经说明了代码是比较糟糕的了。因为代码要尽量的整齐和短小,对于这种情况,我们要利用代码对齐的技巧以及重构函数等方式,使得我们不必使用这种注释就可以一眼分清括号的作用范围。
修改者信息注释 

类似于//modified by xxx这样的注释。这样的信息更应该由代码管理系统来保留。

注释掉的代码

注释掉的代码应该是最让读者憎恨的一种注释了。因为一个新的读者很难确定被注释掉的代码的价值,它是有重要的作用的代码还是仅仅是被遗忘的垃圾代码,为什么它要存在那里,删掉它们会不会有什么后果。因此,这类注释是一定要避免的。至于代码丢失?不必担心这个问题,交给版本控制系统就好了。

非本地注释

提供了一些非本地的信息,对阅读此处的代码没有帮助,因此是多余的。

太多信息的注释

例如用了很长一大段来描述一个函数,把原理等各种细节都交代的极为清楚,注释可能达到十几行甚至几十行。这样的注释对于读者来说往往会很头痛,因为读者并不需要那么多的信息,很多信息对于理解代码来说是没有用的。

含糊的注释

在合适的地方写了注释,但不恰当的词句,使得读者并不能准确领悟所要表达的信息。

四、如何写好注释

1,不要为了注释而注释

我们不应该把注释当做任务,也不应该把注释当做负担,只在需要注释的地方添加注释。

2,言简意赅的注释

注释不能太过冗长,要用最少的词句来表达出要表达的信息。

3,精确描述的注释

注释在描述时要精确,不能含糊不清,要让读者马上领会作者的意图。用词选词要恰当,避免不专业、有二义性的词语。

4,个别情况使用例子来说明

对于用简短的语言难以准确描述的情况,可以选择一个有代表性的例子来进行描述,使读者更快理解。

5,要在维护代码的同时维护注释

写注释要和代码足够近,这样才能在维护代码的时候注意到其对应的注释。修改代码后一定要检查其相应的注释是否需要更新。

6,不要试图用注释来弥补糟糕的代码

很多写注释的时候都是由于代码未能表达出足够的信息。但在写注释之前,我们应该问自己几个问题,我的代码是否已经最大化能表达的信息了,改进变量名字、改变语句结构、重构函数等方法是否能表达更多的信息,确定以上之后再去书写注释。


在我看来写可读代码的最高境界就是写自解释的代码,在保证可读性的前提下,通过使用书写代码的技巧,使其读起来有注释的效果。毕竟,最好的注释就是发现了可以不写注释的方式。

注:本文依旧是阅读《编写可读代码的艺术》和《clean code》之后,结合自己的体会,选择性的总结。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值