2013-10-16 53 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