项目代码是“编写一次,阅读多次”。阅读者包括代码编写者、架构师、审查人员,以及后来的维护人员。能让阅读代码更轻松,有利于增强项目或产品的可维护性。
代码可读性是各种软件工程方法、面向对象实践、重构,以及新技术应用到项目中的一个重要前提,如果代码难以阅读,那么所有这些方法和理论都难以在项目中实施;如果代码难以维护,那么性能优化也无从谈起。
(资料图片)
在代码块中应该尽量减少注释的编写,尤其是描述设计思想和实现过程的注释,原因是代码会不停地随着业务需求变化而变化,注释往往在重构中被 IDE 忽略,也会被人为忽略。用Clean Code 中的话来说,就是注释容易“腐烂”。避免注释“腐烂”需要我们尽力维护代码和注释的同步,在代码中精简注释也是防止注释“腐烂”的最好办法。
下面列举一些代码内注释的使用原则。
场景 1:及时删除被注释的代码。
被注释的代码应该及时删除,否则这段代码将传给一代又一代的代码维护者,无人敢删除这段代码。如下工作流引擎,里面有一段 2007 年编写的代码让人感到迷惑:
//别删除这块代码 by WX,07.09//Task[] tasks = taskService.query();//...Task task = taskService.queryOne();
开发者不应该注释代码块,应该尽快删除。如果想恢复,那么可以通过 Git 工具来恢复。
场景 2:通过注释解释代码行为。
代码注释应该说明代码的动机,而不是再次用文字描述一遍代码过程。以下注释相当于没有:
/*字符内容符合 18 个数字或 15 个数字*/public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";
不如改成如下内容:
/*身份证号验证*/public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";
网上一篇《如何编写无法维护的代码》中就提到一个原则,只记录 How 而不是 Why,就会让代码无法维护。
例如,对账户状态值进行注释,代码如下:
/* 状态 0 正常 1 异常 2 未知 */private Integer status;
如果随后 status 添加了更多的含义,比如添加 3 表示冻结,则很可能忽略修改这里的注释。最好的办法是使用枚举,并且取消注释。
private Integer status = UserStatus.Nomral.getValue();
场景 3:不要在代码中记录更改历史的数据。
//原来版本使用 StringBuffer,改成 StringBuilder bt WX 20190302StringBuilder sb = ...
这段注释毫无存在的必要,可以通过 Git 这样的工具来查看代码更新记录和更新人,以及更新原因。没有必要在代码里标注代码相关人,如果用 IDEA,则可以很方便地查看代码的更新人。在 Editor 左侧代码行空白处单击鼠标右键,在弹出菜单中选择 Annotation,如下图所示。
场景 4:把代码块提取到一个方法中,通过方法名来解释代码作用。
//发送短信给用户StringBuilder sb = new StringBuilder("您的余额是");sb.append(user.getBalance()).append("元-");sb.append(platformName).append(""。)sms.send(sb.toString(),user.getMobile());
以上发送短信的代码可以提取到一个短方法中,代码调用此短方法即可:
sendUserBalanceBySms(user,platformName);
这个短方法的意义是使得代码容易维护:
1.如果需要修改发送短信的内容,则可以直接定位到 sendUserBalanceBySms,不需要从上百行代码中寻找。
2.在阅读 sendUserBalanceBySms 调用所在代码块的时候,sendUserBalanceBySms 无关紧要,可以习惯性地忽略,如果没有这个方法,则需要阅读数行这种代码,哪怕已经熟悉代码了。用这种短方法减轻了阅读负担。
场景 5:使用一个临时变量代替注释。
对于一段计算逻辑,或者一个方法调用,使用临时变量来说明其结果含义,比注释更容易维护。以下代码:
//返回一年总的费用return calcPay(user,type);可以用一个临时变量来表示,代码如下:BigDecimal payByYear = calcPay(user,type);return payByYear;
使用临时变量不会影响性能,两者的虚拟机代码都是一样的。
场景 6:取消 HTML 风格的注释。
如果注释中包含过多的 HTML 标签,虽然生成的 Javadoc 容易阅读,但并不利于直接在源码中阅读。以下代码包含过多的 HTML 标签:
/*** 输入对应以下输出* <table border=0 cellspacing=3 cellpadding=0>* <tr>* <th align=left>输入</th>* <th align=left>输出</th>* <tr>* <td><code>1</code></td>* <td><code>Success</code></td>* <tr>* <td><code>2</code></td>* <td><code>Failure</code></td>* </tr>* </table>*/
可以去掉 table 标签,改成如下内容:
/** 输入对应以下输出* <p>1,输出是 Success* <p>2,输出是 Failure*/
场景 7:取消没有必要的注释。
有些方法过于简单,没有必要添加注释,比如 JavaBean 的 getter 和 setter 方法。以下是没有必要的注释:
/*用户名称*/private String userName;
内容摘自《高性能Java系统权威指南》第六章
李家智 著
本书特点:
内容上,总结作者从事Java开发20年来在头部IT企业的高并发系统经历的真实案例,极具参考意义和可读性。
对于程序员和架构师而言,Java 系统的性能优化是一个超常规的挑战。这是因为 Java 语言和 Java 运行平台,以及 Java 生态的复杂性决定了 Java 系统的性能优化不再是简单的升级配置或者简单的 “空间换时间”的技术实现,这涉及 Java 的各种知识点。
本书从高性能、易维护、代码增强以及在微服务系统中编写Java代码的角度来描述如何实现高性能Java系统,结合真实案例,让读者能够快速上手实战。
风格上,本书的风格偏实战,读者可以下载书中的示例代码并运行测试。读者可以从任意一章开始阅读,掌握性能优化知识为公司的系统所用。
本书适合:
中高级程序员和架构师;
以及有志从事基础技术研发、开源工具研发的极客阅读;
也可以作为 Java 笔试和面试的参考书。