Is a coding style principle - e.g. the single-exit principle
People who still hark at whether to a single-exit or multiple exit are still stuck in the late 1960's. Back then, such a discussion was important since we were in the infancy of structured programmer, and there was a quite numerous camp proclaiming that the findings behind Bohm-Jacopini Structured Program Theorem weren't universally applicable to all programming constructs.
It is something that should have been settled long ago. Well, it has been settled (almost 4 decades to be precise, in both Academia and the industry), but people (those who are absolutely pro or against) have not been paying attention.
As for the rest of my answers, it's all relative (what isn't in software?):
Yes. Most of the time for the general case, with caveats specific to edge cases and language-specific programming constructs.
Always, or just sometimes?
Most of the time.
How much difference does it really make?
Depends.
Readable code vs unreadable code. Increased complexity (which we should know by now increases the probability of introducing errors) vs simpler complexity (and ergo, smaller probability of errors.) Languages whose compilers do not add an implicit return (say, Pascal, Java or C#) and those that default to int (C and C++).
In the end, it is a skill honed with man/hours behind a keyboard. Sometimes, it's ok to have multiple return statements, like here (in some Pascal'esque pseudocode):
function foo() : someType
begin
if( test1 == true )
then
return x;
end
doSomethignElseThatShouldnHappenIfTest1IsTrue();
return somethingElse();
end;
The intent is clear, and the algorithm is small enough and uncomplicated enough that it does not warrant the creation of a 'flag' variable that holds the eventual return value used in a single return point. The algorithm could be in error, but its structure is simple enough that the effort in detecting an error is (most likely) negligible.
Sometimes it's not (here using a C-like pseudocode):
switch(someVal)
{
case v1 : return x1;
case v2 : return x2:
case v3 : doSomething(); // fall-through
case v4: // fall-through
case v5: // fall-through
case v6: return someXthingie;
...
...
default:
doSomething(); // no return statement yet
}
Here, the algorithm does not have a simple structure, and the switch statement (a C-style one) allows fall-through steps which may or may not done intentionally as part of the algorithm.
Maybe the algorithm is correct, but poorly written.
Or maybe, by external forces beyond the programmer's ability, this is the actual (and correct) representation of a legitimately needed algorithm.
Maybe it is wrong.
To uncover the truth of any of this requires far more effort than in the previous example. And herein lies something I strongly believe (mind you that I have no formal studies to back this up):
Assuming a code snippet that is assumed to be correct:
Multiple return statements increase the readability and simplicity of such a code snippet, if the snippet represents a simple algorithm with an inherently simple flow structure. By simple, I don't mean small, but I mean inherently comprehensible or self-evidence, that which does not require disproportionate reading effort (nor induce people to vomit, curse someone's mother, or swallow a bullet when they have to read it.)
A single return statement increases the readability and simplicity of such a piece of code if the return value is either calculated throughout the execution of the algorithm or if the steps in the algorithm responsible for calculating it can be grouped together in one location within the algorithm's structure.
A single return statement decreases the readability and simplicity of such a piece of code if it requires assignments to one or more flag variables, with the locations of such assignments not being uniformly located throughout the algorithm.
Multiple return statements decrease the readability and simplicity of such a piece of code if the return statements are not uniformly distributed across the algorithm, and if they demarcate mutually exclusive blocks of code that are not uniform in size or structure among themselves.
This is closely related to the complexity of a code snippet in question. And this in turn is related to cyclomatic and halstead complexity measures. From this, one could observe the following:
The larger the size of a subroutine or function, the larger and more complex its internal control flow structure is, and the greater the probability you'll face a question of whether to use multiple or single return statements.
The conclusion of this is: keep your functions small doing one thing and only one thing (and doing it well). If they exhibit nominally small cyclomatic and halstead complexity metrics, not only are they bound to be most likely correct and be implementation of tasks that are comprehensible, their inner structures will also be relatively self-evident.
Then, and only then you can quite easily and without losing much sleep, you can decide whether to use a single return and multiple returns without running much risks of introducing errors with either choice.
One could also look at all of this and suggest that when people struggle with the issue of single returns or multiple returns, it is because - either by inexperience, stupidity or lack of work ethics - they don't write clean code and tend to write monstrous functions with complete disregard of cyclomatic and halstead measures.
single-exit principledoes not really apply to C++ because of RAII – Loki Astari Oct 6 '11 at 14:44break,gotoorreturndo. IOW single exit isn't an absolute in C++, but that's pretty much my view of it in C and most other languages anyway. But it's still relevant in a non-strict sense. – Steve314 Oct 7 '11 at 5:37