随着项目日益的复杂,现代项目最核心的问题已经演变成解决复杂度的过程。解决复杂度的方式有很多,比如从架构上就开始思考,使用微服务架构,把大型的项目分而治之。另一种思考的角度就是把项目尽量做得可维护,而要项目变得维护性强,必要的项目文档和代码的注释是必不可少的。本文的主题是阐释到底该不该给代码加注释。
在开始介绍注释之前,我们先看下一些常见的文档。
外部文档
一个大型的项目一般都有完善的文档,文档里面包含了源码清单内外的各种信息,它通常比源码的层次跟高,但是比项目问题定义、需求和架构设计层次更低一点。从专业角度来说,它一般分为两种类型:单元开发文件夹(unit-development folder,简称UDF) 和详细的设计文档。
UDF
UDF 又叫 “软件开发文件夹(software-development folder,SDF)”,它是一种不是很正式的文档,其中包含了供开发者在编程期间的使用记录,亦或是项目中一些复杂模块的设计决策踪迹,运行项目的环境配置等,也是为了方便新加入项目的人尽快地了解项目,从而快速地融入开发。大部分的项目没有标准来指定 UDF 需要包含什么内容,例如某个模块的顶层设计的说明、相关需求的副本、当前的代码清单等等,它通常是提供给项目内部成员使用。
详细的设计文档
详细设计文档是比较低层次的设计文档,主要描述在类和子程序层次上的设计决策,曾考虑过其它方案,以及采用目前方案的理由。当然,有时候这些信息包含在更正式的设计文档中,而低层次的设计文档主要收集UDF 的开发者记录。
注释 VS 不注释
与外部文档相比,内部文档嵌入在程序源码中,它是更详细的文档。在代码层文档中,最重要的部分就是注释。
写注释很容易,写糟糕的注释也很容易,注释写得不好,只会帮倒忙。
有的程序员鼓励所有的代码都需要加注释,他会觉得没有注释的代码是没法阅读的;有些程序员觉得注释比代码更难读懂,源码比注释本身更容易阅读,代码变了,注释就过时了;也有的程序员认为如果你的代码写得足够好,代码本身已经不言自明了,再加注释就是多余,注释是给那些写得不好的代码用的;还有的程序员认为注释过多,使得代码更加难以阅读,代码已经读得够呛了,还得去读一大堆注释。但是也有的人认为,用得好的注释却妙不可言,有注释的代码更加容易维护。
那么这多观点,到底谁才是正确的?我们看几个例子。
几个神秘的子程序
Java神秘子程序:第1号
// write out the sum 1..n for all n from 1 to num
current = 1;
previous = 0;
sum = 1;
for (int i = 0; i < num; i++) {
System.out.println("Sum = " + sum);
sum = current + previous;
previous = current;
current = sum;
}
Java神秘子程序:第2号
// set product to "base"
product = base;
// loop from 2 "num"
for (int i = 2; i <= num; i++) {
// mutiply "base" by "product"
product = product * base;
}
System.out.println("Product = " + product);
Java神秘子程序:第3号
// compute the square root of Num useing the Newton-Raphson approximation
r = num / 2;
while (abs (r - (num / r)) > TOLERANCE) {
r = 0.5 * (r + (num / r));
}
System.out.println("r = " + r);
看完了三个例子,我们来点评下:
1号程序猜出来是什么了吗?它计算的是斐波那契(Fibonacci),数列的前 num 个值。其代码不差,但是注释错了,如果盲目相信注释,就会南辕北辙。
2号程序代码计算整数 base 的 num 次方,注释正确,但没有给代码带来信息,只是用啰嗦的方式又说了一遍代码。
3号程序用来计算 num 的平方根,代码一般,不过注释写得很准确。
上面的三个例子,哪个最容易理解了?其实,严格来讲,上面的例子代码和注释合在一起看没有写得特别好的,变量命名就很一般,但它们展示了注释的优缺点。1号程序的注释就是错误的,2号程序的注释只是重复代码而毫无价值,只有3号程序的注释是有价值的。拙劣的注释还不如没有好,前面两个例子就是这样。
小结
现在再来回答开始的问题,答案已经清晰很多了。笔者认为代码该不该写注释,需要根据团队、项目和具体的情况来考虑,严格来说,没人能自信地说自己写的代码可以让团队所有人都能看懂,而且包括后面加入团队的新成员。亦或者经过岁月的洗礼,有多少人记得那些奇淫技巧,那些拍脑袋想到的迫不得已的命名。我们不是为了写注释而写注释,而是为了能让别人读懂我们的代码意图、让项目变得更加可维护写注释。所以当我们写一些复杂的算法或者业务逻辑时,亦或是一些自己都不能理解的变量命名时,想一想,其它人能读懂理解吗?
写在最后的话
本文是笔者阅读了 《代码大全》 关于注释的章节写的读书笔记,文中的例子来自书中,观点是读者阅读书后加入自己的理解后提炼出来的,如有不足,望指出和给出更好的建议。这是关于注释的第一篇,后续还会更新注释的种类和技术等其它文章。