一 Extract Method (提煉函數)
當看見一個過長的函數或者一段需要註釋才能讓人理解用途的代碼,需要將這段代碼放進一個獨立函數中。提煉函數有如下好處:
1 首先,如果每個函數的粒度都很小,name函數被複用的機會就很大;
2 其次,這樣做會使得高層函數讀起來就像一系列註釋;
3 最後,如果函數都是細粒度,那麼函數的覆寫也會更容易一些。
二 Inline Method (內聯函數)
如果函數的內容和起函數名稱同樣清晰,可以直接使用內部的代碼,去掉這個函數。 一些組織不合理的函數,可以將函數都內聯到一個大型函數中,再從中提煉出組織合理的小型函數。代碼示例如下:
代碼片段 A:
int getRating() {
return (moreThanFiveLateDeliveries()) ? 2:1;
}
boolean moreThanFiveLateDeliveries() {
return _numberOfLateDeliveries > 5;
}
代碼片段 B:
int getRating() {
return _numberOfLateDeliveries > 5 ? 2:1;
}
將代碼片段 A 修改成代碼片段 B,清晰易讀。
三 Inline Temp (內聯臨時變量)
如果有一個臨時變量,只是被一個簡單表達式賦值一次,而它妨礙了其他重構手法。將所有對該變量的引用動作,替換爲對它賦值的那個表達式自身。代碼示例如下:
代碼片段 A:
double basePrice = anOrder.basePrice();
return (basePrice > 1000);
代碼片段 B:
return (anOrder.basePrice() > 1000);
四 Replace Temp with Query (以查詢取代臨時變量)
如果程序以一個臨時變量保存某一表達式的運算結果。將這個表達式提煉到一個獨立函數中,將這個臨時變量的所有引用點替換爲對新函數的調用。此後,新函數就可被其他函數使用。代碼示例如下:
代碼片段 A:
double basePrice = _quantity * _itemPrice;
if(basePrice > 1000) {
return basePrice * 0.95;
} else {
return basePrice * 0.98;
}
代碼片段 B:
if(basePrice() > 1000) {
return basePrice * 0.95;
} else {
return basePrice * 0.98;
}
double basePrice() {
return _quantity * _itemPrice;
}
五 Introduce Explaining Variable (引入解釋性變量)
比如你有一個複雜的表達式,可以將該複雜表達式(或其中一部分)的結果放進一個臨時變量,將以此變量名稱來解釋表達式用途。代碼示例如下:
代碼片段A
if((platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1)) && wasInitialized() && resize > 0) {
//do something
}
代碼片段B
final boolean isMacOS = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if(isMacOS && isIEBrowser && wasInitialized() && wasResized) {
//do something
}
六 Split Temporary Variable (分解臨時變量)
如果某一個臨時變量被賦值超過一次,它既不是循環變量,也不被用於手機計算結果。針對每次賦值,創造一個獨立、對應的臨時變量。代碼示例如下:
代碼片段A:
double temp = 2 * (_height + _width);
System.out.println(temp);
temp = _height * _width;
System.out.println(temp);
代碼片段B:
final double perimeter = 2 * (_height + _width);
System.out.println(perimeter);
final double area = _height * _width;
System.out.println(area);
七 Remove Assignments to Parameters (移除對參數的賦值)
代碼對一個參數進行賦值,以一個臨時變量取代該參數的位置。代碼示例如下:
代碼片段A:
int discount (int inputVal, int quantity, int yearToDate) {
if(inputVal > 50) inputVal -= 2;
}
代碼片段 B:
int discount (int inputVal, int quantity, int yearToDate) {
int result = inputVal;
if(inputVal > 50) result -= 2;
}
八 Replace Method with Method Object (以函數對象取代函數)
如果有一個大型函數,其中對局部變量無法提煉函數,將這個函數放進一個單獨對象中,如此一來局部變量就成了對象內的字段。然後你可以在同一個對象中將這個大型函數分解爲多個小型函數。
九 Substitute Algorithm (替換算法)
想要把某個算法替換爲另一個更清晰的算法,將函數本體替換爲另一個算法。