The single exit point law

Tags: return, code, style, exit point, rule

It is sometimes said that a method should have only one return statement (i.e. one exit point) and that to code using more than one return per method is bad practice. It is claimed to be a risk to readability or a source of error. Sometimes this is even given the title of the "single exit point law".  Actually, if you want to call something a law, I'd expect some evidence for it. I do not know of any formal study that back this "law" up, or of any study of the multiple-return pattern at all. This makes it a "preference" not a "law". And it's a preference that I do not hold for c# code. Or java, ruby or python code either.

This coding rule dates back to Dijkstra's structured programming. However it is outdated, if it ever ever was a "law" or "principle". The single return rule originates in the era of C, FORTRAN or assembler, where it was common to allocate resources (most frequently memory, file handles or locks) at the start of the procedure, and to de-allocate them at the end of it. An early return can lead the programmer  to either forget to do the cleanup code and cause a memory leak or locked file, or to maintain cleanup code in two places. So it makes some sense to stick to just one return right at the end of the method.

But in the modern world, this is no longer so. Firstly, garbage collected languages make explicit deallocation unnecessary in most cases - memory is reclaimed automatically. Secondly, try...finally blocks and using statements allow release of other resources to happen with greater certainly at the end of any block of code when it is needed.

In any event, a function with multiple exit points is a far lesser issue than a goto.  In some cases it is the simplest way to code now that we have control structures to deal with it.  If your method is long, complex and has multiple returns, consider splitting it up into smaller, well-named methods with a single-responsibly each. Also consider doing that if it's long, complex and has only one return.

My summary of the matter is:

•   There are cases where a single return is more readable, and cases where it isn't. See if it reduces the number of lines of code, makes the logic clearer or reduces the number of braces and indents or temporary variables.
•   More than one return style may be a bad habit in C code, where resources have to be explicitly de-allocated, but in languages that have automatic garbage collection and try..finally blocks and using blocks, this argument does not apply - in these languages, it is very uncommon to even need centralised manual resource deallocation.
•   There is no law requiring only one exit point for a method, and no evidence for it as a rule of thumb. Some people have an unsubstantiated belief in the superiority of this style.

Therefore, use as many returns as suits your artistic sensibilities, because it is a layout and readability issue, not a technical one.

There's another issue at play here, about rules being adhered to without people grasping the reason why they are adhering to them, and thus keeping the rule in force after the need for it has evaporated. When you give a rule, also give the reasons for it, so that people can apply their own judgement as to if it is still applicable.

Common patterns of early return

The guard clause

public Foo merge(Foo a, Foo b)
{
    if (a == null)
    {
        return b;
    }

    if (b == null)
    {
        return a;
    }

    // complicated merge code goes here.
}

It is fine, even in C code to use early return as a first check on the parameters after entering a function, before allocating resources and doing the main work of the routine. It's more readable than embedding the rest of the function in an if-block. Bear in mind that if the parameters are actually in error, throwing an exception is probably better than returning a default value.

The pattern is well explained here on Ward Cunningham's wiki. The discussion there diverges into a more general on on "early return vs single return", with the interesting point that single return requires mutable state in the form of a temporary "result" variable, thus early return, not requiring this piece of mutable state, seems "cleaner" to a functional programming perspective.

Found item in loop

Finding an item in a loop using returns was common in C#, but is often now giving way to the more concise LINQ version.  However, beware of returns in the middle of highly nested code or in methods that are more than just a loop (if posible, factor out the loop into a seperate method).  All other things being equal, avoid them, since they are less readable and predictable. However, the following is a valid use of multiple returns:

public Customer FindLuckyCustomer(IEnumerable<Customer> customers)
{
    foreach (Customer customer in customers)
    {
        if (IsLucky(customer))
        {
            return customer;
        }
    }

    return null;
}

Note how FindLuckyCustomer does not requre a result local variable, just the customerItem for the loop. The local variable would be "mutable state" for the method. If you have looked at all at functional programming, you can appreciate how eliminating unnecessary mutable state can be a good thing. Here's the code that uses the same loop but avoid multiple returns:

public Customer FindLuckyCustomer(IEnumerable<Customer> customers)
{
    Customer result = null;

    foreach (Customer customer in customers)
    {
        if (IsLucky(customer))
        {
            result = customer;
            break;
        }
    }

    return result;
}

This version has more lines of code, more state and more complex flow control. To me it's more complex than the version with multiple returns. We have removed one complexity, and introduced a different one which turns out to be worse.

However, the functional, LINQ version is even shorter and has no local state at all:

public Customer FindLuckyCustomerWithLinq(IEnumerable<Customer> customers)
{
    return customers.FirstOrDefault(c => IsLucky(c));
}

Fallback

This pattern has more variation, but the principle is to try and find a result from a first source, falling back to a second or futher sources. The best example of this is data from either cache or database. Early return if a item is found an a cache fits into this pattern.

public Customer GetCustomer(int customerId)
{
    Customer cachedCustomer = customerCache.GetCustomer(customerId);
    if (cachedCustomer != null)
    {
        return cachedCustomer;
    }

    Customer loadedCustomer = dataLayer.GetCustomer(customerId);
    customerCache.Add(customerId, loadedCustomer);
    return loadedCustomer;
}

This example with the fallback is interesting: if you re-write it with a single exit point you must introduce a temporary varaible to hold the result. I think that you cannot do this code without using one of two things: a temporary variable to hold the value to return at your single exit point, or multiple exit points. The single return increases the amount of temporary mutable state and thus the complexity.

Links:

•  There's questions on this topic on Stackoverflow and on programmers.Stackoverflow.
•  See also Ward Cunningham's wiki on Single Function Exit point.
•  Codinghorror talked about "Spartan programming", and mentioned "frugal use of control structures, with early return whenever possible."
•  One of the few links on the topic that I could find was Return statements and the single exit fantasy
•  See this discussion on Single exit point from function from Joel on Software
•  Take a look at some of the comments on this post "Refactoring to the Max" on the Daily WTF where this issue is raised, particularly this comment:
 
Re: Refactoring to the Max
2006-04-05 02:25 • by John Hensley
           
The main reason for the single return "law" in C is to make sure you clean up memory, locks, handles, etc. before you leave a function.
This, on the other hand, is Java code.

9 Comments

  • Bob said

    While I agree it probably shouldn't be a "law", but I do think it is best practice. Many of the examples you are quoting are breaking Single Responsibility Principal. Multiple exit points are usually a sign that a function is trying to do to much. Like I said, never should not be in used in programming, but I would argue against most times that it is done.

  • Anthony said

    Hi Bob I think you're right that complex methods with multiple return statement are usually trying to do too much. However I think we're only starting to see that in the third, "fallback" example. But in a case where there is a cache around a database or web service, however you re-arrange that code, there has to be a place where there is logic that tries to return a value from the cache, and failing that returns a value from a data layer instead. At that point, your have to either use a temporary variable or have two return statements. It is a matter of taste, and my taste is to favour the code with no temporary state. Which is also shorter.

  • Ben Alabaster said

    @Bob/@Anthony While I agree with the "never say never" argument, I also disagree that multiple exit points are a bad practice. In terms of complexity, you can often reduce complexity a lot and hence make code far more readable by allowing multiple exit points. I often use it for items such as: - Caching. - Parameter validation (although, this may throw an exception where suitable instead). - Iterating lists until a suitable exit point (i.e. do something which each item in a list until a certain point). As the expressiveness of languages evolve, some of the reasons for using early exit points become less and less attractive - i.e. code contracts, language integrated queries in the form of LINQ and frameworks such as jQuery. But that doesn't discount using them in places they *can* be used effectively. But I have to ask, why on earth would you force your code to follow a code path to a single exit point through needless instructions? I personally think that requiring a single exit point with today's languages is equally as asinine as using them blindly without considering architectural best practices. Every tool has a purpose, it can be used well or badly. If I have a nail that needs hammering, I use a hammer, if I have a screw that needs screwing I use a screwdriver. A hammer isn't bad just because I don't have any nails to hammer, it just means that it's not the right tool for *this* job.

  • npclaudiu said

    While I agree that having a single exit point in a method is not mandatory as it's not the Panacea for this matter, I strongly consider that it leads to better code from the point of view of maintainability and readability if carefully crafted.

  • AnthonySteele said

    Hi, npclaudiu. I can say the exact opposite - that having multiple returns leads to better code from the point of view of maintainability and readability if carefully crafted. In fact, I think I have. But neither of us has any concrete evidence, so it will have to remain a matter of taste.

  • gordon said

    When debugging code, especially code I've not written myself, I've found plenty of occasions where multiple exit points have caught me out. If you put a print into a statement to quickly check its internal state and it never gets to that point, but you know for certain that the function is being called then it can cause a few minutes of mental gymnastics before you realise what's happened, minutes that could have been avoided by simply having a single point of exit. As others have said, never say never when it comes to programming, but for me having a single point of exit makes the flow of the code more understandable. Normally I've found that if you need to leave a function early it's either because you can deliver an answer early (in which case I use if to skip the bit I don't need to run) or it's because something went wrong (in which case, throwing an exception is often a reasonable way to exit the function in a way that makes it clear that the function ceased execution due to a problem).

    What's with this obsession of avoiding local variables? It's not like it's the 70s anymore where 1k of memory cost thousands of dollars.

  • AnthonySteele said

    Hi Gordon.

    I discuss avoiding local variables (it's not really an obsession) not because of memory constraints, but because they are the internal state of the method, and IMHO they also affect readability. If more exit points make the method more complex, then so do more local variables. And there seems to be a trade-off between exit points and local state - more of the one means less of the other. The interesting thing for me was exchanging one for the other, and how sometimes this reduces the complexity by my (subjective) measure. But if your method is complex and needs lots of one, the other or both then see if you can refactor and split it up.

  • Zsombor said

    your example is not good enough to show the benefit for multiple return statement because it is easy and quite clear to rewrite the example to a single return
    public Customer GetCustomer(int customerId) {
    Customer customer = customerCache.GetCustomer(customerId);
    if (customer == null) {
    customer = dataLayer.GetCustomer(customerId);
    customerCache.Add(customerId, customer);
    }

    return customer;
    }

    now to show a benefit of a single return in such a simple case, add logging to log the returned value of this method (without AOP ) with multiple returns and single return

  • AnthonySteele said

    Zsombor, I talked about this some more in another blob post: http://anthonysteele.co.uk/returning-to-multiple-exit-points

    Single exits might be better sometimes, but it's not a law. If the idea is "use a single return because you might add logging/some other concern later" I say, no, add complexity *when* you have to, not before. It's the YAGNI principle.

Comments have been disabled for this content.