是否应根据案件的稀有性或处理困难来安排陈述?


18

在我现在正在编写的一些代码中,我有类似以下内容:

if (uncommon_condition) {
    do_something_simple();
} else {
    do();
    something();
    long();
    and();
    complicated();
}

我的一部分认为“编写的方式很好。应该先处理简单的案例,然后再处理更复杂的案例。” 但是另一部分说:“不!else代码应该放在之下if,因为它if是用于处理异常情况,else并且用于处理所有其他情况。” 哪个是正确的或更可取的?


4
通过简单/条件易懂的顺序!其余的可以通过优化器,分支预测器和重构来解决。
Marjan Venema 2014年

这就是为什么我们获得巨额薪水的原因:做出这些困难的决定。

Answers:


24

通过其执行可能性的顺序。最常见,最可能等的条件应优先考虑。

“处理它们的困难”应通过代码结构,抽象等处理。在示例中,else块可以重构为单个方法调用。您希望if子句处于相同的抽象级别。

if ( ! LotteryWinner ) {
    GoToWorkMonday();
} else {
    PlanYearLongVacation();
}

6
为了性能我可能会同意。但是话又说回来,大多数优化器和分支预测器完全有能力解决这一问题。为了提高可读性,我可能会同意,如果最有可能的情况比不多的情况有更多行。但是对我来说,这将更快地表明需要提取一种方法而不是使用一种方法not。我个人将专注于避免not条件。与“积极”条件相比,它们已被证明可以诱导更多的认知负担来理解,并且不利于代码的可读性/可理解性。我倾向于只在警卫声明中使用它们。
Marjan Venema 2014年

2
@MarjanVenema,我可以看到您关于“不”说的观点。但是双重否定是真正的“不是” WTF。前几天,我在我们的代码中遇到了这个问题doesNotAllowxxFiles = false。够糟糕,但是要这么做if(! doesNotAllowxxFiles)
雷达波2014年

是的,双重否定词,否定词与and和/或or(sic!)组合,以及否定词与方法/ var组合在一起,且Not的名字,每次都会使我的大脑处于扭曲状态:-)
Marjan Venema 2014年

如果您发现自己无法理解发生的事情,我认为这样做通常是有用的:simpleBool =(!(complexBool || randomfFlag))&&!randomFlag
TruthOf42 2014年

2
我会同意你的看法,除了警卫条款(在IF语句的THEN部分中总是有例外条件,而不是共同条件)。
罗伯特·哈维

5

尝试增强可读性。一种方法是将较长的代码块放入其他部分。

if (s == null)
     // short code
else 
     // long 
     // code
     // block

if (s != null)
    // long
    // code
    // block
else
    // short code

2
为什么它更具可读性?我认为两者在可读性方面没有区别
John Demetriou

2
@JohnDemetriou如果那么短,则其他可见。人们首先扫描结构,然后为其分配含义。没有Else的代码与带有Else的代码是不同的,因此使Else更加可见更容易理解。(所有其他条件都相同,在不下雨的星期二等)

4

我没有听说过这样的固定规则,但我遵循这样

if(usual)
{
(more often)
}
else (unusual)
{
(rarely occurring)
}

但是,如果两者都具有相同的功能,但属性不同,那么最好先处理不寻常的问题,然后再处理常规问题,这样您就可以保存一条指令。


if(x == 0)  // 1
  {x = 1;}  // 2
else
  {x = 2;}  // 3

对于以上代码,汇编代码将如下所示:

1. 000d 837DFC00        cmpl    $0, -4(%ebp)
   0011 7509            jne .L2

2. 0013 C745FC01        movl    $1, -4(%ebp)
   001a EB07            jmp .L3

    .L2:
3.001c C745FC02         movl    $2, -4(%ebp)

        .L3:

如果内部条件为true,则流量为1-> 2(4个指令)
如果内部条件为false,则流量为1-> 3(3个指令)

因此最好将异常或很少发生的事件置于部分正常条件下,否则我们每次可以保存一条指令;-)


2

我发现完全相反的模式导致更容易阅读代码,并减少或消除了嵌套的if语句。我将其称为“手套”模式。(在讲故事,一战书将是一系列具有完成最后的任务之前要成功满足挑战)通过处理您的优势情况下第一,你让你的代码的主体是干净简洁:

if(gauntlet_1){ handle the first gauntlet condition }; 
if(gauntlet_2){ handle the second gauntlet condition };
...
// All preconditions (gauntlets) have been successfully handled

// Perform your main task here

因此,“句柄手套”部分要么必须是控制权的转移,例如throw或return语句,要么必须是要纠正错误。某些人对一系列if ... return语句不满意,但我不认为它确实使代码更容易阅读,如您所说。

1
如果gauntlet条件导致函数无法成功执行,它将立即返回错误。如果可以处理gauntlet条件,请在可能的情况下在输入代码主体之前执行此操作。我主要是尝试避免嵌套的IF语句,根据我的经验,这是晦涩难懂且难以调试编码错误的主要原因之一。
拜伦·琼斯

0

对我来说,更多的是条件,而不是它们执行的代码的复杂性。您需要对条件进行排序,以便先捕获异常条件,然后再捕获更常见的条件。另外,如果else代码真的很长而且很复杂,我可能会为此做一个子程序,以使条件部分对读者显而易见。


-1

我没有固定的规则,但通常我会遵循此规则-首先,请考虑在哪里有遗漏的设计模式将其排除在外。如果不是,我将其编写为使最清楚地理解if中的条件。即,避免双重负片等。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.