All Posts

Naming guidelines for boolean variables

By Erik Uzureau and Cameron Yick

There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors - Leon Bambrick

Debugging happens through manipulating mental models before we change actual lines of code. Names are impactful because they create the mental pictures used when problem solving.

Booleans are among the simplest data types - they only have two possible values, true or false. However, this does not mean that everyone agrees on how to name them! This post will explain the reasoning for naming boolean variables and property names using two simple guidelines:

  1. Avoid negatives in names for standalone variables
  2. Always choose names that enable setting “false” by default

Guideline 1: Avoid negative names for standalone variables

When naming booleans, you should avoid choosing variable names that include negations. It’s better to name the variable without the negation and flip the value. If you absolutely can’t (see Guideline 2 below), then try to find an already-negated form of the concept you are trying to express.

In practice, what this really means is avoiding variable names that contain “not”, “no”, “never”, “won’t”, “doesn’t”, etc. (See this nice list on Grammarly).

Example:

You need a local boolean variable to store whether an array has any values in it, so you can warn the user. Since your action will be triggered when the array has no values, you might be tempted to call your variable “hasNoValues”… something like this:

10: const hasNoValues = myArray.length == 0;

22: if (hasNoValues) {
23:   warnUser();
24: }

Stop right there! While that may appear to make your conditional cleaner, you’ve just given the reader of your code an extra cognitive load. Reading this code now requires performing logical negation twice: once on line 10 when the variable is assigned, and then below again on line 22 when it’s used. Sorry reader.

In cases like this, there are two different ways to spare your reader this cognitive burden:

  • Best: remove the negation
10: const hasValues = myArray.length > 0;

22: if (!hasValues) {
23:   warnUser();
24: }
  • OK: Choose a positive version of values:
10: const isEmpty = myArray.length == 0;

22: if (isEmpty) {
23:   warnUser();
24: }

But don’t take our word for it! Avoiding negations in variable names is a well known “clean code” guideline. You can see this guideline supported and lots of other great tips in Better Boolean Variable Names and Tips on naming boolean variables. It’s even formalized as a rule in these projects: OpenStack API, Eclipse Foundation, and Petroware.

Guideline 2: Always choose names that enable setting “false” by default

While we strongly believe that it’s good to avoid negative boolean variable names whenever possible, there are exceptions to the rule.

One exception is when your boolean is optional (e.g. an optional property in an object/widget constructor or an optional parameter to a function). In this case, we recommend choosing a variable name such that the default (or unspecified) value of the option will be “false”.

Since we are restricting the variable’s value, we have less liberty with choosing the variable name. If the positive name won’t work with a “false” default, this is the time to use that “already-negated form” we mentioned in Guideline 1. If one does not exist, and the only viable option is using a negative variable name, then so be it!

An example:

Imagine we are creating a new widget. In some cases, clients will need to initialize the widget in a disabled state at creation time. This is just an option, and the majority of users will want the widget to be enabled by default.

If we follow Guideline 1, our reflex will be to stay positive and call this property “isEnabled”. We’ll have code like this:

class MyWidget(isEnabled) {
  ...
  isEnabled = true; // Widget is enabled by default
  ...
  doSomething() {
    if (!this.isEnabled) {
      return;
    }
    foo();
  }
}

As a reader of this widget’s API, when I see isEnabled, I might assume it is an important property that must be set:

var foo = new MyWidget(isEnabled=true)

But if it’s just an option, then the client shouldn’t have to bother with it at all:

class MyWidget(isDisabled) {
  ...
  doSomething() {
    if (this.isDisabled) {
      return;
    }
    foo();
  }
}

Now the reader sees isDisabled and knows it is an option, so it can be initialized simply:

var foo = new MyWidget()

Some benefits we received from choosing default-to-false names:

  1. No Double Negatives: We avoid double negatives, because these overridden properties would only be ever assigned to the value of “true”. (See “implicit default” above). Note this is a guideline in Standard English, but isn’t true across all spoken languages.

  2. Implicit Default: In many languages, the absence of a boolean property is interpreted as if the property were false (e.g. Javascript / Python). Optional properties with false defaults mean there’s no need to explicitly declare the default value in the code. We are also absolved of the responsibility of documenting the default value. All this means fewer details for the reader to process in order to understand how your widget works.

  3. Convenience through Convention: Users of the widget get consistent behavior where they can assume that all optional properties are set to false. This is preferable to having an inconsistent mix of true and false possibilities, and helps people understand how a widget behaves without needing to inspect the documentation or source code.

A great example of this rule in practice is how boolean attributes are handled in HTML.

Consider the default values for these attributes:

  • autofocus
  • checked
  • disabled
  • formnovalidate
  • nowrap
  • readonly
  • required
  • selected

…all false!

That’s not a coincidence; it’s in the spec!

The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.

Sources: w3 spec, html.spec.whatwg.org, and mozilla.org

It’s worth highlighting that several of these attribute names include negatives (formnovalidate or noresize). The value of defaulting to false trumps the cognitive advantage of avoiding negatives in the name.

While we haven’t found any writing from the original authors explaining their decision to follow this guideline (let us know if you find one!), we can only assume it wasn’t an arbitrary choice.

Conclusion - Why names matter

Bugs are not necessarily born from single lines of concentrated error, but the accumulation of multiple papercut-sized points of confusion. Naming conventions that encourage developers to express their intent clearly and concisely enables us to build systems that grow safely and solve problems effectively.

This was the first collaboration post on serendipidata, inspired by follow-ups conversations to a code review topic we noticed recurring at least monthly.