Recently I gave a talk that included a slide where I briefly discussed single return vs multiple returns. The purpose of this slide was only to give an example of a dogma and basically had nothing to do with the rest of the talk. Therefore it was kinda funny to see that this particular slide caused a lot of discussion afterwards, so it seems natural to write a blog about this topic.

So…​ should a function only have a single return statement or is it better to allow multiple returns?

Before we begin

Before we start talking about this topic I do want to mention that in a lot of cases this is a typical Bikeshedding problem. Apart from a few cases we will discuss later it does not affect the structure of the software in any way and is more of an implementation detail than an important issue. Also take into account that your view might be biased because you are only familiar with one of the two and therefore think this is the better approach. To give it a fair chance, familiarize yourself with both approaches in different situations. In the rest of the blog I will try to focus on what makes these approaches different in an objective way so you can apply the right pattern in the right situation.

Point of exit

A point of exit in a function is the point where a function is done computing and ready to return the value.

//Example 1a
public String foo(String arg1, String arg2){
  String returnValue = "foo";
  if(arg1 == null){
    returnValue = ""; //Point of exit
  } else if(arg2.equals("")){
    returnValue = "-"; //Point of exit
  }
  return returnValue; //Point of exit
}

//Example 1b
public String foo(String arg1, String arg2){
  if(arg1 == null){
    return ""; //Point of exit
  } else if(arg2.equals("")){
    return "-"; //Point of exit
  }
  return "foo"; //Point of exit
}

If a function has multiple points of exit where no more computing should be done, multiple returns has the advantage in my opinion because it is now impossible to perform extra computation after the return statement. If your function only has one return statement it is now your responsibility to make sure the returnValue does not change anymore after a point of exit. Although mistakes in these things will be rare, I personally like an approach where the compiler makes mistakes impossible to happen, and just returning the value at an exit point will do just that.

Exit conditions

Of course having an exit condition in your function can prevent you from using this approach. An exit condition is any computation that needs to be (manually) performed before returning. Depending on the situation and language, common exit conditions are things like: closing resources, free up memory or logging results. And the closing of resources is also where the "Single exit" part of the "Single Entry Single Exit" principle comes from (the Single Entry part is only relevant in languages that still use GOTO and it means that you should not GOTO line 2 of the function). Note here that the "Single exit" principle only applies to functions which have exit conditions.

//Example 2a
public String foo(String arg1, String arg2){
  String returnValue = "foo";
  if(arg1 == null){
    returnValue = "";
  } else if(arg2.equals("")){
    returnValue = "-";
  }
  logger.info("I am returning {}", returnValue)
  return returnValue;
}

//Example 2b
public String foo(String arg1, String arg2){
  if(arg1 == null){
    logger.info("I am returning empty")
    return "";
  } else if(arg2.equals("")){
    logger.info("I am returning -")
    return "-";
  }
  logger.info("I am returning foo")
  return "foo";
}

If we look at examples 2a and 2b now, we can see the advantage of only having one return statement when dealing with an exit condition. We still have the problem of making sure we don’t change the return value by accident, but in return we do not have to duplicate code and have to remember to put that in at all exit points. This becomes even more important if a resource needs to be closed in order to prevent things like memory leaks. So in these situations I would recommend using only one return statement.

Hybrid functions

Of course there are also hybrid functions which do have multiple exit points, but not all exit points have exit conditions (or have different exit conditions). A common occurrence of this is checking input arguments.

//Example 3
public String foo(String arg1, String arg2){
  if(arg2.length() > 1){
    logger.info("Argument arg2 is invalid")
    return null;
  }

  String returnValue = "foo";
  if(arg1 == null){
    returnValue = "";
  } else if(arg2.equals("")){
    returnValue = "-";
  }
  logger.info("I am returning {}", returnValue)
  return returnValue;
}

In this case we do not want to proceed computing and we have a different exit condition than the normal flow when checking input arguments (we want to log a different message). Here a hybrid approach would be best where we use the multiple returns pattern to prevent further execution, but use the single return pattern to take care of the exit condition.

Conclusion

Instead of a war which of the 2 approaches is better, I would suggest to look at what both approaches have to offer and use this to decide what to do for each function you write. Personally I would recommend using multiple returns where possible to get some aid from the compiler in prevention of mistakes and use the single return pattern in case there are exit conditions. So let go of any dogmas you might have and just pick the best approach depending on the function and don’t try to premature optimize functions because you might want to add in an exit condition later (just rewrite the function if that ever happens).

Closing thoughts

In my research and talks with colleagues I found quite a few more arguments for both sides. In my opinion however most of those arguments were either very contextual or in the lines of "but what if this ever happens". I chose not to include those arguments because very specific situations require specific solutions. I also think that in most cases it is a bad practice to write non-optimal software now just in case it might benefit you in the future.. e.g: Do not use the single return pattern where multiple returns is a better fit just because you never know when you might need to add an exit condition, if that ever happens it will only cost you a few more minutes and there is a bigger chance that was never needed

shadow-left