2013-10-16 135 views
1

我有一個大對象,在我做一些事情之前,我需要檢查多個條件。我有一個很大的功能。這是不可讀的,我想把它分解爲更小的函數,以使我的代碼更清晰。正確的方法來拆分功能

該功能正在檢查條件,如果某件事情不正確,則停止並返回問題(屬於enum類型)。

它看起來像這樣:

AnswerEnum CheckEverything(Bigobj o) 
{ 
    // some calculation 
    if (...) 
    return AnswerEnum.Error1; 

    // some more calculation 
    if (...) 
    return AnswerEnum.Error2; 

    ... 
    return AnswerEnum.OK; 
} 

現在,我想借此計算在更小的功能,我可以做的是以下幾點:

AnswerEnum CheckEverything(Bigobj o) 
    { 
    AnswerEnum ret; 
    ret=CheckFirstThing(o); 
     if (ret!=AnswerEnum.OK) 
     return ret; 

    ret=CheckSecondThing(o); 
     if (ret!=AnswerEnum.OK) 
     return ret; 

     ... 
     return AnswerEnum.OK; 
    } 

此解決方案包含

if (ret!=AnswerEnum.OK) 
    return ret; 

多次,我不喜歡它。 我想盡量減少return聲明的數量和代碼的任何重複部分。在這種情況下我怎麼能做到這一點?

+6

轉到http://codereview.stackexchange.com –

回答

6

如果所有的校驗功能具有相同的簽名(這似乎是在代碼的情況下你貼),那麼所有你需要做的就是創建這樣的代表名單:

List<Func<Bigobj, AnswerEnum>> list; 

那麼您在類初始化過程中添加你的所有檢查方法吧:

list.Add(CheckFirstThing); 
list.Add(CheckSecondThing); 

,並在最後,檢查一切:

AnswerEnum ret; 

foreach(Func<Bigobj, AnswerEnum> f in list) 
{ 
    ret = f(o); 
    if (ret != AnswerEnum.Ok) return ret; 
} 
return AnswerEnum.Ok; 
+0

我會用這個解決方案,很好。 – MUG4N

+0

這裏沒有真正的理由在循環的外面定義'ret'。它應該可以在循環的範圍內。 – Servy

0

恕我直言,這是更好的使用Delegate Dictionary Design Patternhttp://wilbloodworth.com/delegate-dictionary-pattern/)當許多checkings要執行:

AnswerEnum CheckEverything(Bigobj o) 
{ 
    List<Func<AnswerEnum>> checkings = new List<Func<AnswerEnum>> 
    { 
    (obj)=>{return CheckFirstThing(obj);}, 
    (obj)=>{return CheckSecondThing(obj);} 
    }; 

    foreach(var chk in checkings) 
    { 
     AnswerEnum answer; 
     if((answer= chk(o))!=AnswerEnum.OK) 
      return answer; 
    } 
    return AnswerEnum.OK; 
} 
4

定義了一種新方法:

private AnswerEnum ConditionalCheck(AnswerEnum current, 
            Func<BigObj, AnswerEnum> func, 
            BigObj obj) 
{ 
    return current == AnswerEnum.OK ? func(obj) : current; 
} 

然後修改代碼以:

AnswerEnum CheckEverything(Bigobj o) 
{ 
    var ret = AnswerEnum.OK; 
    ret = ConditionalCheck(ret, CheckFirstThing, o); 
    ret = ConditionalCheck(ret, CheckSDecondThing, o); 
    return ret; 
} 

另外,如果你真的想減少方法的大小,我會改變它:

AnswerEnum CheckEverything(List<Func<BigObj, AnswerEnum> funcs, Bigobj o) 
{ 
    foreach (var func in funcs) 
    { 
     var result = func(o); 
     if (result != AnswerEnum.OK) { return result; } 
    } 
    return AnswerEnum.OK; 
} 

這樣你就可以注入一組檢查,所以更容易閱讀,測試和維護。另外,一旦失敗就檢查中止,使其更快。

+0

謝謝你的回答!它清晰可讀,但我不喜歡一件事:在發現問題後,我不想調用其他功能,即使它們不會做任何事情。 – gkovacs90