Jake Worth

Jake Worth

Presence is Boolean

Published: January 24, 2022 2 min read

Here’s a problematic pattern I see a lot in frontend code:

// 1. Network request returns error
// 2. Our code sets `isErrorState = true`
//   and `errorMessage` to the error's message 

// 3. Display logic
if(isErrorState) {
  displayMessage(errorMessage)
}

When you split isErrorState and errorMessage in two, it’s very easy to accidentally put the app into one of these states:

  • There’s no error message… but the we say we’re in an error condition
  • We say we’re not in an error condition… but there’s an error message

If isErrorState is true, then there ought to be an error message, and vice versa.

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

if(errorMessage) {
  display(errorMessage)
}

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

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 render?” from the logic that says “please render” is unnecessary. 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 shines 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 this? Let me know!


Get better at programming by learning with me! Join my 100+ subscribers receiving weekly ideas, creations, and curated resources from across the world of programming.