Replace Nested Conditions with Guard Clauses

Sarfraz Ahmed    May 09, 2015 01:53 PM

Sometimes we have to write code when we need to put conditions inside conditions (nested conditions) and once all of those are true, we perform some action. Here is dummy example of what I mean:

function isAuthorized($userId, $age)
{
    if (isLoggedIn($userId))
    {        
        if (isAdmin($userId) && $age >= 18)
        {            
            if (hasAcess($userId, $resourceId))
            {
                return true;
            }
        }
    }

    return false;
}

Although functionally nothing wrong with above code but it is good practice to avoid nested conditions (also nested loops) in some way or the other. This is simple example that may look easy to grasp to the naked eye, this isn't always the case. Obviously we can refactor above code and avoid nested conditions like this:

function isAuthorized($userId, $age)
{
    if (isLoggedIn($userId) && isAdmin($userId) && $age >= 18 && hasAcess($userId, $resourceId))
    {        
        return true;
    }

    return false;
}

We have shortened the code but still it doesn't look that good and readability is compromised here. Depending on the code editor/IDE you are using and font you are using or if you have even more nested conditions, this doesn't seem good solution or one that is easy to understand.

The solution is something called Guard Clauses which essentially mean you put your conditions in inverted way than your original conditions. Guard clauses should return opposite value compared to your original conditions. Here is how we can use guard conditions with above example:

function isAuthorized($userId, $age)
{
    if (! isLoggedIn($userId)) { return false; }
    if (! isAdmin($userId) || $age < 18) { return false; }
    if (! hasAcess($userId, $resourceId)) { return false; }

    return true;
}

As can be seen, we have got rid of nested conditions by putting reverse conditions on top of the function. We don't proceed any further when any of these is false. If none is false, true is returned as default value in the end.

The benefit here is that code looks easy to understand and gives quick idea of what it is doing at first glimpse. Pretty simple yet effective stuff.

Avoid This ;-)

enter image description here







Comments powered by Disqus