优化代码的几个小技巧
前言
最近看了《重构-改善既有代码的设计》这本书,总结了优化代码的几个小技巧,给大家分享一下。
提炼函数(适当抽取小函数)
定义
提炼函数就是将一段代码放进一个独立函数中,并让函数名称解释该函数用途。
一个过于冗长的函数或者一段需要注释才能让人理解用途的代码,可以考虑把它切分成一个功能明确的函数单元,并定义清晰简短的函数名,这样会让代码变得更加优雅。
优化例子
提炼函数之前:
private String name;private Vector<Order> orders = new Vector<Order>();public void printOwing() {//print bannerSystem.out.println("****************");System.out.println("*****customer Owes *****");System.out.println("****************");//calculate totalAmountEnumeration env = orders.elements();double totalAmount = 0.0;while (env.hasMoreElements()) {Order order = (Order) env.nextElement();totalAmount += order.getAmout();}//print detailsSystem.out.println("name:" + name);System.out.println("amount:" + totalAmount);}
提炼函数之后:
以上那段代码,可以抽成print banner,calculate totalAmount,print details三个功能的单一函数,如下:
private String name;private Vector<Order> orders = new Vector<Order>();public void printOwing() {//print bannerprintBanner();//calculate totalAmountdouble totalAmount = getTotalAmount();//print detailsprintDetail(totalAmount);}void printBanner(){System.out.println("****************");System.out.println("*****customer Owes *****");System.out.println("****************");}double getTotalAmount(){Enumeration env = orders.elements();double totalAmount = 0.0;while (env.hasMoreElements()) {Order order = (Order) env.nextElement();totalAmount += order.getAmout();}return totalAmount;}void printDetail(double totalAmount){System.out.println("name:" + name);System.out.println("amount:" + totalAmount);}
内联函数(适当去除多余函数)
定义
内联函数就是在函数调用点插入函数本体,然后移除该函数。
上一小节介绍了提炼函数代码优化方式,以简短清晰的小函数为荣。但是呢,小函数是不是越多越好呢?肯定不是啦,有时候你会遇到某些函数,其内部代码和函数名称同样清晰,这时候呢你可以考虑内联函数优化一下了。
优化例子
内联函数之前
int getRating(){return moreThanFiveDeliveries() ? 2 : 1;}boolean moreThanFiveDeliveries(){return numberOfLateDeliveries >5;}
内联函数之后
int getRating(){return numberOfLateDeliveries >5 ? 2 : 1;}
内联临时变量(去除多余临时变量)
定义
内联临时变量将所有对该变量的引用动作,替换为对它赋值的那个表达式自身。
优化例子
内联临时变量之前
double basePice = anOrder.basePrice();return basePice >888;
内联临时变量之后
return anOrder.basePrice() >888;引入解释性变量
定义
引入解释性变量 就是将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途。
有些表达式可能非常复杂难于阅读,在这种情况下,临时变量可以帮助你将表达式分解为可读的形式。
在比较复杂的条件逻辑中,你可以用引入解释性变量将每个条件子句提炼出来,以一个良好命名的临时变量来解释对应条件子句的意义。
优化例子
引入解释性变量之前
if ((platform.toUpperCase().indexOf("mac") > -1) &&(brower.toUpperCase().indexOf("ie") > -1) &&wasInitializes() && resize > 0) {......}
引入解释性变量之后
final boolean isMacOS = platform.toUpperCase().indexOf("mac") > -1;final boolean isIEBrowser = brower.toUpperCase().indexOf("ie") > -1;final boolean wasResized = resize > 0;if (isMacOS && isIEBrowser && wasInitializes() && wasResized) {......}
以字面常量取代魔法数
定义
创造一个常量,根据其意义为它命名,并将上述的字面数值替换为这个常量。
所谓魔法数是指拥有特殊意义,却又不能明确表现出这种意义的数字。如果你需要在不同的地点引用同一个逻辑数,每当该数字要修改时,会特别头疼,因为很可能会改漏。而字面常量取代魔法数可以解决这个头疼问题。
优化例子
以字面常量取代魔法数之前
double getDiscountPrice(double price){return price * 0.88;}
以字面常量取代魔法数之后
static final double DISCOUNT_CONSTANT=0.88;double getDiscountPrice(double price){return price * DISCOUNT_CONSTANT;}
用多态替代switch语句
定义
用多态替换switch语句 就是利用Java面向对象的多态特点,使用state模式来替换switch语句。
优化例子
用多态替换switch语句之前
int getArea() {switch (shape){case SHAPE.CIRCLE:return 3.14 * _r * _r; break;case SHAPE.RECTANGEL;return width *,heigth;}}
用多态替换switch语句之后
class Shape {int getArea(){};}class Circle extends Shape {int getArea() {return 3.14 * r * r;}}class Rectangel extends Shape {int getArea() {return width * heigth;}}
将过多的参数对象化
定义
将过多的参数对象化就是把涉及过多参数封装成一个对象传参。
一个方法有太多传参时,即难以阅读又难于维护。尤其针对dubbo远程调用这些方法,如果有过多参数,增加或者减少一个参数,都要修改接口,真的坑。如果把这些参数封装成一个对象,就很好维护了,不用修改接口。
优化例子
将过多的参数对象化之前:
public int register(String username,String password,Integer age,String phone);将过多的参数对象化之后:
public int register(RegisterForm from );class RegisterForm{private String username;private String password;private Integer age;private String phone;}
参考与感谢
《重构-改善既有代码的设计》

腾讯、阿里、滴滴后台面试题汇总总结 — (含答案)
面试:史上最全多线程面试题 !
最新阿里内推Java后端面试题
JVM难学?那是因为你没认真看完这篇文章

关注作者微信公众号 —《JAVA烂猪皮》
了解更多java后端架构知识以及最新面试宝典


看完本文记得给作者点赞+在看哦~~~大家的支持,是作者源源不断出文的动力
