是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
当前回答
有人可能会说……如果在执行函数的任务之前必须满足多个条件,那么在满足这些条件之前不要调用函数:
而不是:
function doStuff(foo) {
if (foo != null) return;
}
Or
function doStuff(foo) {
if (foo !== null) {
...
}
}
在foo != null之前不要调用doStuff
if(foo != null) doStuff(foo);
这要求每个调用站点确保在调用之前满足调用的条件。如果有多个调用站点,则该逻辑最好放在单独的函数中、待调用函数的方法中(假设它们是一级公民)或代理中。
关于函数是否在数学上是可证明的这个话题,要考虑逻辑而不是语法。如果一个函数有多个返回点,这并不意味着(默认情况下)它在数学上不可证明。
其他回答
拥有多个出口点本质上与使用GOTO是一样的。这是不是件坏事取决于你对迅猛龙的看法。
我可能会因此被讨厌,但理想情况下,我认为根本不应该有return语句,函数应该只返回它最后一个表达式,在完全理想的情况下,应该只包含一个。
所以不
function name(arg) {
if (arg.failure?)
return;
//code for non failure
}
而是
function name(arg) {
if (arg.failure?)
voidConstant
else {
//code for non failure
}
不是表达式的if语句和return语句对我来说是一种非常可疑的实践。
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;
}
I always avoid multiple return statements. Even in small functions. Small functions can become larger, and tracking the multiple return paths makes it harder (to my small mind) to keep track of what is going on. A single return also makes debugging easier. I've seen people post that the only alternative to multiple return statements is a messy arrow of nested IF statements 10 levels deep. While I certain agree that such coding does occur, it isn't the only option. I wouldn't make the choice between a multiple return statements and a nest of IFs, I'd refactor it so you'd eliminate both. And that is how I code. The following code eliminates both issues and, in my mind, is very easy to read:
public string GetResult()
{
string rv = null;
bool okay = false;
okay = PerformTest(1);
if (okay)
{
okay = PerformTest(2);
}
if (okay)
{
okay = PerformTest(3);
}
if (okay)
{
okay = PerformTest(4);
};
if (okay)
{
okay = PerformTest(5);
}
if (okay)
{
rv = "All Tests Passed";
}
return rv;
}
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
是的,有:
The single exit point gives an excellent place to assert your post-conditions. Being able to put a debugger breakpoint on the one return at the end of the function is often useful. Fewer returns means less complexity. Linear code is generally simpler to understand. If trying to simplify a function to a single return causes complexity, then that's incentive to refactor to smaller, more general, easier-to-understand functions. If you're in a language without destructors or if you don't use RAII, then a single return reduces the number of places you have to clean up. Some languages require a single exit point (e.g., Pascal and Eiffel).
这个问题通常被提出为多个返回或深度嵌套的if语句之间的错误二分法。几乎总有第三种解决方案,它是线性的(没有深度嵌套),只有一个出口点。
更新:MISRA的指导方针显然也提倡单次退出。
需要澄清的是,我并不是说拥有多个回报总是错误的。但如果有其他等价的解决方案,有很多很好的理由选择单一回报的方案。