2017-04-01 65 views
2

這是一個抽象的問題,沒有真正的代碼(也可能不是最好的僞代碼),所以希望它足夠有意義,不會被主持人死亡。但是這個問題一直在我面前反覆提出,因爲我正在開展的項目是非常線性的,取決於以前的條件和流程。所以...順序邏輯和可讀性

給定了一系列邏輯任務,每個邏輯任務都依賴於前一個,我嘗試了兩種方法來構造代碼。 一個取決於proceed變量,這樣

Proceed = True 

If Task1 Not Successful Then 
    Proceed = False 
End If 

If Proceed Then 
    If Task2 Not Successful Then 
     Proceed = False 
    End If 
End If 

但我已經在許多地方意見的效果看,這種運行繼續變量的方法是不理想的。所以,或者我可以有

If Task1 Succcesful Then 
    If Task2 Successful 
     Then Etc 
    Else 
     Error Condition 
    End If 
Else 
    Error Condition 
End If 

在我看來,前者更可讀,邏輯非常明顯。而且,當順序中的任務數量變大(超過3個或者真的)時,嵌套的Ifs真的變得笨拙。 所以,我的問題是,不使用這種第一種方法的原因是什麼? 有沒有更好的方法來構建第二個例子中的邏輯來提高可讀性? 還是有第三種方式解決前者的問題(不管他們是什麼)以及後者的可讀性問題? 還是第一種方法實際上很好,當一個確實有順序依賴任務序列?

回答

0

這真的取決於你的情況。如果沒有進一步的細節,並與代碼是完全等同於原來的塊堅持,我會避免不必要的嵌套開始:

Proceed = False; 

if Task1 successful and Task2 successful Then 
    Proceed = True 
end if 

在大多數語言中,你可以把布爾直入變量。

Proceed = task1 successful and task2 successful 

如果你真的喜歡避免和的話,或許是這樣的:

Proceed = True; 

If Task1 not successful then 
    Proceed = False 
Else if Task2 not successful then 
    Proceed = False 
Else if Task3 not successful then 
    Proceed = False 
End if 

在所有情況下,到目前爲止,你避免嵌套。爲了便於閱讀,這很重要。

除此之外,您的替代品有兩個變化。首先是「繼續」變量完全丟失的事實。我同意這一點。什麼你原來的代碼讀者必須克服的是:

初始化X ...現在,如果x然後準備Y ...好了,現在做ÿ

如果你可以改變這:

如果x然後做ÿ

這是概念上更容易。

所以我會做:

If Task1 successful and Task2 successful and Task3 successful then 
    Do your thing 
End if 

或者

If Task1 not successful then 
    Do something 
else If Task2 not successful then 
    Do some other thing 
else 
    Do your main thing 
end if 

第二個區別是,你把「錯誤狀態」。特別是,你提到「錯誤」。如果您正在閱讀的文檔說您應該處理錯誤(例如通過停止執行並打印錯誤消息),那麼這是正確的。儘管如果你有機會,你應該在處理if/then語句之前處理它們,例如Task1過程內部。這不僅簡化了if/then語句,而且對於編碼人員來說也是一個更好的體驗,因爲任何體面的IDE都會導致他們失敗,最好是一出現就處理失敗,這樣開發商沒有很長的路要跟蹤,看看最終的來源。

0

兩者都很常見。第一次使用需要幾種方法的順序調用一些連貫的API的工作時尤爲常見:

API_THING *thing = NULL; 
API_RESULT result = CreateThing(&thing, ...); 
if (API_OK == result) result = InitializeThing(&thing, ...); 
if (API_OK == result) result = DoThingToThing(&thing, ...); 
// ... 
if (thing) 
{ 
    ReleaseThing(&thing, ...); 
    thing = NULL; 
} 

另一種是常見的,如果你不需要巢超過2-3層深(特別是如果這兩種情況的處理):

尚未提出另外一個是goto和/或例外:

API_THING *thing = NULL; 
if (API_OK != CreateThing(&thing, ...)) goto CLEANUP; 
if (API_OK != InitializeThing(&thing, ...)) goto CLEANUP; 
if (API_OK != DoThingToThing(&thing, ...)) goto CLEANUP; 
//... 
CLEANUP: 
if (thing) 
{ 
    ReleaseThing(&thing, ...); 
    thing = NULL; 
} 

如果使用異常你可能不喜歡在goto上面的例子,扔在每一行,或者你mig HT包裝你的API中拋出方法:

void DoCreateThing(API_THING **thing, ...) 
{ 
    if (API_OK != CreateThing(thing, ...)) 
     throw new ApiException("CreateThing Failed!"); 
} 

//... 

API_THING *thing = NULL; 
try 
{ 
    DoCreateThing(&thing, ...); 
} 
catch (ApiException e) 
{ 
    // ... 
} 
// ... 
finally 
{ 
    if (thing) 
    { 
     ReleaseThing(&thing, ...); 
     thing = NULL; 
    } 
} 

採取心臟:如果你是做節目吧,你做任何決定,這裏將不那麼重要,你怎麼從你的高層架構封裝的行爲該位。