1

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

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

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

4

10 回答 10

13

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

安排测试,以便首先执行最快且最有可能正确的测试。正常情况下应该很容易掉线,如果效率低下,他们应该在处理异常。

于 2008-10-23T12:07:20.660 回答
6

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

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) ) {
     ...
}

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

于 2008-10-23T12:06:49.197 回答
3

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

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

于 2008-10-23T12:04:25.223 回答
3

另请参阅此问题:

在 IF 块中放什么,在 ELSE 块中放什么?

于 2008-10-23T12:29:27.717 回答
2

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

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

于 2008-10-23T12:09:24.340 回答
2

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

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

    如果(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){ ... } // 最好,没有“心理否定”
于 2008-10-23T13:01:27.730 回答
1

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

于 2008-10-23T12:18:22.650 回答
0

两者任一。不过,我通常使用“否定”方法。

如果(!某事){

}

于 2008-10-23T12:00:12.860 回答
0

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

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

于 2008-10-23T13:17:04.857 回答
0

(上下文:Java)

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

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

READABILITY2:肯定的断言是第一位的,因为它更容易不注意到否定符号

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

于 2008-10-23T13:29:31.043 回答