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

发布于 2024-08-23 16:51:57 字数 239 浏览 7 评论 0原文

我有一个包含许多条件语句的验证方法。基本上,

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

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

提前致谢。

I have a method for validation that has many conditional statements. Basically it goes

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

FxCop complains that the cyclomatic complexity is too high. I know that it is not best practice to have return statements in the middle of functions, but at the same time the only alternative I see is an ugly list of If-else statements. What is the best way to approach this?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

-残月青衣踏尘吟 2024-08-30 16:51:57

我不同意您的说法,即在方法中间使用 return 语句不是最佳实践。有些人为了得到一个单一的 return 语句而付出的努力是疯狂的——选择任何能产生最具可读性的代码。有时这将是单点返回,但我经常发现有一个“提前退出” - 并且最好有该返回,而不是使用 if 作为替代路径在代码中引入更多嵌套。根据经验,我喜欢最终不会缩进太远的方法:)

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

I disagree with your claim that it's not best practice to have return statements in the middle of methods. The lengths some people go to in order to have a single return statement is crazy - go with whatever produces the most readable code. Sometimes that will be a single point of return, but often I find there's an "early out" - and it's better to have that return than to introduce more nesting to the code with an if for the alternative path. I like methods that don't end up indented too far, as a rule of thumb :)

Having said that, is the method really nothing but checks? Are the checks independent? What variables do they require? Can you group them into smaller methods representing "areas" of the checks you're performing?

我要还你自由 2024-08-30 16:51:57

使用你的例子:

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

Using your example:

return (Check1 == false)   ||   (Check2 == false)   [ || etc ]
绝影如岚 2024-08-30 16:51:57

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

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 的委托列表,您可以将其作为检查模式的一部分进行迭代。

For your particular case, it seems you could probably use a loop... assuming this came out of an event handler in a Form or something:

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

Edit: Upon further review, I realize that this was based off of psuedocode and you weren't actually use check boxes. However, I think the same methodology applies. You could very easily refactor your rules into a separate class which implements a custom interface (IRule or similar), or have a list of delegates which return true/false which you would iterate over as part of your check pattern.

一口甜 2024-08-30 16:51:57

如果您连续进行多项检查并且不需要保留短路,您可以尝试如下操作:

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

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

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

然而,只有当条件全部串联时,这才是正确的。如果它们分布在整个代码中,并且在检查之间发生有意义的处理,那么该指标就表明了真正的复杂性(必须测试更多分支)。在这种情况下,您可能会考虑该方法是否可以在逻辑上分解为更小的、可单独测试的部分。

If you have several checks in a row and don't need to preserve short-circuiting, you might try something like this:

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

If you do need to preserve short-circuiting, you can consolidate the conditions into a large if statement. If there are a lot of conditions, however, I would prefer the original code, with multiple returns, as a single large 'if' could get a bit ugly.

Note that, in the latter case, you're merely side-stepping the metric, as the logical branching is actually the same. If the condition checks do not have side effects (and I really hope they don't), then I believe high cyclomatic complexity is a false alarm, as the multiple returns are really just a more readable way of expressing complex boolean validation logic.

This is only true, however, if the conditions are all in series. If they are spread throughout the code, with meaningful processing happening between checks, then the metric is indicating real complexity (more branches that must be tested). In this case, you might consider whether the method can be logically broken into smaller, individually testable pieces.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文