Me and my coworker follow a totally different pattern while programming. Probably there are a better technical term for that, but I call it now positive pattern and negative pattern.<p>I prefer the following way (in controllers, etc.):<p><pre><code> function ($param)
{
if ($param is not valid) {
return false
}
// do the stuff
return true;
}
</code></pre>
While my coworker does the opposite:<p><pre><code> function ($param)
{
if ($param is valid) {
// do the stuff
return true;
}
return false
}
</code></pre>
We agreed that none of them is good or wrong, just different approach. I am curious, how do you do, what are your thoughts, pros and cons?
In personal projects I do whatever has the code outside of the `if` block longer. e.g.<p><pre><code> function login() {
if (isLoggedIn) {
return
}
if (!isAuthenticated) {
throw AuthenticationFailure
}
// Do the login
...
}
</code></pre>
It doesn't matter that `isLoggedIn` is positive and `isAuthenticated` is negative, the point is both of those are short-circuit cases.<p>Though what usually actually ends up happening is<p><pre><code> function login() {
if (isLoggedIn) {
return
} else if (isAuthenticated) {
doTheLogin()
} else {
throw AuthenticationFailure
}
}
function doTheLogin() {
...
}
</code></pre>
Where there's no "long case", so the order really doesn't matter and I just make everything positive.
Personally, I think they're both sub-optimal because it's not abstracting the arg. check all the way. I think code is easier to reason about if your functions return one data type... and although the examples are returning boolean, in most cases functions return "stuff", and applying that to the examples would make their type "stuff | boolean". As the codebase scales this can be a source of pain for adding new things or finding bugs. The solution is abstracting the param check, and then composing two functions, one function that checks params, followed by the function that modifies "stuff". That way not only is the logic reused cleanly, but the functions will always return "stuff". This has drawbacks of course, as abstracting too much can become unwieldy, however I think there is a lot of power that comes along with it.
Two things I think about (obviously it's very context dependent):<p>- Quick returns go inside the condition to save a level of nesting in the function; try to minimize level of nesting of the main function body<p>- I try to return a value at the end of a function that will do the least harm if I somehow fall through (because maybe I've messed up the condition or something), for example:<p><pre><code> def launch_nukes():
if you_are_sure():
launch()
abort()
</code></pre>
It's not always obvious how best to structure a function to meet the second criteria, but in general I try to think defensively (how to minimize chances of bad bugs both now and when I come back in 6 months).
Negative, this keeps things consistent and clean. Here's a great article <a href="https://szymonkrajewski.pl/why-should-you-return-early/" rel="nofollow">https://szymonkrajewski.pl/why-should-you-return-early/</a>