重构:一、重新组织方法
来源:互联网 发布:特效照相机软件下载 编辑:程序博客网 时间:2024/05/17 01:42
重构:
在编写完代码后,仔细再去检查,会发现有很多地方都有改进。代码的重构(整理)可以为后期维护带来很好的选择。每个方法的粒度应该尽可能的比较小,这样复用代码重写代码,效率才会偏高。
- 重新组织方法
- 提炼方法
- 内联方法
- 内联临时变量
- 某些时候可以以查询方式取代临时变量
- 引入解释性变量
- 分解临时变量
- 移除对参数的赋值
- 以方法对象取代方法
- 替换算法
- 重新组织方法
重新组织方法
1. 提炼方法
提炼方法是最常用也是用的最多的一种手法。将一个过长的方法,提炼成一个主方法下多个子方法。这样的好处是,在后期如果不需要某个逻辑,直接注释其调用即可,如果再需要时,可以再添回来。如果不需要时删除,需要时再写,就重复了。
例如:
//存在伪代码public void printBill(double amount) { double total = 0; System.out.println("-----------"); System.out.println("------顾客账单-----"); System.out.println("-----------"); for(Order order : orders){ total += order.getPrice(); } System.out.println("顾客:" + name); System.out.println("付款总额:" + total);}
上面这个方法,虽然比较简单,但是依然是可以进行提炼的。提炼结果:
public void printBill(double amount) { printBillHeader(); double total = getTotal(); printDetail(total);}private void printBillHeader(){ System.out.println("-----------"); System.out.println("------顾客账单-----"); System.out.println("-----------");}private double getTotal(){ double total = 0; for(Order order : orders){ total += order.getPrice(); } return total;}private void printDetail(double total){ System.out.println("顾客:" + name); System.out.println("付款总额:" + total); }
提炼成这样的结果后,在阅读方面,易于阅读,在后期维护方面,也更易维护。
提炼原则
- 一个大的方法可以进行分解
- 分解后的方法用方法名表达方法主体意图
除了将大的方法分解为小的方法外,也可以重新修改变量名,让其名称更能表达其用意。重构的目的是,让计算机理解的程序修改成人可以理解的程序。只要能够清晰表达方法的意图,不在乎方法名的长短。
2. 内联方法
一个提取的方法本体与它的方法名一样清晰易懂,应该移除这个方法,将它内联到原方法中。
例如:
public int getRating(){ return (moreThanFiveLateDeliveries()) ? 2 : 1;}private boolean moreThanFiveLateDeliveries(){ return numberOfLateDeliveries > 5;}
因为函数本体就很清楚,所以,可以将它内联到调用方法中。
public int getRating(){ return numberOfLateDeliveries > 5 ? 2 : 1;}
这种情况应该很少遇到。
3. 内联临时变量
方法内存在一个简单变量,只被赋值一次,使用一次。
double basePrice = order.getBasePrice();if (basePrice > 100){}
改变后:
if (order.getBasePrice() > 100) {}
4. 某些时候可以以查询方式取代临时变量
某些时候可以把临时变量变成一种查询方式,虽然这样会调用多次方法,性能上有点影响,但是有些时候把这些变量分开,会让代码提炼的更简洁。举个例子:
public double getPrice(){ int basePrice = quantity * itemPrice; double discountFactor; if (basePrice > 1000) { discountFactor = 0.95; } else { discountFactor = 0.98; } return basePrice * discountFactor;}
似乎好像没有哪个地方可以提炼的,因为一个临时变量贯穿了整个方法,没有必要把它们分开。但是如果把这个临时变量定义为一个方法的话,就比较好提炼了。
public double getPrice(){ return getBasePrice() * getDiscountFactor();}public int getBasePrice(){ return quantity * itemPrice;}public double getDiscountFactor(){ if (getBasePrice() > 1000) { return discountFactor = 0.95; } return discountFactor = 0.98;}
有时候如果一个临时变量比较简单,不涉及太多查询的话,这种方式是可以采取的,因为调用一个方法来获取的时间,基本可以忽略。如果这个值是从数据库中查询的话,不建议使用,因为每次查数据库,消耗都比较大。
5. 引入解释性变量
例:
if (platform.toUpperCase.indexOf("MAC") != -1 && browser.toUpperCase.indexOf("IE") != -1 && resize > 0) { //dosomething}
变更为:
boolean isMac = platform.toUpperCase.indexOf("MAC") != -1;boolean isIE = browser.toUpperCase.indexOf("IE") != -1;if(isMac && isIE && resize > 0){ //dosomething}
这种方式可以用第一种方式,提炼方法来代替。
6. 分解临时变量
其实就是意义不同不要使用同一个变量。
例如:
double temp = 2 * (width + height);System.out.println(temp);temp = width * height;System.out.println(temp);
要将这个temp分解成两个变量。
double girth = 2 * (width + height);System.out.println(girth);double area = width * height;System.out.println(area);
7. 移除对参数的赋值
也就是说,如果不想改变参数的值,就不要对参数赋值。
8. 以方法对象取代方法
一个比较大的方法,其中局部变量使用方式一的形式进行了提取。如果还有其他比较多的提取方法,将这些方法放入一个单独的类中,其中,局部变量便成了对象的字段,其他方法将是对象的方法。
示例:
public class Account { public int gamma(int inputValue, int quantity, int yearToData) { int importValue1 = (inputValue - quantity) * delta(); int importValue2 = inputValue * yearToData + 100; if (yearToData - importValue1 > 100 ){ importValue2 -= 20; } int importValue3 = importValue2 * 7; return importValue3 - 2 * importValue1; }}
把提炼的方法放在一个新的对象中。
public class Gamma { private Account account; private int inputValue; private int quantity; private int yearToData; private int importValue1; private int importValue2; private int importValue3; public Gamma(Account source, int inputValue, int quantity, int yearToData){ this.account = source; this.inputValue = inputValue; this.quantity = quantity; this.yearToData = yearToData; } public int cumpute(){ //.... }}原来的将变为:public class Account { public int gamma(int inputValue, int quantity, int yearToData) { return new Gamma(this, inputValue, quantity, yearToData).cumpute(); }}
上面是一个简单示例,如果是一个大的方法,可以采用类似的这种方式。这样做的好处是,整个类会变得比较小。阅读起来更加容易。如果一个类中存放一大堆私有方法,第一眼看上去,就很累赘。
9. 替换算法
如果想把某个算法换成更清晰的算法,直接替换。
示例:
String fondPerson(String[] peoples){ for(String people : peoples){ if (people。equals("Don")) { return "Don"; } if (people。equals("John")) { return "John"; } } return null;}
如果要换另一种写法,直接删了原来的,替换新的即可。
String fondPerson(String[] peoples){ String[] exist = {"Don", "John"}; for(String people : peoples){ if(ArrayUtils.contains(exist, people)){ return people; } } return null;}
上面是对方法进行重构的几种手法。方法的重构是比较频繁的,几乎每个人都能遇到,也是最基本的。只是很多人像我一样,写完代码测试通过之后,再就不想回头去修改自己的代码了。在后期慢慢修改这种坏习惯。勤看自己写过的代码,优化以前的代码,使看起来更易懂,维护起来更方便。
- 重构:一、重新组织方法
- 重构手法(一) —— 重新组织方法
- 重构手法一重新组织函数
- 重构方法之重新组织函数
- 重构方法之重新组织数据
- 【重构笔记】重构手法之重新组织方法
- 重新组织函数(重构手法一)
- 重构-重新组织函数
- 重构--重新组织函数
- 重构 重新组织函数
- 《重构改善既有代码的设计》之重构列表--重新组织函数(一)
- 《重构改善既有代码的设计》之重构列表--重新组织数据(一)
- 重构之重新组织数据
- 重构之重新组织函数
- 重构系列3.重新组织函数
- 重构系列5.重新组织数据
- 代码重构-重新组织函数
- 重构手法之重新组织函数
- Heroku工具
- JAVA02
- java中的重写和重载
- GloVe学习笔记
- The Smallest String Concatenation CodeForces
- 重构:一、重新组织方法
- TPC/IP发送文件
- caffe安装调试(win10+VS2013)
- Jeesite配置使用之代码生成
- 多线程方式
- 源生JS实现回到顶部--缓冲效果
- Android Studio初认识
- IDEA 乱码以及junit模板
- 1121. Damn Single (25)[数学逻辑]