Replace Nested Conditional with Guard Clauses

Summary 函數中的條件邏輯令人難以看清正常的執行路徑。使用衛語句表現全部特殊狀況。java

                         

動機:程序員

  條件表達式一般有兩種表現形式。第一種形式是:全部分支都屬於正常行爲。第二種形式則是:條件表達式提供的答案中只有一種是正常行爲,其餘都是不常見的狀況。編程

這兩類條件表達式有不一樣的用途,這一點應該經過代碼表現出來。若是兩條分支都是正常行爲,就應該使用如if…else…的條件表達式;若是某個條件極其罕見,就應該單獨檢查該條件,並在該條件爲真時馬上從函數中返回。這樣的單獨檢查經常被稱爲「衛語句」(guard clauses編程語言

Replace Nested Conditional with Guard Clauses的精髓就是:給某一條分支以特別的重視。若是使用if-then-else結構,你對if分支的重視是同等的。這樣的代碼結構傳遞給閱讀者的消息就是:各個分支有一樣的重要性。衛語句就不一樣了,它告訴閱讀者:「這種狀況很罕見,若是它真地發生了,請作一些必要的整理工做,而後退出。」函數

「每一個函數只能有一個入口和一個出口」的觀念,根深蒂固於某些程序員的腦海裏。當咱們處理他們編寫的代碼時,常常須要使用Replace Nested Conditional with Guard Clauses。現金的編程語言都會強制保證每一個函數只有一個入口,至於「單一出口」規則,其實不是那麼有用。保持代碼清晰纔是最關鍵的:若是單一出口能是這個函數更清楚一度,那麼就使用單一出口;不然就沒必要這麼作測試

作法:spa

1.對於每一個檢查,放進一個衛語句。code

 衛語句要不就從函數中返回,要不就拋出一個異常。orm

2.每次將條件檢查替換成衛語句後,編譯並測試。get

 若是全部衛語句都致使相同結果,請使用Consolidate Conditional Expressions 

  範例:

   想象一個薪資系統,其中以特殊規則處理死亡員工、駐外員工、退休員工的薪資。這些狀況不常有,但的確偶爾會出現。

假設咱們在這個系統中看到下列代碼:

double getPayAmount(){
    double result;
    if(_isDead){
        result = deadAmount();
    }else{
        if(_isSeparated){
            result = separatedAmount();
        }else{
            if(_isRetired){
                result = retiredAmount();
            }else{
                result = normalPayAmount();
            }
        }
    }
    return result;
}

在這段代碼中,非正常狀況的檢查掩蓋了正常狀況的檢查,因此應該用衛語句來取代這些檢查,以提升程序清晰度。咱們能夠逐一引入衛語句。讓咱們從最上面的條件檢查動做開始,:

double getPayAmoutn{
    double result;
    if(_isDead){
        return deadAmount();
    }
    if(_isSeparated){
            result = separatedAmount();
        }else{
            if(_isRetired){
                result = retiredAmount();
            }else{
                result = normalPayAmount();
            }
        }
     }
     return result
}

而後繼續下去,仍然一次替換一個檢查動做,直到最後一個:

double getPayAmoutn{
    double result;
    if(_isDead){
        return deadAmount();
    }
    if(_isSeparated){
        return separatedAmount()
    }
    if(_isRetired){
        return retiredAmount();
    }
    result = normalPayAmout();
    return result;
}

此時,result變量已經沒有價值了,因此咱們把它刪掉:

double getPayAmoutn{
    double result;
    if(_isDead){
        return deadAmount();
    }
    if(_isSeparated){
        return separatedAmount()
    }
    if(_isRetired){
        return retiredAmount();
    }
    return normalPayAmout();
}

嵌套條件代碼每每由那些深信「每一個函數只能有一個出口」的程序員寫出。我發下那條規則實在有點太簡單粗暴了。若是對函數剩餘部分再也不有興趣,固然應該馬上退出。引導閱讀者去看一個沒有用的else區段,只會妨礙他們的理解。

相關文章
相關標籤/搜索