【问题标题】:Coding style... error condition first or last?编码风格...首先还是最后一个错误条件?
【发布时间】:2008-11-24 21:22:03
【问题描述】:

就排序而言,一般来说哪个更好?您将故障条件放在顶部还是底部?

if (noProblems == true) {
    // do stuff
} else {
    // deal with problem
}

if (noProblems == false) {
    // deal with problem
} else {
    // do stuff
}

【问题讨论】:

    标签: coding-style


    【解决方案1】:

    我喜欢首先消除错误情况 - 并尽早从函数返回,以便“快乐路径”保持未嵌套,例如

    if (some error condition)
    {
        //handle it
        return;
    }
    //implicit else for happy path
    ...
    

    如果很容易确定通往幸福道路的条件,那么一定要把那个子句放在第一位(感谢 Marcin!)

    【讨论】:

    • 好答案。这种模式通常被称为“保护子句”。
    • 对不起,我完全不能同意这一点。请在下面查看我的答案。
    【解决方案2】:

    也许这取决于语言约定或其他因素,但我觉得名义上的情况应该在顶部,分支应该包含例外情况。它使代码更容易阅读。当有许多异常情况时尤其如此,并且在大多数情况下都有。您可以很容易地假设作者希望大多数时间都采用这条特定的路径,并且通过这种方式更容易理解代码。

    来自“代码完整,第 2 版”第 15.1 节:

    通过将最常见的情况放在首位,您可以最大程度地减少人们为找到常见情况而必须阅读的异常情况处理代码的数量。 您可以提高效率,因为您可以最大限度地减少代码为查找最常见情况而执行的测试次数。

    【讨论】:

    • 您可能还想阅读第 17.1 节,其中说:“使用保护子句(提前返回或退出)来简化复杂的错误处理”
    • 我同意在很容易确定导致幸福道路的条件的情况下,将编辑我的答案以反映您的额外智慧
    【解决方案3】:

    如果它有 1 或 2 行并且提前返回,我会将它放在顶部 - 特别是如果它位于函数的开头。这几乎读起来像一份合同。否则,我会遵循“消极条件之前的积极条件”规则。

    【讨论】:

      【解决方案4】:

      这取决于你更清楚什么。我的意思是,更有意义的是,noProblems 具有真值或假值。

      例如,对于 isDeviceEnabled(),我总是会检查结果是否为真,因为“启用”隐含一个正值。对于隐含的负值,我们可以检查例如“isMemoryAvailable()”,可能是因为您只需要检查没有更多空间容纳新对象/数组或其他数据。

      【讨论】:

        【解决方案5】:

        这是一种非常个人化的决定,但我倾向于将我的错误条件放在首位,假装将类似代码组合在一起。也就是说,如果我做了某事,但它失败了,那么检查失败实际上是做某事的一部分;如果我在我的代码的开头放置基于它的失败检查和操作,我已经将我的操作和对该操作的复杂响应组合在一起(假设失败结果实际上是一个比返回更复杂的情况成功)。

        【讨论】:

          【解决方案6】:

          第一个对我来说似乎更可取,因为它避免了条件中的双重否定。

          除此之外,你已经构建了一些你不能真正做到的东西

          // do stuff
          

          在你之后

          // deal with problem
          

          除此之外,一个似乎和另一个一样好。

          【讨论】:

            【解决方案7】:

            try/catch 一样,我执行正常流程,然后处理异常情况。

            这并不意味着错误检查/清理不会首先发生,但前提是我不相信传递给我的内容。

            例如,

            if (foo is null) then
                // bail
            end if
            
            if (bar == foo) then
                // foo hasn't been changed... print the regular report
            else
                // foo has changed, run the reconciliation report instead.
            end if
            

            我喜欢快乐的故事像直线一样流动,而不幸的故事则顺其自然。

            【讨论】:

              【解决方案8】:

              为什么不从函数中创建一个退出点并在那里进行适当的清理而不是多次返回...

              DWORD bRetVal= TRUE; if(foo is null) { bRetVal = FALSE; goto Error; } else { // do something } Exit: return bRetVal;

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-08-10
                • 2022-09-23
                • 1970-01-01
                • 1970-01-01
                • 2013-02-20
                相关资源
                最近更新 更多