I'm wondering if there has been any research (both casual and robust) on the maintainability of projects that use the "guard statement" paradigm vs. the "single function exit point" paradigm?
Guard statement example (in C#):
string GetSomeString()
{
if(necessaryConditionFails) { return null; }
if(!FunctionWithBoolReturn(someAttribute)) { return null; }
//all necessary conditions have been met
//do regular processing...
return finalStringValue;
}
single function exit point example (in C#):
string GetSomeString()
{
string valueToReturn = null;
if(necessaryConditionPasses && FunctionWithBoolReturn(someAttribute))
{
//all necessary conditions have been met
//do regular processing...
valueToReturn = finalStringValue;
}
return valueToReturn;
}
I know the merits and failings of both have been debated endlessly on SO, but I'm looking for actual research into how maintainable each paradigm is*. This may be unknown, but I figured if the information is out there, someone on SO would know where it was. My web searches have not been sucessful so far.
**I'm also aware that many programmers (including me) use both principles throughout their code, depending on the situation. I'm just hoping to discover which one has a proven track record of greater maintainability to use as the preferred paradigm.*
Forcing to have single exit points have some problems of their own.
The first one is that it may lead to complex constructions. Image a function in which you have to open a file, read a line, convert the line to a number and return that number or zero if something goes wrong. With a single exit point, you end up using lots of nested if's (if file exists open it, if open succeeds read the line, if read succeeds convert the value to an integer), which makes your code unreadable. Some of it can be solved by having a label at the end of the function and using goto's (we had to use that in the past since we also used the single exit point and preferred readability) but it's not ideal.
Second, if you are using exceptions you are forced to catch everything if you want your single exit point again.
So, personally, I prefer putting lots of checks (and asserts) in the beginning and during the execution of the function, and exit the function at the first sign of trouble.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With