【问题标题】:Correct order for control structure logic (true/false, false/true)?控制结构逻辑的正确顺序(真/假、假/真)?
【发布时间】:2010-09-18 18:31:35
【问题描述】:

我是编程新手,想知道是否有正确的方法来订购您的控制结构逻辑。

首先检查最可能的情况似乎更自然,但我觉得某些控制结构将无法工作,除非他们检查所有错误的东西以得出正确的结果(逻辑推论?)

很难适应这种“消极”的观点,我更喜欢更积极的观点,假设一切都是真的:)

【问题讨论】:

    标签: language-agnostic conditional logic control-structure


    【解决方案1】:

    McConnell 的 Code Complete 中就这个话题进行了精彩的讨论。这是一本我强烈推荐的书。无论如何,相关讨论在第一版或 pg 的第 706-708 页上。第二版的 749-750(感谢 plinth)。从那本书:

    安排测试,以便 最快和最有可能是真的是 先执行。应该很容易 通过正常情况,如果 有效率低下,他们应该 正在处理异常。

    【讨论】:

    • 完全同意,将大部分时间执行的放在最上面,这样分支就最小化了。
    • @chakrit:编译器可以(并且确实)对块进行重新排序,因此位于顶部并不能保证更少的分支。在 gcc 上,请参阅 __builtin_expect 的文档,您可以使用它来告诉它哪个结果更有可能。
    • @plinth,非常感谢。我已经编辑了答案以添加该信息。
    • @wdm,非常明智的投资。
    【解决方案2】:

    除了条件语句的值之外,还有一些事情需要考虑。例如,如果代码块的大小明显不同,您可能希望将小块放在第一位,以便更容易看到。 (如果较大的块真的很大,它可能需要重构,或者可能被拉到一个单独的方法中。)

    if( condition is true ) {
        do something small;
    } else { 
        do something;
        and something else; 
        . . .
        and the 20th something;
    }
    

    在条件范围内,是的,有些语言会在表达式的一部分为假时停止计算表达式。如果您在代码中包含某种 is-defined 逻辑,请务必记住这一点:如果您的语言计算整个表达式,您应该这样做:

    if( variable is defined ) {
        if( variable == value ) {
            ...
        }
    }
    

    而不是这样:

    if( (variable is defined) && (variable == value) ) {
         ...
    }
    

    我认为没有一种“正确”的方式来设计您的条件。如果您在一家有编码标准的公司工作,您应该检查是否包含在标准中。 (我工作的最后一个地方定义了合理数量的标准,但没有指定如何编写条件逻辑。)

    【讨论】:

      【解决方案3】:

      一般情况下,我会先检查意外的项目,这迫使我处理程序的异常流程。

      这样,我可以在开始“设置”正常程序流程之前抛出异常/中止操作。

      【讨论】:

      • 通常也是最短的 - 这使得结构更易于阅读: if(condition) { ...short... } else { ...long... }
      【解决方案4】:

      【讨论】:

        【解决方案5】:

        在大多数情况下,可读性比执行速度更重要。因此我尝试 使用以下方法进行优化以便于理解:

        所有“断言”检查都是预先完成的。这保证了所有错误的情况在一开始就得到处理。这对于空指针检查尤其重要,例如

        如果(arg == null){ 抛出新的 IllegalArgumentException(); // 苛刻(正确) } // 要么 如果(arg == null){ 参数 = ""; // 宽容(懒惰) }

        接下来,我尝试仅在每个 if 语句中检查 1 个条件。而不是

        如果(条件1 && 条件2){ ... } 别的 { ... }

        我一般比较喜欢

        如果(条件1){ 如果(条件2){ ... } 别的 { ... } } 别的 { ... }

        这种方式更容易设置断点,逻辑更清晰。

        我避免否定;而不是

        如果(!条件){ ...一种... } 别的 { ...b... }

        事情最好重新安排

        如果(条件){ ...b... } 别的 { ...一种... }

        最后,所有返回布尔结果的方法都应该有一个“肯定”的名称来表明结果的含义:

        boolean checkSomething(Something x){ ... } // 不好——结果是什么? boolean isSomethingInvalid(Something x){ ... } // 更好,但是 ... boolean isSomethingValid(Something x){ ... } // 最好,没有“心理否定”

        【讨论】:

        • 坦率地说,我不同意这一点。断言预先检查,通常是的。但是,为了避免出现复合逻辑条件而使用大量嵌套的 if 语句使代码混乱似乎会降低可读性,恕我直言。
        • @tvanfosson,我同意。深度嵌套的 if 语句可能极难阅读和/或破译——这意味着维护程序员更有可能意外地以错误的方式修改测试。
        • @tvanfosson:是的,条件嵌套不应超过深度 2 或 3。
        【解决方案6】:

        我的目标是以某种方式构建我的条件,以尽量减少读者必须接受的信息量。有时更容易测试负面以证明正面:

        一个例子 - 测试 2 个日期的周期是否与另一个 2 个日期的周期相交更容易编写为两个周期不相交的测试

        【讨论】:

          【解决方案7】:

          如果这是一个简单的“是”或“错误”问题,那么我通常会构造一些东西,以便错误处理分支是 else 子句。如果这是一个是或否的问题(即两个分支都不是错误),那纯粹是对感觉更自然的判断要求。如果在代码的核心可以执行之前必须进行很多测试,我通常会尝试构建一些东西,以便首先出现负面测试并以某种方式跳过后面的代码(从函数返回,中断或继续一个循环)。

          【讨论】:

            【解决方案8】:

            要么/要么。不过,我通常使用“否定”方法。

            如果(!某事) {

            }

            【讨论】:

              【解决方案9】:

              这有点超出了问题的范围,但通常您也希望您的方法快速失败。出于这个原因,我倾向于在方法的顶部进行所有的参数验证,即使在代码的后面部分我不会使用该参数。这会损害可读性,但仅在方法非常长的情况下(必须滚动屏幕才能看到它)。当然,这本身就是一种代码味道,而且往往会被重构。

              另一方面,如果检查不简单,我将把它传递给另一个方法,无论如何都要检查它,我不会重复代码来检查当前方法。与大多数事情一样,存在平衡。

              【讨论】:

                【解决方案10】:

                (上下文:Java)

                READABILITY1:解析为较小代码块的条件优先

                if (condition) {
                  smallBlock();
                } else {
                  bigBlockStart();
                  ........
                  bigBlockEnd();
                }
                

                READABILITY2:肯定断言优先,因为它更容易不注意到否定符号

                有意义:使用 Assert.blabla() 断言方法的所有先决条件,并仅对方法的作用使用条件。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-03-30
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-02-10
                  • 1970-01-01
                  • 2014-02-17
                  • 2015-12-05
                  • 2016-01-31
                  相关资源
                  最近更新 更多