> Having a single return point is structured -- which gives
> a simple, uniformity of shape (check: ‘Notes On Structured
> Programming’/ewd249; Dijkstra; 1970).
Structured programming and this rule specifically is baked into Java. This isn't surprising given that Java was created 20 years later. It's implicit. Doing it explicitly is redundant and has provides no benefit.
Like I said before, the reasoning that people give for doing this is based on older languages that allow for things that Java does not.
> It should be the
> default, unless the code can be made even simpler
> otherwise.
It's almost always simpler otherwise. Tree shaped methods are easier to follow than onion shaped methods which is why the compiler can verify tree shaped methods and not onion shaped methods.
I've worked with reams of code written in single return style. It's much buggier and harder to understand than multiple return style code. You are just substituting an assignment to variable (a vague operation) for the return keyword (a clear operation.) The variable is completely extraneous.
Yes, you know there is one return at the end. Why is that important? It tells you nothing about what is returned. You still have to do the look through the code to figure out what value the variable will be i.e. what will be returned. And often this is more difficult than it is to determine than in the equivalent multi return code for multiple reasons. For example consider the following snippets:
boolean isFoo()
{
for (item : things) {
if (item.hasBar()) return true;
}
// more code ...
}
boolean isFoo()
{
boolean returnValue = false;
for (item : things) {
if (item.hasBar()) returnValue = true;
}
// more code ...
return returnValue;
}
In the first example, I can see immediately that if one of the items has bar, the method returns true. If that's all the information I need, I'm done. In the second, all I know is that returnValue is set to true at that point in the method. I might think that probably means the method returns true in that case but I can't be sure. I must look through the rest of the code or risk error. Most of the time it will be but I've seen cases where it would set later. I often found this kind of logic while hunting down bugs because the later assignment to the return variable was in error.
And, on a side note, any decent IDE is going to allow the return keyword to be syntax highlighted. The simple assignment won't be. I seriously don't understand why people continue to insist that this unequivocally bad practice is good.
Consider this:
boolean isFoo()
{
for (item : things) {
if (item.hasBar()) return true;
}
if (useDefaultFoo) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("using default foo: " + defaultFoo);
return defaultFoo; // real error I've seen
}
} else {
return false;
}
}
boolean isFoo()
{
boolean returnValue = false;
for (item : things) {
if (item.hasBar()) returnValue = true;
}
if (useDefaultFoo) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("using default foo: " + defaultFoo);
returnValue = defaultFoo; // real error I've seen
}
}
return returnValue;
}
Both are wrong. The first doesn't compile, the second does. By using return variables, you are impeding the compiler's ability to catch mistakes. I can't count the number of times using multiple returns has saved me from errors.