03. 重新組織函數

一 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 (替換算法)

       想要把某個算法替換爲另一個更清晰的算法,將函數本體替換爲另一個算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章