DEV Community

Cover image for Code Smell 07 - Boolean Variables
Maxi Contieri
Maxi Contieri

Posted on • Updated on

Code Smell 07 - Boolean Variables

Using boolean variables as flags, exposes accidental implementation and pollutes the code with Ifs.

TL;DR: Don't use boolean variables, they force you to write Ifs. Create polymorphic states instead.

Problems

  • Extensibility

  • Comparison in some languages

Solutions

  • If Boolean maps to a real world entity is safe. Otherwise, model as a State to favor Extensibility. This also follows Open/Closed Principle.

Examples

  • Flags

Exceptions

  • Real world true/false rules

Sample Code

Wrong

<?

function processBatch(
    bool $useLogin,
    bool $deleteEntries,
    bool $beforeToday) {
    //...
}
Enter fullscreen mode Exit fullscreen mode

Right

<?

function processBatch(
    LoginStrategy $login,
    DeletionPolicy $deletionPolicy,
    Date $cutoffDate) {
    //...
}
Enter fullscreen mode Exit fullscreen mode

Detection

Automatic detection can warn for boolean usage, but this can yield false positives.

Relations

Some languages have issues with boolean comparators.

Alt Text

In these coupled with accidental complexity languages, booleans are a common error source.

Also Known as

  • Flag Abuser

Tags

  • Declarative

  • Primitive

More info

Martin Fowler

Conclusion

Take extra care when declaring something boolean. Flags are difficult to maintain and extend.
Learn more about the domain. Try migrating to state design pattern. Use polymorphism instead of ifs/switch/cases.

Credits

Photo by Phil Hearing on Unsplash

These tweets inspired this code smell:


This article is part of the CodeSmell Series.

Last update: 2021/06/08

Oldest comments (2)

Collapse
 
joelbonetr profile image
JoelBonetR 🥇

Using booleans as params is something common and definitely not a code smell, it's more about the context and how it's handled.

const getBreakfast = (isPremium) => {
  return isPremium ? getPremiumBreakfast() : getBasicBreakfast();
}
Enter fullscreen mode Exit fullscreen mode
const getBreakfast = (user) => {
  return user.isPremium ? getPremiumBreakfast() : getBasicBreakfast();
}
Enter fullscreen mode Exit fullscreen mode

None of those is better than the other, it's a matter of how the app is modelled 🤷🏻‍♀️
The alternative is to set which breakfast a user should get as user property which can become quite inefficient and bloated quickly as soon as you get more breakfast menus for different users, have optionals, start serving lunchs, dinners and so on.

Of course this is better than adding multiple params to the getBreakfast function:

const getBreakfast = (user) => {
     let options = { 
       vegan: user.isVegan,
       vegetarian: user.isVegetarian,
       keto: user.isKeto,
    }

    return isPremium ? getPremiumBreakfast({options: options}) : getBasicBreakfast({options: options});

}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mcsee profile image
Maxi Contieri

is premium has an accidental IF . So it is a code smell

a better solution following open/closed principle would be to delegate on the breakfast using double dispatch. In this way you can have even more than two breakfasts

Ternarys are IFs, so they are also code smell

Code is not better this way, IMHO