Reduce code complexity: Guard clauses

Almost every software engineer fights a never-ending fight: we strive to make our codebase simpler and thus more readable every day.

Complexity is added almost every time we interact with the codebase. A simple feature addition would probably result in added complexity and there's nothing we can do about it.

But there are patterns we can follow to keep complexity to the minimum. The simplest pattern you can start applying today and has an impressive impact on complexity is the guard clause.

Take a look at the following 2 snippets that have the same result.

fun nested() {
    if (condition1) {
        doThings1()
        if (condition2) {
            doThings2()
            if (condition3) {
                doThings3()
            } else {
                throw Exception3()
            }
        } else {
            throw Exception2()
        }
    } else {
        throw Exception1()
    }
}
fun guard() {
    if (!condition1) {
        throw Exception1()
    }
    doThings1()

    if (!condition2) {
        throw Exception2()
    }
    doThings2()

    if (!condition3) {
        throw Exception3()
    }
    doThings3()
}

You can see that the same code using guard clauses is easier to read and easier to reason.

In a nutshell, nesting adds complexity. Our code base, full of if statements are full of nesting. Avoid unnecessary nesting and you will reduce complexity.

When there's deep nesting you need more "mental" processing to keep everything in your head.

In addition, things are now more "local". The appropriate exception is thrown as soon as the error happens. No need to chase curly braces to figure out when something is thrown.

Hopefully, this simple trick can make your code a bit more readable with minimum effort.

Happy coding!