是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?

或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?


当前回答

正如Kent Beck在《实现模式》中讨论保护子句时指出的那样,使一个例程具有单一的入口和出口点……

是为了防止可能的混淆 当你在许多地方跳来跳去 同一例程中的位置。这让 当应用到FORTRAN或 汇编语言程序 有大量的全球数据,甚至 理解哪些语句是 执行是一项艰苦的工作……使用小方法和大部分本地数据,它是不必要的保守。”

我发现用保护子句编写的函数要比一长串嵌套的if then else语句容易理解得多。

其他回答

一般来说,我尝试从一个函数中只有一个出口点。然而,有时这样做实际上会创建一个比必要的更复杂的函数体,在这种情况下,最好有多个出口点。它确实需要基于结果的复杂性进行“判断”,但目标应该是在不牺牲复杂性和可理解性的情况下尽可能减少出口点。

I lean towards using guard clauses to return early and otherwise exit at the end of a method. The single entry and exit rule has historical significance and was particularly helpful when dealing with legacy code that ran to 10 A4 pages for a single C++ method with multiple returns (and many defects). More recently, accepted good practice is to keep methods small which makes multiple exits less of an impedance to understanding. In the following Kronoz example copied from above, the question is what occurs in //Rest of code...?:

void string fooBar(string s, int? i) {

  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

我意识到这个例子有点做作,但我很想把foreach循环重构成一个LINQ语句,然后将其视为一个保护子句。同样,在一个人为的例子中,代码的意图并不明显,someFunction()可能会有一些其他副作用,或者结果可能会在代码的// Rest中使用....

if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;

给出以下重构函数:

void string fooBar(string s, int? i) {

  if (string.IsNullOrEmpty(s) || i == null) return null;
  if (someFunction(s, i).Any(r => !r.Passed)) return null;

  // Rest of code...

  return ret;
}

我曾经使用过糟糕的编码标准,强迫你使用单一的退出路径,如果函数不是琐碎的,结果几乎总是非结构化的意大利面条——你最终会遇到许多中断和继续。

我相信多次返回通常是好的(在我用c#编写的代码中)。单返回样式是从C语言中保留下来的,但是您可能没有用C语言编写代码。

在所有编程语言中,没有法律要求一个方法只有一个退出点。有些人坚持这种风格的优越性,有时他们把它提升为“规则”或“法律”,但这种信念没有任何证据或研究支持。

在C代码中,多个返回样式可能是一个坏习惯,资源必须显式地去分配,但Java、c#、Python或JavaScript等语言具有自动垃圾收集和try. finally块(以及在c#中使用块)等构造,并且这个参数不适用-在这些语言中,需要集中的手动资源回收是非常罕见的。

在某些情况下,单个返回值可读性更好,而在某些情况下则不是这样。看看它是否减少了代码行数,使逻辑更清晰,或减少了大括号、缩进或临时变量的数量。

因此,根据你的艺术感受使用尽可能多的返回,因为这是一个布局和可读性问题,而不是技术问题。

我在我的博客上详细地讨论过这个问题。

由于错误处理,您已经隐式地拥有多个隐式返回语句,因此要处理它。

但是,就像编程中的典型情况一样,有支持和反对多次返回实践的例子。如果它能让代码更清晰,那就这样做。使用许多控制结构会有所帮助(例如case语句)。