As the title states I would like to hear the forum’s opinions on the acceptable style of returns. Should I use one or many? Which way is most specific to Ada? I’ve thought about it for a while, and can’t seem to put a choice into words.
This is the one-entry-one-exit discussion.
There can be no definitive answer because the set of possible functions is infinite.
Sometimes the logic is best captured with a single return statements and some Result variable.
Sometimes it’s better to use multiple return statements (e.g. a boolean function that has to check multiple mutually dependent predicates).
That said, my custom is to first look for a one-exit logic.
This way I’m pushing myself to think of ways to reduce the problem, which does not happen when I just assume that I can return something at any point (in that case, I just write code without much thinking).
An interesting fact: the language Eiffel does not allow multiple returns. Instead, each function has an implicit Result variable that can be assigned a value and is returned when the function execution completes.
Use as many as is needed, but also bear in mind the extended-return:
Function Example(Input : Positive) return Character is
Begin
Return Result : Character := '*' do
if Input = 1 then
Result:= '1';
elsif Input = 2 then
Result:= '2';
else
Result:= '!';
end if;
End return;
End Example;
I’ve tried following the one-entry-one-exit rule at various times, but usually find it to be more of a burden than being useful. Most of the time, with multiple returns, especially when checking for bad parameters at the beginning, it is simply easier to comprehend when processing has concluded, whether successfully or not. Reviewers often find it easier as well, especially if it matches the requirement that has to be verified. Of course, there are cases when a single return makes more sense.
I don’t follow inversion patterns in my code. I usually just do a fall through failure for everything that’s not the most likely. So I don’t have guard conditions that need returns. I guess this whole thing is extremely variable depending on the underlying patterns. Guess I was hoping for a magic solution haha.
After reading everyone’s responses I think I’ll stick with single returns if I can get away with it or double returns if I absolutely have to. I don’t use inversion, so this should be the best choice for me.
Thank you all for you input.
The structured programming advises one entry one exit.
In practice it depends on the way the result is constructed. If the result is incrementally bult and adjusted then single return is the best. If the result is from a narrow set of predefined choices then fall out is better. Raising exceptions falls into this category too.
In Ada you can handle most of the early exit on error cases using proper preconditions.
Then there are some function that could return early for trivial cases, like atan2 when the first argument is zero. I find it easier to see a return there, then I don’t need to bother anymore about this special case when reading the rest of the function. Otherwise there is always a chance that the return value is accidentally modified somewhere.
Finally if it’s more complicated than that, I try to use the extended-return and put the complicated stuff into separate functions.
Ada follows structured programming from Wirth, so you should really use one at the end, but you can use multiple.
The one-entry-one-exit rule came from the world of program proofs in the late 1960s. At the time, units with multiple exits were difficult to prove, so it was recommended that code that was going to be proved not use them. It was not intended to apply to code that was not going to be proved. These days things like SPARK handle multiple exits OK, so there’s even less reason to pay attention to this rule.
Modern software engineering is mainly concerned with Correctness and Clarity. Multiple returns generally don’t affect Correctness, but can have a significant impact on Clarity. Early returns for special cases is a common example.
So my rule is: whichever makes the code easiest to read and understand.