Remove Control Flag (移除控制標記)

Summary 在一系列布爾表達式中,某個變量帶有「控制標記」(control flag)的做用。break語句或return語句取代控制標記。java

動機:編程

  在一系列條件表達式中,你經常會看到用以判斷什麼時候中止條件檢查的控制標記:編程語言

Set done to false函數

While not doneoop

                If(condition)測試

                                Do something編碼

                                Set done to truespa

                Next step of loopcode

這樣的控制標記帶來的麻煩超過了它所帶來的便利。人們之因此會使用這樣的控制標記,由於結構化編程原則告訴他們:每一個子程序只能有一個入口和一個出口。我贊同「單一入口」原則(並且現代編程語言也強迫咱們這樣作),可是「單一出口」原則會讓你在代碼中加入討厭的控制標記,大大下降條件表達式的可讀性。這就是編程語言提供break語句和continue語句的緣由:用它們跳出複雜的條件語句。去掉控制標記所產生的效果每每讓你大吃一驚:條件語句真正的用途會清晰得多。it

作法: 

對控制標記的處理,最顯而易見的辦法就是使用Java提供的break語句或continue語句。

1.找出讓你跳出這段邏輯的控制標記值。

2.找出對標記變量賦值的語句,代以恰當的break語句或 continue語句。

3.每次替換後,編譯並測試。

在未能提供breakcontinue語句的編程語言中,可使用下述辦法。

1.運用Extract Method,將整段邏輯提煉到一個獨立函數中。

2.找出讓你跳出這段邏輯的控制標記值。

3.找出對標記變量賦值的語句,代以恰當的return語句。

4.每次替換後,編譯並測試。

即便在支持breakcontinue語句的編程語言中,咱們也優先考慮上述第二方案。由於return語句能夠很是清楚地表示:再也不執行該函數中的其餘任何代碼。若是還有這一類代碼,你遲早須要將這段代碼提煉出來。

請注意標記變量是否會影響這段邏輯的最後結果。若是有影響,使用break語句以後還得保留控制標記值。若是你已經將這段邏輯提煉成一個獨立函數,也能夠將控制標記值放在return語句中返回。

範例1: 以break 取代簡單的控制標記

    下列函數用來檢查一系列人名之中是否包含兩個可疑人物的名字(這兩我的的名字硬編碼與代碼中):

void checkSecuurity(String[] people){
    boolean found = false;
    for(int i=0; i < people.length; i++){
        if(!found){
            if(people[i].equals("Don")){
                sendAlert();
                found = true;
            }
            if(people[i].equals("John")){
                sendAlert();
                found = true;
            }
        }
    }
}

這種狀況下很容易找出控制標記:當變量found被賦予true時,搜索就結束。咱們能夠逐一引入break語句,直到替換掉全部found變量語句:

void checkSecuurity(String[] people){
    boolean found = false;
    for(int i=0; i < people.length; i++){
        if(!found){
            if(people[i].equals("Don")){
                sendAlert();
                break;
            }
            if(people[i].equals("John")){
                sendAlert();
                break;
            }
        }
    }
}

而後就能夠把全部對控制標記的引用都去掉:

void checkSecuurity(String[] people){
    for(int i=0; i < people.length; i++){
        if(people[i].equals("Don")){
           sendAlert();
           break;
        }
        if(people[i].equals("John")){
            sendAlert();
            break;
        }
    }
}

範例2:以return 返回控制標記

  本項重構的另外一種形式將使用return語句。爲了闡述這種方法,咱們把前面的例子稍加修改,以控制標記記錄搜索結果:

void checkSecuurity(String[] people){
    String found = "";
    for(int i=0; i < people.length; i++){
        if(found.equals("")){
            if(people[i].equals("Don")){
                sendAlert();
                found = "Don";
            }
            if(people[i].equals("John")){
                sendAlert();
                found = "John";
            }
        }
    }
    someLaterCode(found);
}

在這裏變量found作了兩件事:它既是控制標記,也是運算結果。遇到這種狀況,咱們先把計算found變量的代碼提煉到一個獨立函數中: 

void checkSecurity(String[] people){
    String found = foundMiscreant(people);
    someLaterCode(found);
}

String foundMiscreant(String[] people){
    String found = "";
    for(int i=0; i < people.length; i++){
        if(found.equals("")){
            if(people[i].equals("Don")){
                sendAlert();
                found = "Don";
            }
            if(people[i].equals("John")){
                sendAlert();
                found = "John";
            }
        }
    }
    return found;
}

  而後以return語句取代控制標記:

String foundMiscreant(String[] people){
    String found = "";
    for(int i=0; i < people.length; i++){
        if(found.equals("")){
            if(people[i].equals("Don")){
                sendAlert();
                return "Don";
            }
            if(people[i].equals("John")){
                sendAlert();
                return "John";
            }
        }
    }
    return found;
}

最後徹底去掉控制標記:

String foundMiscreant(String[] people){
    for(int i=0; i < people.length; i++){
        if(found.equals("")){
            if(people[i].equals("Don")){
                sendAlert();
                return "Don";
            }
            if(people[i].equals("John")){
                sendAlert();
                return "John";
            }
        }
    }
    return "";
}

即便不須要返回某值,也能夠用return語句來取代控制標記。這時候你只須要一個空的return語句就好了。

固然,若是以此辦法去處理帶有反作用的函數,會有一些問題。因此咱們須要先以Separate Query from Modifier將函數反作用分離出去。

相關文章
相關標籤/搜索