How to Write Conditional Statements like a Pro ๐Ÿ˜Ž

How to Write Conditional Statements like a Pro ๐Ÿ˜Ž

Tips on writing cleaner conditional statements (if else)

ยท

6 min read

As a software engineer, I use conditional statements frequently. In this post, I will share with you how to write a better conditional statement. I hope that this approach will help you to write cleaner code so that your teammates will love your code. Here are the tips.

Use Guards

Let's take a look at the example below

if (user.isActive) {
    // do some process for active user
}

return false

Imagine that the processing inside the if block is multiple lines of code. The longer the line of code, the harder to read. We can change the code and make the if statement a guard. See the example below

if (!user.isActive) {
    return false
}

// do some processing

As you can see in the example above, we change the condition on the if statement and it will return fast. So the if statement becomes a guard. It returns fast and guards the rest of the code not to be executed. Furthermore, there is only a single line of code within the if block. This makes it easier to read & understand.

Guard on If Else

How about an if else statement? Let's see the example

if (user.isActive) {
    // do some processing
} else {
    throw new Error('inactive_user')
}

We can still use guard on this. See the refactored code below

if (!user.isActive) {
    throw new Error('inactive_user')
}

// do some processing

With this technique, we don't even need to write an else statement anymore. The guard will throw an error fast and protect the rest of the code.

What if both the if block and the else block have multiple lines of code? Hold on, I will explain it. Just continue reading ๐Ÿ˜. You can read decompose conditional statement section.

Guard on Loop

You can also use conditional statements as a guard inside a loop. The concept is that the guard is able to break or continue fast. If you want to break or continue inside the loop, you can put it at the beginning of the loop.

const products = [
    {id: 1, isActive: 1 },
    {id: 2, isActive: 0 },
    {id: 3, isActive: 1 },
]

for (const product of products) {
    if(!product.isActive) continue // this is a guard

    // do something 
}
const carts = [
    {id: 1, isActive: 1 },
    {id: 2, isActive: 0 },
    {id: 3, isActive: 1 },
]

for (const cartItem of carts) {
    if(!cartItem.isActive) break // this is a guard

    // do something
}

Decompose Conditional Statement

If you have a long conditional statement, try to decompose it. Look at the example.

function processToFinalExam(student) {
    if (
        student.attendanceCount >= 10 && 
        student.projects.length === 4 && 
        student.finalProjectStatus === 'submitted'
    ) {
        console.log('calculate attendance percentage')
        console.log('calculate average exam score')
        console.log('calculate average project score')
        console.log('calculate final project score')
        console.log('calculate total score')
        console.log('check if student is allowed to attend the exam')
    } else {
        console.log('check if student is eligible for chapter remedial')  
        console.log('notify parent via push notification')
        console.log('generate warning letter')
    }
}

In the example, I have a long conditional statement. Imagine a school that wants to check whether a student can attend the exam or not. If the student meets the minimum criteria, then calculate the total score and check eligibility to attend the exam.

In the if and else block, I put some console.log as a replacement for some example processes to make it simple. Now the question is, how to make the conditional statement cleaner and more readable? Ok, let's decompose the statement by extracting the statements into functions.

Extract Function

First, let's extract the statements on if block.

function processToFinalExam(student) {
    if (
        student.attendanceCount >= 10 && 
        student.projects.length === 4 && 
        student.finalProjectStatus === 'submitted'
    ) {
        checkExamEligibility()
    } else {
        console.log('check if student is eligible for remedial class')  
        console.log('notify parent via push notification')
        console.log('generate warning letter')
    }
}

function checkExamEligibility () {
    console.log('calculate attendance percentage')
    console.log('calculate average exam score')
    console.log('calculate average project score')
    console.log('calculate final project score')
    console.log('calculate total score')
    console.log('check if student is allowed to attend the exam')
}

I move the code from the if block to a new function called checkExamEligibility . This is just an example function. I don't use any parameters for simplicity. I hope that you got the idea.

Next, extract the code inside the else block into function.

function processToFinalExam(student) {
    if (
        student.attendanceCount >= 10 && 
        student.projects.length === 4 && 
        student.finalProjectStatus === 'submitted'
    ) {
        checkExamEligibility()
    } else {
        checkRemedialEligibility()
    }
}

function checkExamEligibility () {
    console.log('calculate attendance percentage')
    console.log('calculate average exam score')
    console.log('calculate average project score')
    console.log('calculate final project score')
    console.log('calculate total score')
    console.log('check if student is allowed to attend the exam')
}

function checkRemedialEligibility () {
    console.log('check if student is eligible for remedial class')  
    console.log('notify parent via push notification')
    console.log('generate warning letter')
}

After extracting statements into functions, the overall conditional statement is more readable now. But, you can actually refactor once more.

Extract Condition / Control Structure into Function

Let's extract the condition into a new function.

function processToFinalExam(student) {
    if (isQualified(student)) {
        checkExamEligibility()
    } else {
        checkRemedialEligibility()
    }
}

function isQualified (student) {
    return student.attendanceCount >= 10 && 
    student.projects.length === 4 &&
    student.finalProjectStatus === 'submitted'
}

function checkExamEligibility () {
    console.log('calculate attendance percentage')
    console.log('calculate average exam score')
    console.log('calculate average project score')
    console.log('calculate final project score')
    console.log('calculate total score')
    console.log('check if student is allowed to attend the exam')
}

function checkRemedialEligibility () {
    console.log('check if student is eligible for remedial class')  
    console.log('notify parent via push notification')
    console.log('generate warning letter')
}

You can also add constant for a better readability.

const MIN_ATTENDANCE_COUNT = 10
const MIN_PROJECT_COUNT = 4
const FINAL_PROJECT_STATUS = {
    SUBMITTED: 'submitted'
}

function isQualified (student) {
    return student.attendanceCount >= MIN_ATTENDANCE_COUNT && 
    student.projects.length === MIN_PROJECT_COUNT &&
    student.finalProjectStatus === FINAL_PROJECT_STATUS.SUBMITTED
}

Next, you can remove the else on processToFinalExam function.

function processToFinalExam(student) {
    if (isQualified(student)) {
        checkExamEligibility()
        return
    }

    checkRemedialEligibility()
}

Now, the function become shorter and easy to understand.

Summary

In this article, I shared about two ways of refactoring your If else statement by using Guard and Decompose Conditional Statements. A guard can be used to return, fail, break, or continue fast, so you can protect the rest of the code to be executed. Decompose conditional statement can be used by extracting the condition/control structure, and the code on if and else block into new functions. There are many other techniques to make your conditional statement cleaner, If you want to know more about it, please leave a comment below.

The benefits of applying Guard and Decompose Conditional Statement are:

  • You can avoid a long function, and create shorter functions that focus on a specific task. This is good for the long term.

  • Make your code cleaner & more readable

I hope that this article can help you learn how to write a better and cleaner if else statement.

ย