如何写好代码注释?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何写好代码注释?相关的知识,希望对你有一定的参考价值。

参考技术A

对于代码注释来说,在不同的教程或者原则中有不同的规定或者解释。有的原则是需要使用JavaDoc来描写每个方法,而有的原则是要求每一个属性标注命名。我愿意相信每一份看起来不那么妥当的注释都是出于一些善意的目的,这就是注释的本质:

对未能自行解释的代码做出解释。

在进行代码工作的时候我们多多少少会有一些陈旧的、与业务无关的逻辑在代码中运行。有时候并不是一个变量名或者一个方法名就能阐述清楚产品同学所期望的业务内容。我们希望将代码外的逻辑也加入到其中,但是一篇长篇大论的注释似乎也不那么妥当,所以对于注释我一般会加入一个约束的条件:

尽可能精简地描述当前方法、属性未能解释的逻辑。

那么这个约束中的关键词是:精简、当前、未能解释。这是我现在的理解,如果有更好的见解也希望可以联系我进行沟通。当然这些关键词在后文中也会进行解释。

对于代码的退化这个概念在很多的领域之中都有阐述。而一种比较主流的观点是:应用程序的生产寿命可能为3-5年。当然这个大限将至无法使用的定义是有很大空间的。但是这个说法的主要思想是:代码随着业务的迭代开发,会逐渐地降低可维护性,直到它的生命终结。代码是这样,对应的代码注释也是这样的。

对于代码注释来说,不知道大家是否经历过类似的内容:

他们可能都是痛苦的回忆,但是这就是刚刚所描述的,注释的退化。

对于代码来说,我们有许多的方法论、设计模式来尽可能地将代码的职责划分清晰从而延长。而对于注释来说,我认为最大的方法是“ 不写注释 ”(关于这个在后面的章节中会再次讨论)。

只要不写注释,注释就不会有问题。之所以会有这个问题的原因是,通常人们在调整业务逻辑后无法完美地维护注释。而更多情况是当代码逻辑发生变动了之后,注释直接编成了业务谜题中的一部分,开发人员不仅要在破败不堪的代码中梳理逻辑,还同时要小心错误注释发出的诱惑。

同时,当代码发生退化逐渐变得不可控的时候,比起重新抽象代码结果,看起来以一段注释来描述新的逻辑比较简单。但是带来的问题就是:“在尝试用注释弥补代码逻辑的问题”。显然注释无法帮你抽象代码,只是看起来将问题爆发的时间延后了(甚至引入了更严重的问题)。

那么“不写注释”的思想换一个角度来描述的话就是:让代码注释自己。这是一种习惯,举个最简单的例子:

可以改为:

哪怕是调整为:

可以看出来,第二种方法是指用对象内的方法,如果order只是一个自动生成的实体对象或者是一种值对象的话,那么也可以使用第三种方法。

这样调整的好处就是,用代码自身去描述逻辑,从而尽量“不写注释”。

对于不写注释的这个论点,除了代码自动解释以外,还有很多情况下的注释都是不那么合适的。

那么我对简单方法的定义是,如果方法实际逻辑(刨除括号部分)5-7行(我自己的标准)则可以认为是一个简单方法。读这样的方法的注释反而可能比直接看代码还来得复杂。

对于一些无法直接用语言进行直接描述的逻辑,我觉得要不就直接不要写注释了,让他们直接进行代码的阅读比较好。否则有歧义性的注释反而会误导人员进行理解。当然,对于我自己而言,内部项目中对于不便与用文字精确描述的逻辑,我会贴上wiki的连接进行图文描述。这样对于不希望阅读的开发人员注释不会产生干扰,而同时图文配合又便于理解。

JavaDoc标准要求对每个参数进行定义,但是这样带来的问题就是一些足够简明的参数的注释本身就是冗余的,例如:

尽管看起来很完美,但是它本身没有任何意义。所以对于代码中具有自解释性的变量名称(它们本应该具有自解释性),JavaDoc的注释其实是非必要的。

行为注释在在IDE里面行为的注释会导致代码的可读性大大降低,有的可能会在很长一段代码之后,有的则可能在很短的代码之后,他们的格式是不容易统一的,所以在现在广为流传的阿里巴巴开发手册中就明确的加上了在上一行中注释。

事实上,我还在用用户署名,因为之前创建了文件模版之后就一直沿用了。不过原则上来说,java文件署名的这个习惯是源于早期的代码版本控制并不是很发达的时代。而现代版本控制中,文件的来世今生都由版本控制来进行了,所以事到如今的用户署名已经没有意义了。

注释掉的代码就应该直接删除,否则会对后续的人员产生干扰。人们可能会下意识地与注释掉的代码产生逻辑交互,并且认为这部分由其保留的目的而并不动。和上条一样,在版本控制比较发达的今天,已经被注释的代码如果有其特殊的功能作用的话,应该是由一个单独的分支进行保护,而非一段会干扰到正常业务开发的注释代码。

如果注释所表达的功能与当前的方法无关的话,说明这部分的注释并不是完全为当前的方法服务的。那么它就不应该出现在这里,也许在一个另外的readme或者是wiki文档中才是它更好的位置。

如果将非当前功能的注释添加到方法上的话,那这里就会造成:如果要理解注释,就要去知道注释的上下文,那么这部分的注释本身就需要额外的说明,就与注释本身的功能背道而驰了。

尽管我们希望不使用注释,直接让代码就能完成逻辑解释的功能,但有时候代码确实是无法完全胜任。一般来说,以下的情况下是适用于进行注释补充的。

有时候,对于额外的程序外的背景描述,是可以补充的。这样可以在你尽管理解了代码逻辑,但是不知道他为什么这么实现的时候增加了额外的判断条件。也可以帮你确认是由于什么考虑才成为了当前的代码逻辑,比如:

这样的话尽管你可能不认同之前人员实现的方法,但是至少可以知道他的目的,从而判断是否可以进行业务调整。

代码是临时的在代码中进行的笔记。尽管是注释,但却和单纯的代码注释的意义不一样,可以进行标记。但一定要记得定时的处理TODO,否则大家的敏感度会降低。

警告如果业务或者功能方法在特定的情况下不应该执行。这些情况往往是组合了一些业务情况的信息,或者是实际生产情况下产生bug的记录。这样的注释将可以确实地提高解决问题的效率。但是要注意的是这部分的内容可能会遭受到代码腐化的影响。题外话:idea里面可以设置不同颜色的"@xxx"的标签,例如我新建了"@ATTENTION"从而将后续的内容调整成了紫色以提供相应的警示作用。

事实上,对于上面的观点很多观点,也是大多数全球程序员的观点。而中国自有我大国之情:便是语言问题。上文所说的代码自解释性的前提是对代码的表达意思了解得准确。而会想一下你对一些领域模型进行起名的时候,有多少是通过谷歌翻译、或者百度结果而查出来的?对于这种得到的名词来说,很难定义它是准确地描述了开发人员意图的变量名称。所以如果是这种前提的话,我认为对于指定对象中的字段、或者指定使用的参数、局部变量等名称,是可以酌情在属性、方法名上对指定的名字进行约束解释,以便由于方法名称和其他的概念混淆。简单点来说:

对于没有信心使用英文精准描述的名称,还是用注释进行约束较好。

本文主要内容来自《Clean Code》中注释一章。阅读感悟主要是文章中的内容有一些是针对超长工作经验的老油条说的,他们可能由于过往的习惯导致注释问题,而这一点在中国互联网存在的问题不明显;中国的母语区别导致代码的自解释性降低,学好英语还是非常重要的呀。



代码精进之路——如何写好代码

如何才能写好代码呢?我们可以从代码规范、起好名字、写好注释以及合理划分代码块等反面优化自己的代码。

代码规范

编码规范指的是针对特定编程语言约定的一系列规则,通常包括文件组织、缩进、注释、 声明、语句、空格、命名约定、编程实践、编程原则和最佳实践等。

规范的代码,可以降低代码出错的几率。比如之前提到的因为没有正确的缩进和括号导致的 bug。如果是一个追求或者遵从代码规范的程序员就很难犯这样的错误。

复杂是代码质量的敌人。 越复杂的代码,越容易出现问题,并且由于复杂性,我们很难发现这些隐藏的问题。在编码的时候,我们应该尽量使代码风格直观、逻辑简单、表述直接。

规范的代码,降低软件维护成本。大家写的代码都遵循规范,代码审阅人员看的舒心,后期维护人员也能看懂。就算是自己维护自己的代码,我相信在三个月后再看自己写的代码也一定会为当时的自己点赞,明确的变量,准确的缩进,简单的逻辑,恰当的注释...

一件东西,无论其实用性多强,终究比不上让人心情愉悦更为实用。

优秀的代码不 光是给自己看的,也是给别人看的,而且首先是给别人看的。

起好名字

为什么需要一个好的名字?首先我们先看一个列子:

public byte[] isEmpty();

这个命名是不是非常的蛋疼?根本看不懂这个名字是用来干嘛的,所以使用一个好的命名规范是非常重要的。

一段优秀的代码应该是自解释的,通过简单明了的变量、方法、类的命名可以让代码变得易于理解,提高代码的清晰度、可读性以及美观程度。

写好注释

如果一段代码没有办法做到自解释该怎么办?这个时候就该注释了。注释其实是一种无奈的妥协。

首先,因为注释不需要运行,所以没有常规的办法来测试它。 注释对不对?有没有随着代码变更?这些问题都是写注释需要注意的地方。注释难以维护,这是使用注释带来的最大的麻烦。但是,对于大部分程序员来说,问题还是注释太少,而不是太多。

我们要对关键代码和方法提供明确的注释,注释要准确、必要、清晰。

  1. 准确,错误的注释比没有注释更糟糕。
  2. 必要,多余的注释浪费阅读者的时间。
  3. 清晰,混乱的注释会把代码搞得更乱。

代码片段

有没有看过一个方法 2000 多行?是不是看到这样的代码就感到非常的头痛?或者是一个类写的乱七八糟?构造方法在中间,get/set 方法在成员变量上面等等。

首先,类的属性和方法,一般是一个代码文件的主要组成部分。类的结构,推荐的编码顺序依次 为:

  1. 类的属性;
  2. 构造方法;
  3. 工厂方法;
  4. 其他方法。

按照这样的规范,一个类的方法一目了然,读这样的代码不会像无头苍蝇一样的猜这个是什么方法,那个是什么方法。

其次按顺序使用限定词,在声明一个类、方法或者方法属性时,为了更准确地描述和理解声明的适用场景,我们通常要使用修饰性的关键词。
private final static long serialVersionUID 就没有 private static final long serialVersionUID 来的规范,static 关键字应该在 final 关键字之前。

代码块应该通过空格、缩进、空行进行分割。使用空行来分开同级别的不同代码块。这样可以使得代码变得更加的清晰和明了。

以上是关于如何写好代码注释?的主要内容,如果未能解决你的问题,请参考以下文章

代码精进之路——如何写好代码

Python 如何写好注释与文档字符串o(* ̄▽ ̄*)ブ

Python 如何写好注释与文档字符串o(* ̄▽ ̄*)ブ

为了写好代码,你坚持了哪些好习惯?

为了写好代码,你坚持了哪些好习惯?

为了写好代码,你坚持了哪些好习惯?