1.1 起點
背景:影片出租商店應用。涉及三個類:電影,出租,顧客。
源碼鏈接:
https://github.com/sigma65535/Refactoring_improving_the_design_of_existing_code/tree/master/Chapter1
UML圖:
問題所在:
在Customer中statement()這個函數非常長,大約有50行。而且做了不止一件事情。(swich語句完成折扣計算,result完成結果返回輸出)。《clean code》中對函數的要求是:短小,一個函數只做一件事等。
Tip:程序需要添加特性時,原有的代碼結構無法方便的擴展,此時需要重構。
1.2 重構的第一步
必須建立良好的測試環境,好的測試是重構的根本。
1.3 分解重構statement()
1.2 重構的第一步
必須建立良好的測試環境,好的測試是重構的根本。
1.3 分解重構statement()
函數中最複雜的是switch這個邏輯泥團,如下圖所示:
Eclipse IDE中有強大的重構工具,方便我們進行重構。如下:
處理步驟1:將switch這個函數提取爲一個單獨的函數;
方法:
在statement()函數下,新方法已經抽離出來。
函數的參數變量thisAmount其實是個常數,可以拿到函數裏邊來進行處理。(《clean code》 函數的參數越少越好)。
進一步,將thisAmount變量重名爲改爲result更合理。依然是refactor菜單Rename,
這樣方法內的thisAmount會一同變爲result,這樣可以避免手動修改出錯。
2.搬移金額計算代碼
getCharge()函數並沒有涉及Customer類中的變量,因此放這不合適。在該方法中Rental類有關,因此應將getCharge()搬移到Rental.
選中方法後,執行Move……操作,IDE自動會分析方法應該移動到Rental類下邊。
金額搬遷之後的,所有類的狀態:
3.臨時變量往往容易導致大量參數傳來傳去,觀察下邊的代碼,thisAmount應該刪除。
4. 同樣的方法來處理frequentRenterPoints的計算代碼,將其提煉爲一個單獨的方法getFrequentRenterPoints(),並移動到Rental類中。
分析上圖的矩形區域內的代碼,每次進入while循環的if語句時 frequentRenterPoints+2,否則frequentRenterPoints+1;根據此寫出代碼,並移動到Rental類之後。
frequentRenterPoints()處理之後的UML圖如下:
5. 去除臨時變量totalAmount,將其值得計算用函數getTotalAmount()替代。
6 同樣處理frequentRenterPoints,用方法getFrequentRenterPoints()替代
private int getFrequentRenterPoints(){
int result = 0;
Enumeration<Rental> rentals = _rentals.elements();
while (rentals.hasMoreElements()) {
Rental each = (Rental) rentals.nextElement();
result += each.getFrequentRenterPoints();
}
return result;
}
1.4 利用多態邏輯取代與價格相關的條件邏輯。
引入了state模式來進行重構。
1.5重構總結
各個重構過程中UML的變換圖如下: