Refactoring: How to avoid nested or several conditionals within a function?

Elie Nehmé
4 min readNov 5, 2018

--

Most of the time, having several conditionals inside a function and many levels of nested indentation make the code source so tedious to maintain, difficult to read and rapidly unclear — the pyramid of doom.

In the previous episode, we explored how to exit a loop without violating the Object Calisthenics rule: “Only One Level Of Indentation Per Method”! Through this article, we discuss two examples of nested IFs and try to explain, step by step, how to get rid of all these conditional structures.

Example 1: Introducing assertion function

Let’s dive into the first example and see how to change the code structure in order to remove all nested IFs:

doJob3 is executed whenever all conditions are met.

For simplicity, I picked out a simple example with three nested IFs.

In our case, conditionals are very simple, but we can imagine more complicated ones. Yet, extracting conditions into variables could not be an appropriate solution and may introduce more tests than needed:

Extract conditionals to variables

So to avoid duplicating or moving conditions into constants, I found a better approach by adding an assertion function:

run is executed when isTrue is true 😃

This assertion is straightforward and in addition, it returns the result of isTrue.

If run() would return a boolean value which is not the case here, we could compact the code to fit in one line.

“when” could be static and not related directly to the correspondent class or file.

Once we introduce the assertion function, we replace all nested conditions as follows:

Each when is called when the previous call returns true

If we still need to keep constants when conditions are too complex, we can do the following:

when is called three times but doJobX functions are executed depending on each constant result.

Of course, I prefer the first refactoring, where the call of the assertion function is immediate and cleaner.

Example 2 — Replacing IFs with Math.max

Another elegant way to replace conditionals could be implemented by checking and returning the maximum of several results. For example, consider the following code:

According to position or coefficient the numberOfDaysOff changes

Besides, the list could grow by adding other positions or coefficient ranges which lead to a more complex and unreadable code.

So, how could we eliminate all these IFs?

In this case, we can start extracting conditions to constants in order to use Typescript Accessors later:

Extract conditions to constants

SonarQube would emit a warning when we use more than three return statements. For this reason, I excluded this solution.

Now we have constants in place, we move them into accessors as follows:

Each get accessor replaces a previous condition.

Simultaneously, I added position and coefficient as class properties:

position and coefficient became class properties

However, I would like to change all getters in order to return the number of days off instead of a boolean value:

We return the number of days off according to position or coefficient

Obviously, function name has been changed to reflect our purpose.

Now, since we have the number of days off over all getters, replacing conditionals with Math.max becomes straightforward:

Math.max returns the maximum number of days off according to the position or the coefficient.

Summary

As we can see, in both examples, our source code became more readable and cleaner. After all, our main goal is to write beautiful code — that works 😉— .

I didn’t mention unit tests during refactoring because it is beyond the scope of this article, however, unit tests are required and must accompany the whole process of refactoring.

The complete source code for example 2 could be found here: https://github.com/elie29/if-elseif.

Each step has its own dedicated branch.

Don’t hesitate to give me your feedback or contact me on Twitter @elie_nehme

--

--

Elie Nehmé
Elie Nehmé

Written by Elie Nehmé

Lead Web Application Architect. Passionate about refactoring, clean code, and building scalable solutions with simplicity. https://elie29.hashnode.dev/

No responses yet