Do Boolean Parameters Make You a Bad Programmer?


A Boolean value is used to determine a program’s execution behavior.

However, using a Boolean as a parameter in a function is a sign of a code smell. Therefore, you should avoid preserving the functions’ exact purpose and make the code readable, cohesive, and maintainable.

This article explains why using Boolean parameters to determine behavior is a bad software engineering practice, what techniques you should follow to eliminate their usage, and scenarios it can be acceptable.

Is it wrong to use a Boolean parameter to determine behavior?

bool

One of the indications of a good code is functions that exactly do one job according to the Single Responsibility Principle. For example, look at the following simple C# code example:

using System;
using System.Collections.Generic;

public class TestExample
{
    public static string ProcessList(bool flag, int max, List<int> list)
    {
        int x;
        if (flag) {
          x = 0;
          while (x <= max)
          {
              list.Add(x);
              x++;
          }
       }
       else {
          x = max;
          while (x >= 0)
          {
              List.RemoveAt(x);
              x--;
          }
       }
       return string.Join(",", list);
    }
    
    public static void Main(string[] args)
    {
        var list1 = new List<int>();
        var list2 = new List<int> { 1, 2, 3, 4, 5 };
        string s1 = processList(true, 4, list1);
        Console.WriteLine ("List1: " + s1);
        string s2 = processList(false, list2.Count-1, list2);
        Console.WriteLine ("List2: " + s2);
        
    }
}

The ProcessList method takes a Boolean flag to determine which control flow it should execute to provide the right result based on the function call. 

Using a Boolean parameter to determine function behavior is a code smell that every programmer must avoid.

Though it is technically correct to use Boolean parameters, it violates the Single Responsibility Principle and functional cohesion that helps to achieve a single, well-defined purpose to the function. It means that based on a Boolean value, the function does two different things.

Some methods may do only small modifications in different flows based on the Boolean value. However, there can be methods that use more than two conditional statements to adjust calculations and more than one Boolean parameter to introduce multiple control flows. 

In addition, Boolean parameters can violate the Tell, Don’t Ask principle, which states that we should call the exact method rather than letting methods ask what behavior they should execute based on a flag. Take a look at the following simple example:

public static void ProcessMessage (string name, bool isStudent) {
      //code
}

And the usage:

if(obj.getUserType == 'student') {
  obj.processMessage(name, true);
}
else {
  obj.processMessage(name, false);
}

The method takes a Boolean parameter to determine if the user is a student or not. Then, when the code calls it, the object first ‘asks’ what behavior it should execute by executing another function. This is simply not a good programming practice that can make the code harder to maintain. Instead, it would be best if you told the object exactly what it should do rather than letting objects ask for it.

Boolean parameters also increase the ‘cyclomatic complexity‘ that measures the number of control flows in a code. In the above example, the cyclomatic complexity is two since there are two different control flows. The complexity can increase with the number of Boolean parameters it takes. Thus, if the method takes two booleans, the complexity grows to 4.

Boolean parameters make code harder to read

Another problem with Boolean parameters is that it significantly reduces the code’s readability. Suppose the above example code is part of a larger program, and a novice programmer reads the line ProcessList(true, 4, list1) called in a different file. In that case, they might not understand the exact purpose of the Boolean argument value true here. Of course, the method name might hint at its purpose. However, until they read the entire function code, its exact purpose will be difficult to determine.

Also, suppose the following simple method that calculates the volume of a cylinder in cubic centimeters as well as in liters.

public static double CalculateCylinderVolume(double Radius,
                                                double Height,
                                                bool isCubic)
{
    double volume = Math.PI * (Radius * Radius) * Height;
    volume = isCubic ? volume : volume / 1000;
    return volume;
}

With the call:

double volume = CalculateCylinderVolume(10,15, true);

In the CalculateCylinderVolume(10,15, true) method call, if the programmer wants to get the volume in liters, they may pass the value true as an argument, which returns the volume in cubic centimeters unless they read the exact function.

Thus, Boolean parameters make code harder to read and make programmers do extra, unnecessary work to understand the code.

Boolean parameters increase maintenance cost

Boolean parameters also make it difficult to modify the code. Maintainability is one of the key features of a high-quality code. For example, imagine you want to add another condition for your application flow, and it needs to add in a function with a boolean parameter. If the function is larger, you will have to modify a large amount of code or introduce a new boolean parameter that would make the code even more complex and harder to read.

For example, if your software is real-estate software that needs to calculate the area of the land in multiple units of measurements like hectares, acres, and perch. Then you will have to introduce multiple boolean parameters to the function, increasing the code complexity. Thus, modifying the code becomes harder with the number of boolean parameters you use in the method.

How to eliminate an if-else block used to determine behavior based on a boolean parameter?

Eliminating the use of boolean parameters can be done using two solutions. One is by introducing two separate methods for each boolean value, and the other is using Enums that provide more code readability and functional cohesion than boolean parameters.

(And in case you have nested if statements that use a boolean parameter, you can eliminate nested if statements using guard clauses.)

Split the method into two methods

In the above-discussed example, there are two different functionalities in the function: inserting the data into the list and removing the data from the list, which you can define in two separate methods. This makes programmers understand the purpose of the methods easily without any confusion and helps preserve the Single responsibility principle.

public static string AddToList(int max, List<int> list)
 {
    int x = 0;
    while (x <= max)
    {
        list.Add(x);
        x++;
    }
    return string.Join(",", list);
  }

  public static string RemoveFromList(int max, List<int> list)
  {
    int x = max;
    while (x >= 0)
    {
        list.RemoveAt(x);
        x--;
    }
    return string.Join(",", list);
  }

Now the method calls become lot simpler:

string l1 = AddToList(4, list1);
string l2 = RemoveFromList(list2.Count-1, list2);

Use Enum instead of the boolean flag

Another way you can avoid boolean flags is using Enums or enumeration types. Many programming languages support defining Enums. Enums define a group of constant names for a particular variable.

For example, suppose you need to calculate the area of a square land in different units of measurement. In that case, you can use an Enum to define units of measurements as constant names and pass the corresponding Enum value in each method call according to your requirements. The following code defines the Enum with three values for LandAreaUnits.

enum LandAreaUnits
{
   Hectares,
   Perch,
   Acres
};

You can then use that Enum inside the function to define the behavior according to each enum value.

public static void CalculateSquareLandArea(double side1 double side2, String value)
    {
      double landArea;
      switch (value)
      {
        case Hectares:
          //code
          break;
        case Perch:
          //code
          break;
        case Acres:
          break;
        default:
          //code
      }
      return landArea;
    }

And the call:

CalculateSquareLandArea(1045.99, 1334.5, LandAreaUnits.Hectares);

Using Enums eliminates boolean parameters and improves the code readability, functional cohesion, and maintainability.

Is the boolean parameter always bad?

As you have identified so far, even though using boolean parameters is a code smell you should avoid, there are a few scenarios it is acceptable to have. 

  • One scenario is when the method uses exactly one parameter, and it is a boolean. For example, the following setter method takes only a boolean parameter to set a particular property as a configuration value in a class.
private static bool open;

public static void SetOpen(bool value)
{
    open = value;
}

public static bool GetOpen()
{
    return open;
}


//usage
SetOpen(true);
bool value = GetOpen();
Console.WriteLine ("set Open Value " + value);


//output
Output: true

The above SetOpen method represents exactly setting a true or false and provides enough meaning for the reader to understand its exact purpose without any ambiguity. Thus, in such scenarios, passing a boolean parameter is acceptable.

  • Also, some programming languages like Javascript allow users to pass boolean parameters inside a config or a property object, enabling you to explicitly define the boolean parameters’ name. For example, 
area({width: 50, height: 100, isAcres: true});

Also, in C#, you use the above approach with named and optional parameters.

Conclusion

Using boolean parameters is a code smell because of several reasons. One obvious reason is that it makes the code harder to read. Also, it violates the single responsibility and “tell, don’t ask” principles and increases the cyclomatic complexity making it harder to maintain the code.

A person that does not have any idea about the method will never understand what the boolean parameter does in the function call.

The best solutions for avoiding boolean parameters include splitting the method into two separate functions and using Enums. However, there can be situations where using boolean parameters are acceptable. For example, methods that need only the boolean parameter and pass it inside an object explicitly define the parameter name.

Recent Posts