好的代码优于大量注释
如果出现了代码坏味道,首先考虑的应该是重构。带有少量注释的整洁而有表达力的代码,要比带有大量注释的零碎而复杂的代码像样的多。
好注释
法律信息
有时,公司代码规范要求编写与法律有关的注释。对于此类注释,只要有可能,就指向一份标准许可或者其他外部文档,而不是把所有条款放在注释中。此类注释,应充分利用IDE的模板生成功能,将公司文档模板加入到IDE自动生成注释功能中。
提供信息
如果代码无法准确表示需要传达的信息,就需要注释来表达代码需要承担的职责。下面是一个例子:
// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Patter.compile("\\d*:\\d*\\d* \\w*, \\w* \\d*, \\d*);"
本例中,正则表达式匹配一个经由SimpleDateFormat.format函数利用特定格式字符串格式化的时间和日期。值得注意的是,如果这段代码出现在某个转换时间格式的类中,注释就变得毫无意义。
解释意图
有时,程序员会因为一些具体的原因,使用某个决定。此处情况,注释是一个好的向后来者(交接人或者未来的自己)传达信息的途径。
阐释含义
有时,有些代码晦涩难懂,或者作为调用者你无法修改接口名称时,可以增加注释帮助增加代码的可读性。下面是一个例子
assertTrue(aa.compareTo(ab) = -1); //aa < ab
本例中,compareTo是已经定义好的接口,开发者无法修改命名。-1作为返回值无法准确表达aa ab直接的关系。此时增加注释是最好的手段。
警示
当你在调试或运行代码时,通常会踩到一些坑。此时增加注释,可警示后来者防止他们犯同样的错误。部分语言中,可能会有装饰器承担此类工作。
@Ignore(Takes too long to run)
TODO
TODO通常是程序员认为应该做,但由于某些原因还没有做的工作。它可能时要删除某个非必要的特性,或者要求他人注意某个问题。当前好的IDE都提供了特别的手段来定位TODO,这种方式可以让开发者快速定位到当前需要做的工作。
当然,有些公司的代码规范中,要求发布版本不允许出现todo注释,因为这可能带来安全风险或者商务风险。这类情况应视具体情况而定。
//todo a sample needed
放大
注释可以放大某种看起来不合理代码的重要性。
//the trim is important! It remove the starting space that could could cause error match
String str = matched.group(3).trim();
公共API
标准JAVA库中的javadoc或者Python库中api注释,都是开发者开发程序中的好帮手。如果你在编写公共API,就该为它编写良好的doc。标准库中的注释,可以作为学习的模板,好好学习临摹下。
坏注释
多余型
如果一个函数,读者能够很容易的就读出来代码要表达的意思。注释就是多余的。例如:
# when a>b return true,and when a<=b return false
if(a>b):
return True
else:
return False
本例中代码清晰无歧义,读注释纯粹是浪费时间。
误导型
尽快初衷可嘉,但是程序员有时候会写出不够精确的注释。这种误导型,将误导后来者,甚至不如不加注释。
日志式
有人喜欢在每次编辑代码时,在模块开始时增加一套注释。此功能应该由代码管理工具(svn/git)来承担,而非注释。后来者在读代码时,只需要知道这段代码为什么这么做,而非它的来世今生。
/*
* 2021-01-03 Fixs bugs in add()
* 2021-02-07 Fixs errors when add 5 and 4
* 20210-03-08 Add function in add
*/
废话式
此类注释通常为了满足某些编程规范,在没必要加注释的地方强行加注释。
String date; //date
String version; //version
Int id; //id
标记式
有些程序员喜欢在代码中标记特别位置。此类注释,通常随着时间推移逐渐膨胀,真正有用的信息会沉默在背景噪声中。
// debug @@@@@@@@@@@@@
// fix large number //////////////////////////
括号后面的注释
此类注释,在很长的括号后增加标记。这种功能,同样应让IDE来承担。或者缩短括号体中的代码行数。
while(xxxxx){
xxxx
......
xxxx
} //while
签名式
// Add by rock 2020-12-25
此类注释毫无意义,且会搞脏代码。随着时间推移,这注释将会越来越无用,因为这行代码与原作者会越来越没关系。同时,此类注释会增加代码被社会工程学攻击的风险。如果想帮助后来者找到原作者,应充分使用代码管理工具(svn/git)的能力。如果使用vscode作为IDE,推荐使用Gitlens来查找代码作者。
注释掉的代码
直接注释掉代码而不是删除,是一个愚蠢的做法。其他人不敢删除注释掉的代码,因为他们会想代码放在那儿肯定有原因。他们也不敢放开注释,因为他们不知道为什么注释掉。如果怕代码丢失,同样可以用代码管理工具来进行管理。
非本地信息
如果你一定要写注释,确保它描述了距离它最近的代码。如果在非本地增加了注释,我们无法确保真正的代码逻辑修改之后,这里的注释也会修改。
def setVaule(val):
# set value of xxx, default to 1024
self.val = val
本例中,default 1024非本地逻辑。如果未来有修改,不修改注释也能过UT,很容易漏掉修改。