如何写好代码注释?

更新日期: 2022-05-03阅读: 1.1k标签: 注释

注释的本质

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

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

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

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

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

代码的退化

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

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

  • 几个位置的方法是同样的注释,看起来是来自于一次方法的批量注释。

  • 代码上有一段业务的注释,但是看起来和代码逻辑并不一致

  • 代码上描述了一段业务,但是产品同学说业务已经下线了

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

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

不写注释

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

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

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

//判断订单是否满足支付条件if(order.getRealPirce()>0 && PAID != order.getPayState())

可以改为:

if(order.isPayable())

哪怕是调整为:

boolean isPayable = order.getRealPirce()>0 && PAID != order.getPayState();if(isPayable)

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

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

人不能,至少不该

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

简单的方法添加注释

对于简单的函数来说,代码本身就已经有足够的解释性了,如果为其增加了注释,反而会降低代码的关注度,让开发人员将注意力放到注释上,而如果在简单逻辑变更后,就更糟糕了,你能想象 set() 方法上进行方法注释告诉你这是一个设置数值的方法吗。

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

无法精确描述的注释

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

无情的 JavaDoc 机器人

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

public class User {    /**     * @param id 准备构建用户的用户id     * @param name 准备构建用户的用户名称     * @param age 准备构建用户的用户年龄     */       public User(long id, String name, int age) {        this.id = id;        this.name = name;        this.age = age;    }
private long id;
private String name; private int age; }

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

行为注释

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

用户名称

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

注释代码

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

非当前功能注释

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

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

充分必要条件

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

声明

对于法律、许可的声明,是可以放到一些文件头上的,他们有额外的作用。好消息是现在的 IDE 可以自动折叠这部分的信息,就如果可以自动折叠 import 一样,将他们对于逻辑理解的干扰降到最低。

描述背景

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

//由于数据库实例读写分离,所以这个地方在延迟后进行异步调用。

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

TODO

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

警示

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

中国地区特色注释

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

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

最后

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

原文 https://xie.infoq.cn/article/7ff593b97d4d9b47e711aec58

链接: https://fly63.com/article/detial/11438

php代码中注释的含义

最近在梳理和优化手上的项目代码,这个项目已经走过好几任了,每一任的开发人员多多少少都有一些差异和各自的习惯,所以代码逻辑和写法上都有点【乱】。在代码中,注释是一个非常重要的信息

HTML 注释 和 实体字符

在HTML中还有一种特殊的标签——注释标签。如果需要在HTML文档中添加一些便于阅读和理解但又不需要显示在页面中的注释文字,就需要使用注释标签

条件注释的两种形式_下层隐藏与下层显示

条件注释 (conditional comment) 是于HTML源码中被 Microsoft Internet Explorer 有条件解释的语句。条件注释可被用来向 Internet Explorer 提供及隐藏代码。条件注释最初于微软的 Internet Explorer 5浏览器中出现

JS正则与注释的冲突

最近在写一款前端组件的时候,无意发现正则与注释之间的一点冲突,现分享下。猜测应该是正则没有使用引号,导致JS解析时将正则里边的*/做为了注释的结尾。

html代码中如何写注释?

HTML中的注释通常用于解释标记。在编辑源代码时,它将帮助您和其他人快速轻松地选择或查找文档中的特定部分;浏览器不会显示注释。那么如何在html代码中如何写注释?下面本篇文章就来给大家介绍一下,希望对大家有所帮助

javascript注释有几种?

代码注释对长久维护的项目来说很重要,随着前端代码逻辑日趋复杂,合理的文档注释能提高维护开发效率。尤其在多人团队中,良好的注释能降低沟通成本。

html注释代码怎么写?

HTML注释:不被程序执行的代码。用于程序员标记代码,在后期的修改,以及他人的学习时有所帮助。对关键代码的注释是一个良好的习惯。在开发网站或者功能模块开发时,代码的注释尤其重要。

如何在javascript中添加注释?

代码注释对长久维护的项目来说很重要,随着前端代码逻辑日趋复杂,合理的文档注释能提高维护开发效率。尤其在多人团队中,良好的注释能降低沟通成本。

为啥CSS不会支持双斜杠(//)注释?

相信大家对 CSS 的语法又有了一个新的认识,下面总结一下有部分属性值会出现双斜杠语法,比如border-image、-webkit-mask-box-image,不支持双斜杠注释最主要的原因是无法兼容现版本

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!