Refactoring the Nested Conditionals code smell

Nested conditionals are a code smell because they make the code harder to understand. They tend to grow more and more complicated over time because developers will keep adding conditions and more levels of nesting. The deeper the nesting, the more time it’ll eventually take to refactor it.

Code Smell: Nested conditionals.
Definition: A conditional block (such as an if block) has another conditional block nested within it.
Solution: Guard clause refactoring.

Code on the left shows nested conditionals. Code on the right shows the refactored code after inverting the conditions and exiting early (Guard Clause refactoring)

In this article I’ll show how to do the guard clause refactoring shown in the image above.

Nested conditional code smell example

First, let’s start by looking at code with a nested conditional.

var miles = 0.0;

if (car.HasFuel)
{
	if (car.EngineWorks)
	{
		var startingMiles = car.Miles;
		car.Drive();
		var endingMiles = car.Miles;
		miles = endingMiles - startingMiles;
	}
}

return miles;
Code language: C# (cs)

This is the simplest example possible. It only has one level of nesting.

Invert the conditions and pull them into a guard clause

Notice that when the car.HasFuel condition is not true, it doesn’t enter the if block, and it’s returning the miles variable (which is initialized to 0.0).

In other words, when car.HasFuel is false, it returns 0.0. Let’s pull that logic up into a guard clause:

if (!car.HasFuel)
	return 0.0;

var miles = 0.0;

if (car.EngineWorks)
{
	var startingMiles = car.Miles;
	car.Drive();
	var endingMiles = car.Miles;
	miles = endingMiles - startingMiles;
}

return miles;
Code language: C# (cs)

Notice the same thing can be done with the car.EngineWorks condition. When it’s false, it returns 0.0. Therefore, let’s pull it up into the guard clause:

if (!car.HasFuel || !car.EngineWorks)
	return 0.0;

var startingMiles = car.Miles;
car.Drive();
var endingMiles = car.Miles;
return endingMiles - startingMiles;
Code language: C# (cs)