重新组织函数
一、提炼函数(Extract Method)
你有一段代码可以被组织在一起并独立出来,将这段代码放入一个独立的函数中,并让函数名称解释该函数的用途(以他做什么来命名)。
public void printOwing(){ int em=88; int outstanding=9999; //计算outstanding do { em--; outstanding+=em; } while (em==0); //pirnt outstanding System.out.println("Oh the outstanding is "); System.out.println(" "+outstanding); }
//提取后 public void printOwing(){ int em=88; int outstanding=9999; //计算outstanding do { em--; outstanding+=em; } while (em==0); //pirnt outstanding System.out.println("Oh the outstanding is "); System.out.println(" "+outstanding); }
一)为什么这样做?
1.提取过长代码使之便于理解。
2.细粒度代码,被复用的机会更大。
3.代码粒度更细,覆写更容易。
二)怎样做?
关键是新函数的命名,要一他“做什么来命名”。
二、内联函数(Inline Method)
如果一个函数的本体和其名称同样清楚易懂,就可以在函数调用点插入本体,删除该函数。
public int getRating(){ return moreThan5Delivers()?1:0; } boolean moreThan5Delivers(){ return numOfDelivers>5; }
//内联后 public int getRating(){ return numOfDelivers>5?1:0; }
一)为什么这样做?
间接性可以带来帮助,但非必要的间接性总让人不舒服。我们要移除不必要的间接层。
二)怎样做?
注意:确定函数不具有多态性。
三、内联临时变量(Inline Temp)
你有一个临时变量,只被简单的表达式赋值一次,而它妨碍了其他的重构手法。将所有对该变量的引用动作,替换为为它赋值的表达式自身。
四、以查询取代临时变量(Replace Temple with Query)
你的程序以一个临时变量保存某一表达式的运行结果。将这个表达式提炼到一个独立的函数中。
将这个临时变量的所有引用点替换为对新函数的引调用。此后,新函数就可以被其他函数调用。
//取代前的方法 public double getPrice(){ double basePrice=count*itemPrice; double discountFactor; if (basePrice>888) discountFactor=0.8; else discountFactor=0.9; return basePrice*discountFactor; }
public double getPrice(){ return basePrice()*discountFactor(); } //如果没有提炼basePrice,将难以提炼discountFactor! private double basePrice(){ return count*itemPrice; } private double discountFactor(){ if (basePrice()>888) return 0.8; else return 0.9; }
一)为什么这样做?
局部变量使代码变得难以提炼!
二)怎样做?
注意将该局部变量声明为fianl。
五、引入解释性变量(Introduce Explaining Variable)
你有一个复杂的表达式。将复杂表达式(或其中一部分)的结果放入一个临时变量,以此变量的名称来解释表达式的用途。
public double price(){ return count*itemPrice-(Math.max(0, count-5)*itemPrice*0.05+ Math.min(count*itemPrice*0.1, 100)); }
public double price(){ final double basePrice=count*itemPrice; final double discount=Math.max(0, count-5)*itemPrice*0.05; final double shipping=Math.min(count*itemPrice*0.1, 100); return basePrice-discount+shipping; }
一)为什么这样做?
同提炼函数一样,可以使复杂的表达式更容易理解。当一个函数的局部变量太多,
造成使用“提炼函数”法不太好用时,可以考录引入解释性变量。
二)怎样做?
记得将引入的变量声明为final。
六、分解临时变量(Split Temporary Variable)
你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果。
针对每次赋值,创建一个独立的、对应的临时变量。
public void suan(){ int temp=2*(height+width); System.out.println(temp); temp=height*width; System.out.println(temp); }
public void suan(){ final int zhouchang=2*(height+width); System.out.println(zhouchang); final int mianji=height*width; System.out.println(mianji); }
一)为什么?
如果一个临时变量被多次赋值,承担多个责任,就会使代码不易于理解。
七、移除对参数的赋值(Remove Assignments to Parameters)
代码对一个函数的参数赋值,以一个临时变量取代该参数的位置。
八、以函数对象取代函数(Replace Method with Method Object)
你有一个大型函数,其中对局部变量的使用使你无法采用提炼函数。将这个函数放入单独的对象中,
如此一来局部变量成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。
九、替换算法(Substitude Algorithm)
你想要把某个算法替换为另一个更清晰的算法,将函数本体替换为另一个算法。