编程风格:如果不满足保护条件,您应该提早返回吗?

Joh*_*ley 30 language-agnostic program-flow control-flow

我有时想知道的一件事是下面显示的两个中哪个更好(如果有的话)?它是更好立即返回,如果监护条件尚未满足,或者如果保护条件,你应该只能做其他的东西满意吗?

为了参数,请假设保护条件是一个返回布尔值的简单测试,例如检查元素是否在集合中,而不是通过抛出异常可能影响控制流的东西.还假设方法/函数足够短,不需要编辑器滚动.

// Style 1
public SomeType aMethod() {
  SomeType result = null;

  if (!guardCondition()) {
    return result;
  }

  doStuffToResult(result);
  doMoreStuffToResult(result);

  return result;
}

// Style 2
public SomeType aMethod() {
  SomeType result = null;

  if (guardCondition()) {
    doStuffToResult(result);
    doMoreStuffToResult(result);
  }

  return result;
}
Run Code Online (Sandbox Code Playgroud)

unb*_*eli 37

我更喜欢第一种风格,除了在不需要它时我不会创建变量.我这样做:

// Style 3
public SomeType aMethod() {

  if (!guardCondition()) {
    return null;
  }

  SomeType result = new SomeType();
  doStuffToResult(result);
  doMoreStuffToResult(result);

  return result;
}
Run Code Online (Sandbox Code Playgroud)

  • @Mike:实际上,正确的标签将是"与语言无关的",关键是问题不是关于指针语义或类似的语言细节,而是关于是否早期或晚期从方法/函数返回. (6认同)
  • @Tim:语法可能是Java,但问题不在于Java.这是一般的命令式编程.(它几乎立即应用于C#,C和C++,并对Python,Perl,Ruby,Tcl等进行了一些更多的语法更改.)它非常强烈不可知. (4认同)
  • 啊.我不使用Java,所以我认为它是C++.抱歉.问题上的"Java"标签会有所帮助. (2认同)

Eig*_*uru 27

在80年代后期接受过杰克逊结构化编程培训后,我根深蒂固的哲学始终是"一个功能应该只有一个入口点和一个单一的出口点"; 这意味着我根据Style 2编写代码.

在过去的几年里,我逐渐意识到用这种风格编写的代码往往过于复杂,难以阅读/维护,我已经切换到了Style 1.

谁说老狗不能学习新技巧?;)


Mik*_*one 14

样式1是Linux内核间接推荐的.

来自http://www.kernel.org/doc/Documentation/CodingStyle,第1章:

现在,有些人会声称有8个字符的缩进会使代码向右移动太远,并且难以在80个字符的终端屏幕上阅读.答案是,如果你需要超过3个级别的缩进,你仍然会被搞砸,并且应该修复你的程序.

样式2增加了缩进级别,因此不鼓励.

就个人而言,我也喜欢风格1.样式2使得在具有多个防护测试的功能中匹配闭合括号变得更加困难.


tan*_*ius 6

我不知道守卫在这里是否是正确的词.通常,不满意的防护会导致异常或断言.
但除此之外,我会选择样式1,因为它让代码更清晰.你有一个只有一个条件的简单例子.但是在许多条件和风格2中会发生什么?这导致很多嵌套的ifS或巨大的,如果条件(有||,&&).我认为,只要你知道可以,最好从方法返回.
但这肯定是非常主观的^^


Oli*_*ops 5

如果使用.net-Reflector挖掘.net-Framework,您将看到.net程序员使用样式1(或者unbeli可能已经提到的样式3)。上面的答案已经提到了原因。也许另一个原因是使代码更易于阅读,简洁和清晰。这种样式最多使用的是检查输入参数时,如果您编写一种frawework / library / dll,则必须总是这样做。首先检查所有输入参数,然后再使用它们。


bug*_*yci 5

马丁·福勒(Martin Fowler)将此重构称为: “用警卫条款代替嵌套条件”

if / else语句还会带来圈复杂度。因此更难测试案例。为了测试所有if / else块,您可能需要输入很多选项。

如果有任何保护子句,则可以先对其进行测试,然后以更清晰的方式处理if / else子句中的实际逻辑。