具有许多条件返回语句的重构方法

时间:2010-03-02 20:12:39

标签: .net refactoring code-analysis fxcop

我有一个验证方法,它有很多条件语句。基本上就是

If Check1 = false 
  return false
If Check2 = false
  return false
etc

FxCop抱怨圈复杂度过高。我知道在函数中间使用return语句不是最佳实践,但与此同时,我看到的唯一替代方法是一个丑陋的If-else语句列表。解决这个问题的最佳方式是什么?

提前致谢。

4 个答案:

答案 0 :(得分:11)

我不同意你的说法,即在方法中间使用return语句不是最佳做法。有些人为了获得单一的return语句而去的长度是疯狂的 - 与任何产生最可读代码的东西一起去。有时这将是一个单一的返回点,但我经常发现有一个“提前退出” - 并且最好有这个回报,而不是为代码引入更多嵌套,并为替代路径添加if。根据经验,我喜欢不会缩进太多的方法:)

话虽如此,该方法真的没有但检查?检查是独立的吗?他们需要什么变量?您可以将它们分组为代表您正在执行的支票的“区域”的较小方法吗?

答案 1 :(得分:1)

使用您的示例:

return (Check1 == false)   ||   (Check2 == false)   [ || etc ]

答案 2 :(得分:1)

对于您的特定情况,似乎您可能使用循环...假设这是来自Form或其他事件中的事件处理程序:

For Each ctrl As Control In Me.Controls

    Dim check As CheckBox = TryCast(ctrl, CheckBox)

    If check IsNot Nothing AndAlso check.Checked = False Then
        Return False
    End If

Next

Return True

编辑:经过进一步审核,我意识到这是基于伪代码而你实际上并没有使用复选框。 然而,我认为同样的方法适用。您可以非常轻松地将规则重构为一个实现自定义接口(IRule或类似)的单独类,或者具有一个返回true / false的委托列表,您将在检查模式中迭代它们。

答案 3 :(得分:0)

如果您连续多次检查并且不需要保留短路,您可以尝试这样的事情:

        bool isValid = true;
        isValid &= Condition1;
        isValid &= Condition2;
        isValid &= Condition3;
        if (!isValid)
            return false;

如果确实需要保留短路,可以将条件合并到一个大的if语句中。但是,如果有很多条件,我会更喜欢原始代码,多次返回,因为单个大的“if”可能会有点难看。

请注意,在后一种情况下,您只是侧面指标,因为逻辑分支实际上是相同的。如果条件检查没有副作用(我真的希望它们没有),那么我认为高的圈复杂度是一种误报,因为多次返回实际上只是表达复杂布尔验证逻辑的一种更易读的方式。 / p>

但是,如果条件全部是串联的,那么这是正确的。如果它们遍布整个代码,并且在检查之间发生了有意义的处理,则度量指示真正的复杂性(必须测试更多分支)。在这种情况下,您可以考虑是否可以将该方法逻辑分解为较小的,可单独测试的部分。