文章出處

重構

以查詢取代臨時變量

臨時變量的問題在于:它們是暫時的,而且只能在所屬函數內使用。由于臨時變量只能在所屬函數內可見,所以它們會趨勢你寫出更長的函數,因為只有這樣你猜可以訪問到所需要的臨時變量,如果把臨時變量替換為一個查詢,那么同一個類中的所有函數都可以獲得這份信息。

范例

double getPrice() {
   int basePrice = number * itemPrice;
   double discountFactor;
   if (basePrice > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice * discountFactor;
}

將臨時變量聲明為final

double getPrice() {
   final int basePrice = number * itemPrice;
   final double discountFactor;
   if (basePrice > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice * discountFactor;
}

把賦值動作的右側表達式提煉出來

double getPrice() {
   final int basePrice = getBasePrice();
   final double discountFactor = getDiscount();
   return getBasePrice() * discountFactor;
}

int getBasePrice() {
    return number * itemPrice;
}

double getDiscount() {
    if (getBasePrice() > 1000) return  0.95;
    else return  0.98;
}

最后

double getPrice() {
   final int basePrice = getBasePrice();
   
   return getBasePrice() * getDiscount();
}

int getBasePrice() {
    return number * itemPrice;
}

double getDiscount() {
    if (getBasePrice() > 1000) return  0.95;
    else return  0.98;
}

引入解釋性變量

你有一個復雜的表達式,將該復雜的表達式(或其中一部分)的結果放進一個臨時變量,以此變量名稱來解釋表達式的用途。

if ((platform.toUpperCase().indexOf("MAC") > -1) &&
    (browser.toUpperCase().indexOf("IE") > -1)  &&
    wasInitialized() && resize > 0)
{
    // do something
}

可以重構為:

final boolean isMacOS = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = platform.toUpperCase().indexOf("IE") > -1
final boolean wasResized = resize > 0;
if (isMacOS && isIEBrowser && wasInitialized() && wasResized)
{
    // do something
}

分解臨時變量

如果你的程序有某個臨時變量賦值超過一次,它既不是循環變量也不是結果收集變量,這就意味著這個臨時變量在函數中承擔了一個以上的責任,如果臨時變量承擔多個責任,就應該針對每次賦值,創造一個獨立,對應的臨時變量。

double temp = 2 * (height + width);
System.out.println(temp);
temp = height * width;
System.out.println(temp);

應該改寫成:

final double perimeter = 2 * (height + width);
System.out.println(perimeter);
final double area = height * width;
System.out.println(area);

以函數對象取代函數

將這個函數放進一個單獨的對象中,如此一來局部變量就成了對象內的字段,然后你可以在同一個對象中將這個大型函數分解為多個小型函數

class Account {
   int gamma(int inputVal, int quantity, int yearToDate) {
        int importantValue1 = (inputVal * quantity) + delta();
        int importantValue2 = (inputVal * yearToDate) + 100;
        if ....
        ....
        ....
        return importantValue3 - 2 * importantValue1;
   }    
}

第一步:把這個函數變為一個函數對象,并加入一個構造函數

class Gamma {
    private final Account account;
    private int inputVal;
    private int quantity;
    private int yearToDate;
    private int importantValue1;
    private int importantValue2;
    pirvate int importantValue3;
    
    Gamma(Account account, int inputVal, int quantity, int yearToDate) {
        this.xx = xx
        ...
        ...
        ...
    }
}

現在可以把原本的函數搬到compute()中了,

int compute() {
    int importantValue1 = (inputVal * quantity) + account.delta();
    int importantValue2 = (inputVal * yearToDate) + 100;
    if ....
    ....
    ....
    return importantValue3 - 2 * importantValue1;
}

然后,我們修改舊的函數:

int gamma(int inputVal, int quantity, int yearToDate) {
    return new Gamma(this, inputVal, quantity, yearToDate).compute();
}    

文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()