Jake Worth

Jake Worth

Presence is Boolean

Published: January 24, 2022 • Updated: June 13, 2023 2 min read

  • booleans

When possible, I prefer to use the presence of data as a boolean, rather than a boolean itself.

Here’s a problematic pattern I see a lot in frontend code. Imagine we’ve made network request that returns an error. Our code sets a boolean errorState (“are we in an error state?”) to true. Then we display an errorMessage for that condition:

if(isErrorState) {
  displayMessage(errorMessage)
}

We now have two variables representing our error condition: isErrorState and errorMessage. When that happens, it’s trivially easy to put the app into one of these illogical states:

  • We’re in an error state… but there’s no error message?!
  • We’re not in an error state… but there’s an error message?!

Common sense says they should both either be truthy or falsy. A disagreement is problem.

Rather than creating both a boolean and a string, a pattern I prefer is to let the string’s presence be the boolean.

if(errorMessage) {
  display(errorMessage)
}

An Example: App Configuration

Fertile ground for this mistake is app configuration. Consider a boolean in the environment called SENTRY_ENABLED and a string SENTRY_URL. This design makes it easy to put the app in state where Sentry is enabled, but has no URL. A better choice is to let the presence of SENTRY_URL tell us whether Sentry is enabled. You can even codify this in a helper method.

def sentry_enabled?
  ENV["SENTRY_URL"].present?
end

An Example: React Data Presentation

Another example is some conditional view logic that looks like this:

// template
canDisplayName() && <p>{displayName()}</p>

// functions
const canDisplayName = () => data.firstName && data.lastName
const displayName = () => `${data.firstName} ${data.lastName}`

The first function, canDisplayName, is a little indirect. Separating the logic that says “can this safely render?” from the rendering is redundant; both functions “know” the same things.

Here’s a version where the presence of data becomes the boolean.

// template
displayName() && <p>{displayName()}</p>

// functions
const displayName = () => {
  if(data.firstName && data.lastName)
    return `${data.firstName} ${data.lastName}`
  }
}

The presence of firstName and lastName returns a string like "Jake Worth" or undefined. Hence we get truthiness and falsiness and display data in one function.

This becomes advantageous when displayName needs to change. Instead of two or more functions all reading the same data, there’s just one.

For further exploration, check out Matt Pocock’s State Management: How to tell a bad boolean from a good boolean. I’ll conclude with a quote from that post.

Bad booleans represent state. Good booleans are derived from state. — Matt Pocock

What are your thoughts on data as a boolean? Let me know!


Join 100+ engineers who subscribe for advice, commentary, and technical deep-dives into the world of software.