控制结构逻辑的正确顺序(真/假,假/真)?

时间:2008-10-23 11:56:55

标签: language-agnostic conditional logic control-structure

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

首先检查最可能的情况似乎更自然,但我觉得有些控制结构不起作用,除非他们检查所有错误的东西以得到真实的东西(逻辑演绎?)

很难适应这种“负面”观点,我更倾向于采取更积极的态度,假设一切都是真的:)

10 个答案:

答案 0 :(得分:13)

在McConnell的 Code Complete 中对这个主题进行了很好的讨论。这是我强烈推荐的一本书。无论如何,相关讨论在第一版的第706-708页或第6页。第二版749-750(谢谢基座)。从那本书:

  

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

答案 1 :(得分:6)

除了条件语句的值之外,还有一些事情需要考虑。例如,如果代码块的大小明显不同,您可能需要先放置小块,以便更容易看到。 (如果较大的块非常大,则可能需要重构,或者可能需要将其拉出到单独的方法中。)

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

在这种情况下,是的,有些语言会在其中一部分为假时停止评估表达式。如果在代码中包含某种定义的逻辑,这一点很重要:如果您的语言评估整个表达式,您应该这样做:

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

而不是:

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

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

答案 2 :(得分:3)

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

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

答案 3 :(得分:3)

答案 4 :(得分:2)

我的目标是以最小化读者必须接受的信息量的方式构建我的条件。有时,更容易测试否定证明积极的事情:

一个例子 - 看一个2个日期的周期是否与另一个2个日期相交的测试更容易写成2个周期的交叉点的测试

答案 5 :(得分:2)

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

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

    if(arg == null){ 
      throw new IllegalArgumentException();  // harsh (correct)
    }
    // or 
    if(arg == null){
        arg = "";  // forgiving (lazy)
    }

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

    if(condition1 && condition2) {
        ...
    } else {
        ...
    }

我通常更喜欢

    if(condition1) {
        if(condition2) {
            ...
        } else {
            ...
        }
    } else {
        ...
    }

这种方法更容易设置断点,它使逻辑变得更加一致。

我避免否定;而不是

    if(! condition) {
        ...a...
    } else {
        ...b...
    }

事情更好地重新安排到

    if(condition) {
        ...b...
    } else {
        ...a...
    }

最后,所有返回布尔结果的方法都应该有一个“肯定”的名称,表明结果意味着什么:

    boolean checkSomething(Something x){ ... }     // bad -- whats the result?
    boolean isSomethingInvalid(Something x){ ... } // better, but ...
    boolean isSomethingValid(Something x){ ... }   // best, no "mental negation"

答案 6 :(得分:1)

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

答案 7 :(得分:0)

要么/或者。我通常使用'否定'方法。

if(!something) {

}

答案 8 :(得分:0)

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

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

答案 9 :(得分:0)

(上下文:Java)

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

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

READABILITY2:首先是肯定断言,因为更容易不注意否定符号

MAKING SENSE:使用Assert.blabla()断言方法的所有前提条件,并仅将条件用于该方法。