前言
不知道大家有没有经历过维护一个已经离职的人的代码的痛苦,一个方法写老长,还有很多的if else ,根本无法阅读,更不知道代码背后的含义,最重要的是没有人可以问,此时只能心里默默地问候这个留坑的兄弟。。
其实造成这些原因的很大一部分原因是由于代码规范的问题,如果写的规范,注释好,其实很多问题也就解决了。所以本文我就从代码的编写规范,格式的优化,设计原则和一些常见的代码优化的技巧等方面总结了了45个小技巧分享给大家,如果不足,欢迎指正。
1、规范命名
命名是写代码中最频繁的操作,比如类、属性、方法、参数等。好的名字应当能遵循以下几点:
见名知意
比如需要定义一个变量需要来计数
int i = 0;
名称 i 没有任何的实际意义,没有体现出数量的意思,所以我们应当指明数量的名称
int count = 0;
能够读的出来
如下代码:
private String sfzh; private String dhhm;
这些变量的名称,根本读不出来,更别说实际意义了。
所以我们可以使用正确的可以读出来的英文来命名
private String idCardNo; private String phone;
2、规范代码格式
好的代码格式能够让人感觉看起来代码更加舒适。
好的代码格式应当遵守以下几点:
-
合适的空格
-
代码对齐,比如大括号要对齐
-
及时换行,一行不要写太多代码
好在现在开发工具支持一键格式化,可以帮助美化代码格式。
3、写好代码注释
在《代码简洁之道》这本书中作者提到了一个观点,注释的恰当用法是用来弥补我们在用代码表达意图时的失败。换句话说,当无法通过读代码来了解代码所表达的意思的时候,就需要用注释来说明。
作者之所以这么说,是因为作者觉得随着时间的推移,代码可能会变动,如果不及时更新注释,那么注释就容易产生误导,偏离代码的实际意义。而不及时更新注释的原因是,程序员不喜欢写注释。(作者很懂啊)
但是这不意味着可以不写注释,当通过代码如果无法表达意思的时候,就需要注释,比如如下代码
for (Integer id : ids) { if (id == 0) { continue; } //做其他事 }
为什么 id == 0 需要跳过,代码是无法看出来了,就需要注释了。
好的注释应当满足一下几点:
-
解释代码的意图,说明为什么这么写,用来做什么
-
对参数和返回值注释,入参代表什么,出参代表什么
-
有警示作用,比如说入参不能为空,或者代码是不是有坑
-
当代码还未完成时可以使用 todo 注释来注释
4、try catch 内部代码抽成一个方法
try catch代码有时会干扰我们阅读核心的代码逻辑,这时就可以把try catch内部主逻辑抽离成一个单独的方法
如下图是Eureka服务端源码中服务下线的实现中的一段代码
整个方法非常长,try中代码是真正的服务下线的代码实现,finally可以保证读锁最终一定可以释放。
所以这段代码其实就可以对核心的逻辑进行抽取。
protected boolean internalCancel(String appName, String id, boolean isReplication) { try { read.lock(); doInternalCancel(appName, id, isReplication); } finally { read.unlock(); } // 剩余代码 } private boolean doInternalCancel(String appName, String id, boolean isReplication) { //真正处理下线的逻辑 }
5、方法别太长
方法别太长就是字面的意思。一旦代码太长,给人的第一眼感觉就很复杂,让人不想读下去;同时方法太长的代码可能读起来容易让人摸不着头脑,不知道哪一些代码是同一个业务的功能。
我曾经就遇到过一个方法写了2000+行,各种if else判断,我光理清代码思路就用了很久,最终理清之后,就用策略模式给重构了。
所以一旦方法过长,可以尝试将相同业务功能的代码单独抽取一个方法,最后在主方法中调用即可。
6、抽取重复代码
当一份代码重复出现在程序的多处地方,就会造成程序又臭又长,当这份代码的结构要修改时,每一处出现这份代码的地方都得修改,导致程序的扩展性很差。
所以一般遇到这种情况,可以抽取成一个工具类,还可以抽成一个公共的父类。
7、多用return
在有时我们平时写代码的情况可能会出现if条件套if的情况,当if条件过多的时候可能会出现如下情况:
if (条件1) { if (条件2) { if (条件3) { if (条件4) { if (条件5) { System.out.println("三友的java日记"); } } } } }
面对这种情况,可以换种思路,使用return来优化
if (!条件1) { return; } if (!条件2) { return; } if (!条件3) { return; } if (!条件4) { return; } if (!条件5) { return; } System.out.println("三友的java日记");
这样优化就感觉看起来更加直观
8、if条件表达式不要太复杂
比如在如下代码:
if (((StringUtils.isBlank(person.getName()) || "三友的java日记".equals(person.getName())) && (person.getAge() != null && person.getAge() > 10)) && "汉".equals(person.getNational())) { // 处理逻辑 }
这段逻辑,这种条件表达式乍一看不知道是什么,仔细一看还是不知道是什么,这时就可以这么优化
boolean sanyouOrBlank = StringUtils.isBlank(person.getName()) || "三友的java日记".equals(person.getName()); boolean ageGreaterThanTen = person.getAge() != null && person.getAge() > 10; boolean isHanNational = "汉".equals(person.getNational()); if (sanyouOrBlank && ageGreaterThanTen && isHanNational) { // 处理逻辑 }
此时就很容易看懂if的逻辑了
9、优雅地参数校验
当前端传递给后端参数的时候,通常需要对参数进场检验,一般可能会这么写
@PostMapping public void addPerson(@RequestBody AddPersonRequest addPersonRequest) { if (StringUtils.isBlank(addPersonRequest.getName())) { throw new BizException("人员姓名不能为空"); } if (StringUtils.isBlank(addPer