Replace Temp with Query

當你的程序以一個臨時變量保存某一表達式的運算結果

將這個表達式提煉到一個獨立函數中,將這個臨時變量的所有[被引用點]替換爲[對新函數的調用],新函數可被其他函數使用

java 代碼
  1. double  basePrice=_quantity * _itemPrice;
  2. if(basePrice>1000){
  3.      return basePrice * 0.95;
  4. else
  5.      return basePrice * 0.38;
  6. }
  7. ......

 

提煉後:

java 代碼
  1. if (basePrice()>1000){
        return basePrice() * 0.95
  2. else
  3.     return basePrice() * 0.38
  4. }
  5. ......
  6. double basePrice(){
  7.     return _quantity * _itemPrice;
    }

動機:
臨時變量的問題在於:它們是暫時的,而且只能在所屬函數內使用,由於臨時變量只有在所屬內纔可見,所以它們會驅使你寫出更長的函數,因爲只有這樣你才能訪問到想要訪問的臨時變量,如果把臨時變量替換爲一個查詢式(query method),那麼同一個CLASS中的所有函數都將獲得這份信息。這將帶給你極大幫助,使你能夠爲這個CLASS編寫更清晰的代碼。

這個重構手法較爲直率的情況就是:臨時變量只被賦值一次,或者賦值給臨時變量的表達式不受其他條件影響,其他情況比較情況棘手,但也有可能發生,你可能需要先運用Split Temporary Variable 或Separate Query from Modifier 使情況變得簡單一些。如果你想替換的臨時變量是用來收集結果的(例如循環中的累加值),你就需要將某些程序的邏輯(例如循環)拷貝到查詢式(query method)去。


作法:

  • 找出只被賦值一次的臨時變量
  • 將臨時變量聲明爲 final
  • 編譯(這可確保臨時變量的確只被賦值一次)
  • 將對該臨時變量賦值之語句的等號右側部分提煉到一個獨立函數中。詳細步驟:首先將函數聲明爲private,之後你可能會發現有更多CLASS需要使用它,彼時你可輕易放鬆對它的保護。確保提煉出來的函數無任何連帶影響,就對它進行Separate Query from Modifier
  • 編譯,測試

 範例:
首先,我從一個簡單函數開始:

java 代碼
  1. double  getPrice()
  2. {   
  3.      int basePrice=_quantity+_itemPrice;   
  4.      double discountFactor;   
  5.      if(basePrice>1000)   
  6.         discountFactor=0.95;   
  7.      else  
  8.         discountFactor=0.98;   
  9.      return  basePrice = discountFactor;   
  10.    
  11. }  

 我希望將這個兩個變量都替換掉,當然,每次一個。

儘管這裏的代碼十分清楚,我還是先把臨時變量聲明爲final,檢查它們是否的確只被賦值一次:

java 代碼
  1. double getPrice()   
  2. {   
  3.       final int basePrice = _quantity * _itemPrice;   
  4.       final double discountFactor;   
  5.       if(basePrice>1000)   
  6.          discountFactor=0.95;   
  7.       else  
  8.          discountFactory=0.98;   
  9.       return basePrice * discountFactor;   
  10. }  

這麼一來,如果有任何問題,編譯器就會警告我,之所以先做這件事,因爲如果臨時變量不只被賦值一次,不該進行這項重構了,接下來我開始替換臨時變量了,每次一個,首先我把賦值動作的右側表達式提煉出來。

java 代碼
  1. double getPrice()   
  2. {   
  3.       final int basePrice = basePrice();   
  4.       final double discountFactor;   
  5.       if(basePrice >1000)   
  6.          discountFactor =0.95;   
  7.       else  
  8.          discountFactor =0.98;   
  9.       return basePrice * discountFactor;   
  10. }   
  11. private int basePrice()   
  12. {   
  13.       return _quantity * _itemPrice;   
  14. }   
  15.     

再把臨時變量的引用點替換掉:

java 代碼
  1. double getPrice()   
  2. {   
  3.     final int basePrice = basePrice();   
  4.     final double discountFactor;   
  5.     if ( basePrice()>1000 )   
  6.        discountFactor = 0.95;   
  7.     else  
  8.        discountFactor = 0.98;   
  9.    return basePrice() * discountFactor;   
  10. }  

下一步:

java 代碼
  1. double getPrice()      
  2. {      
  3.     final double discountFactor;      
  4.     if ( basePrice()>1000 )      
  5.        discountFactor = 0.95;      
  6.     else     
  7.        discountFactor = 0.98;      
  8.    return basePrice() * discountFactor;      
  9. }    

下一步(仔細觀察代碼)

java 代碼
  1. double getPrice()      
  2. {      
  3.    return basePrice() * discountFactor();      
  4. }     
  5.   
  6. private double discountFactor()   
  7. {   
  8.     if ( basePrice()>1000 )      
  9.        return  0.95;      
  10.     else     
  11.        return  0.98;      
  12. }   
  13.   
  14. private int basePrice()   
  15. {   
  16.     return _quantity * _itemPrice;   
  17. }  

是多麼簡單啊(代碼有錯請指點)

發佈了19 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章