Although it’s quite short, the most popular section of Java for small teams (as judged by the number of comments on reddit) is the “bad advice” section at the end.
The idea of this section was to capture some of the “negative value” advice and rules that are sometimes followed and enforced without question. If you’ve ever been in the situation where you’ve been asked to do stupid things in the name of “best practice” you can understand its appeal.
I had Hungarian notation imposed on me in the past and in my early career forced myself to follow the single exit point rule before finally seeing sense.
As a recovered single-exit-point programmer I thought I had a pretty good grasp of arguments for and against it, but this item generated some interesting community feedback with points I hadn’t considered.
Single exit point rule recap
The single exit point rule is the idea that a method or function should only ever return from one location. The idea has been around since before Java existed and is an enforced constraint in some languages.
It sounds pretty sensible. If a method only ever exits from one place it must be easier to understand right?
If your method is 100 lines long knowing it can only exit right at the end probably is useful. But we don’t write 100 line methods any more.
What happens if you tell a Java programmer that all methods should have only one return statement?
They will probably write something like this.
Doesn’t look too bad does it?
How about if we don’t instruct them to have a single exit point?
You’ll probably get something like this.
What’s wrong with it?
In fact it’s a little clearer than the single exit point method.
The difference is minor, but in the multi exit version it is slightly clearer what happens when
x isn’t greater than 0 as the returned value is declared at the point of return. In the single exist point version we have to scan up a few lines to the declaration.
In the single exit point version we also have a tiny bit of bloat in the form of the extra
retVal variable. We assign to it and then over-write which is a little ugly.
Other versions of this logic using both single and multiple exit points are possible.
For example if we add an else statement we can make the single exit version a little clearer and stop overwriting the initial value.
Is this now better than the multi-exit version?
This is the problem with the single-exit point rule — applying it as a universal rule doesn’t make things any better, but might make things a little worse.
If we look around for more complex examples we’ll find some where the single exit version is clearer, some where the multi exit version is clearer and countless more where they are about the same.
Martin Fowler and Kent Beck put things nicely in “Refactoring: Improving the Design of Existing Code”
“… one exit point is really not a useful rule. Clarity is the key principle: If the method is clearer with one exit point, use one exit point; otherwise don’t.”
It turns out there are still a few proponents of the single exit point rule out there, and we got some good feedback from Jean-Baptiste Giraudeau who works on the Functional Java and derive4j projects.
As you can tell from the projects he’s involved with he has a background in functional languages. His first point was that enforcing having only a single exit point seems to be working out pretty well for modern functional languages like Haskell.
This is true and prompted me to think about why it works out well in those situations but not for Java.
The answer is, of course, that they are different languages.
Functional languages are expression based (i.e everything returns a value), while Java code consists largely of statements.
To demonstrate the difference lets look at some Scala code. Because in Scala everything is an expression the following is valid.
The if statement returns a value, so we can assign it to a variable. In Java this would be a syntax error as
if is a statement and returns nothing.
A Scala version of our example function might therefore look like this:
It looks a lot like our earlier single exit point Java example, except we don’t have to create an extra variable to store the result.
Of course Java isn’t made entirely of statements, it has some expressions as well.
Which brings us to this interesting single exit point implementation that I hadn’t considered.
This uses Java’s
? operator which forms an expression in exactly the same fashion as
if does in Scala, returning the value from either side of the branch.
I rarely use the
? operator as I find it overly terse, but it lets us express this particular logic quite nicely, if a little tersely.
Is this clearly superior to our earlier multi exit version?
Personally I find the multi exit version much easier to read, but that is in part because I’m not used to this more compact idiom. If I’d been writing like this for a little while I’d probably be able to make sense of the
? version at a glance.
Although its statement based core isn’t going anywhere, the introduction of Lambdas and streams in Java 8 means we are all going to be writing a greater proportion of expressions in our code. As we’ve seen expressions and short single exit point methods fit together well.
It still won’t make sense to decree that all methods should be single exit, but I suspect we will all naturally write a greater proportion of them.