Python taught me some good practices in regards to this. Python's "enforcement" (or rather, strong PEP-8 suggestions) of 80 characters per line teaches you to come up with a lot of ways to avoid nesting.
The most useful one, and the one that drives me crazy when I see it, is when people write code like this:
if something:
value = do something
else:
value = do something else
return value
These days I write code like this:
if something:
return do something
return do something else
In the simple example, it's not a big deal. But once you have 30 lines of code in between each statement (and nested if statements), it gets trickier to maintain every possible code path in your head.
This isn't the same as "show all conditions at once" -- instead it's "ignore the conditions that have already been satisfied."
Seeing that we already returned out in condition #1 lets me focus more on condition #2.
Believe it or not, I once interviewed for a cryptography firm and they had me look over some code samples to improve them. Some of my improvements were just what you did. But they stopped me mid way through and said that the "standard" they are required to follow only allows one return statement and it had to be at the end of the function... Don't know what standard it was, whether their own or some 3rd party compliance.
I've heard this argument (I like a single exit point) before, but I don't really understand it, I'd love for someone to explain why they prefer it, if they do.
I think the main reason returning early works so well is that often times, when you're returning different values, it's because you quickly have an answer (often times that something is invalid) for particular inputs. Generally though, there is "real work" to be done after validating or normalizing your inputs.
If that's not true, you're probably trying to do too many things at once, and the different pieces should be broken into separate functions.
In the specific case of crypto, maybe they are concerned about leaking information through timing if they return early? Though even if you have only one exit point, that alone does not in any way guarantee that timing differences won't occur. For that, I think the same work must be done always and only at the very end it is decided whether or not the result is valid. Something like that. So maybe they have some other reason. Maybe it's just cargo cult programming.
if some_function(arg, arg2):
result = True
else:
result = False
return result
Obviously a waste of time and lines of code. Instead, do
return some_function(arg, arg2)
Unless anything else needs to be done with the result of some_function but that's not the case I'm talking about, I'm talking about when it looks like above.
I figured readers could fill in the relevant blanks. Updated example:
if something:
value = do something
else:
if something_else:
value = do something else
else:
value = do a third thing
As I said in my initial post, "it helps once you have nested ifs, and multiple lines of code." Here's the change:
if something:
return do something
if something_else:
return do something else
return do a third thing
Again, what I'm stressing here is that if you already have your result, you can return, and it makes the code easier to follow than adding a superfluous "else:" statement.
The most useful one, and the one that drives me crazy when I see it, is when people write code like this:
These days I write code like this: In the simple example, it's not a big deal. But once you have 30 lines of code in between each statement (and nested if statements), it gets trickier to maintain every possible code path in your head.This isn't the same as "show all conditions at once" -- instead it's "ignore the conditions that have already been satisfied."
Seeing that we already returned out in condition #1 lets me focus more on condition #2.