Monday, December 10, 2012

重構-Code Refactoring-Vol.2

1.Replace Temp with Query

2.Introduce Explaining Variable

3.Split Temporary Variable

4.Remove Assignments to Parameters

5.Replace Method with Method Object

6.Substitute Algorithm

1.Replace Temp with Query

將運算式提煉成一個獨立函式(query Method)。

將暫時變數的所有引用點替換為對新函式的呼叫。新函式可被其他函式所使用。

Example:

   1: double basePrice = _quantity *_itemPrice;
   2: if(basePrice > 10000)
   3:     return basePrice * 0.95;
   4: else
   5:     return basePrice * 0.98;

提煉



   1: if(basePrice() > 10000)
   2:     return basePrice() * 0.95;
   3: else
   4:     return basePrice() * 0.98;
   5: //...
   6: double basedPrice()
   7: {
   8:     return _quantity *_itemPrice;
   9: }

Motivation


1.將暫時變數替換成query method同一個Class都可以獲得這資訊且能夠為這class編寫更清晰的程式碼。


2.Replace Temp with Query往往運用Extract Method之前不可少的一個步驟,區域變數會使程式碼難以提煉,所以應該盡可能將區域變數替換為query method


3.暫時變數只被賦值一次,或者賦值給暫時變數的運算式不受其他條件影響。


4.可先將query method需告成private,較容易保護。


5.確保提煉出來的函式無任何副作用。如果有影響可使用Separate Query from Modifier


 


2.Introduce Explaining Variable


將複雜運算式(或其中一部分)的結果放進一個暫時變數,以此變數名稱來解釋運算適用途。


Example:



   1: if(platform.toUpperCase().indexOf("MAC") > -1 )&&
   2:         browser.toUpperCase().indexOf("IE") > -1)&&
   3:         wasInitialized() && resize > 0)
   4: {}

提煉



   1: final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
   2: final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
   3: final boolean wasResized = resize >0;
   4: if(isMacOs && isIEBrowser && wasInitialized() && wasResized){}

Motivation:


1.用良好命名的暫時變數來解釋對應條件子句的意義。


2.但也可以盡量使用Extract Method來解釋一段程式碼意義,這方法就可以不需要做了。


 


3.Split Temporary Variable


某個暫時變數被賦值超過一次,它既不是迴圈變數,也不是一個急用暫時變數(collecting temporary variable)。


Example:



   1: double temp = 2 * (_height + _width);
   2: System.out.println(temp);
   3: temp = _height * _width;
   4: System.out.println(temp);

提煉



   1: final double perimeter = 2 * (_height + _width);
   2: System.out.println(perimeter);
   3: final double area = _height * _width;
   4: System.out.println(area);

Motivation:


1.暫時變數可能會被多次賦值,為每個不同功能的暫時變數給予不同的命名。


 


4.Remove Assignments to Parameters


對一個參數進行賦值的動作。


Example



   1: int discount (int inputVal,int quantity,int yearToDate)
   2:     if(inputVal > 50) inputVal -= 2;

提煉



   1: int discount (int inputVal,int quantity,int yearToDate)
   2: {
   3:     int result - inputVal;
   4:     if(inputVal > 50) result -= 2;
   5: }

Motivation:


1.會使用這個方式是因為降低了pass by value 和 pass by reference的清晰度。


 


5.Replace Method with Method Object


將這個函式放進一個單獨物件中,如此一來區域變數就成了物件內的欄位。然後在同一個物件將這個大型函式分解數個小函式。


Example



   1: class Order..
   2: double price(){
   3:     double primaryBasePrice;
   4:     double secondaryBasePrice;
   5:     double tertiaryBasePrice;
   6: }

 繪圖3


Motivation


1.區域變數的存在增加函式分解難度,雖然Replace Temp with Query可以減輕一點負擔,但還是可能完全無法拆解,就可使用這個方法。
2.這將會把所有區域變數變成函式物件,然後使用Extract Method。



   1: class Account
   2: {
   3:     int gamma(int inputVal,int quilityVal,int date)
   4:     {
   5:         int importantVal1 = (intputVal * quility) * delta();
   6:         int importantVal2 = (inputVal * date);
   7:         //And so on...
   8:         return importantVal3 *2;
   9:     }
  10: }

建立新的Class



   1: class gamma
   2: {
   3:     private Account _acount;
   4:     private int inputVal;
   5:     private int data;
   6:     private int qualityVal;
   7:     private int importValue1;
   8:     private int importValue2;
   9:     //Constructor
  10:     Gamma(Acount source,int inputValArg,int quilityArg,int dataArg)
  11:     {
  12:         _acount = source;
  13:         inputVal = inputValAtg;
  14:         quilityVal = quilityArg;
  15:         data = dataArg;
  16:     }
  17:     int compute()
  18:     {
  19:         importantValue1 = (inputVal * quility) + _account.delta();
  20:         return ....
  21:     }
  22: }




因此在改動Account Class:



   1: int gamma(int inputVal,int quility,data)
   2: {
   3:     return new Gamma(this,inputVal,quility,data).compute();
   4: }

可以輕易的在Gamma class 使用Extract Method。


5.Substitute Algorithm



   1: string foundPerson(string[] people)
   2: {
   3:     for(int i =0; i< people.length;i++)
   4:     {
   5:         if(people[i].equals("Don"))
   6:           return "Don";
   7:         if(people[i].equals("J"))
   8:           return "J";
   9:         if(people[i].equals("D"))
  10:           return "D";
  11:     }
  12:     return "";    
  13: }

提煉



   1: string foundPerson(string[] people)
   2: {
   3:     List candidates - Arrays.asList(new string[] {"Don","J","D"}  );
   4:     for (int i =0; i < people.length;i++)
   5:         return people[i];
   6:     return "";
   7: }

No comments:

Post a Comment