The dragon’s lair

On optional booleans

In programming, a “boolean” is a data type that is either true or false. An “optional” is a wrapper around a data type that indicates that the value may or may not be present. Thus, an optional boolean has three possible states:

  1. true
  2. false
  3. null

Typically, an optional boolean is used to represent a state where the records might be incomplete. registered may indicate whether a user is already registered (true if they are, false if they are not), allowing for the information to be missing (in which case it’s null).

Of course, true, false, and null are just words. Any property with exactly three possible states can be encoded with an optional boolean. However, it might seem that one has to sacrifice readability in order to force most three-state properties into an optional boolean.

In my reading tracker app, I have a reading_status property which has three possible states:

  1. to_read
  2. reading
  3. finished

I could definitely use an optional bool for that, but what does reading_status: null really mean? I could do the mapping in my head, but chances are, if I look at my code a few months later I will be confused.

Luckily, I found that in more cases than not, the name of the property can make the optional bool perfectly readable. Instead of calling my property reading_status, for example, I could call it finished_reading. In that case, true obviously corresponds to finished, false to not finished (i.e. currently reading), and null to “not even engaged in the process of reading, so the question if I have finished does not make sense” (to_read).

Then, if we abstract away from true, false, and null, an optional boolean nicely represents a three state mapping in which two of the states are tightly connected to each other, with the third one being a conceptual outlier or a middle ground.

Could we really force all three state properties to this conceptual paradigm? Most certainly not, but I have been pleasantly surprised at how many of them do lend themselves to such conceptualization with very little in the way of “forcing”. Here are some:

All of these are, in my opinion, very readable. It is reasonable to ask, however, “to what benefit?”, i.e. why not just encode things in simple strings: “to_read”, “reading”, “finished”?

One practical benefit is consistency by constraint: if my reading tracker app stores things in strings, another app that operates on the database, even if written by me, might unintentionally store “reading” as “currently_reading” (as Goodreads does). Now I have four unique strings in that column, which is a pain. What’s worse, I may not even notice, so my SQL queries will be missing some of the rows.

More importantly, it forces me to think about the naming of the properties. Thinking about names forces me to better understand the concepts that I am dealing with. It also lets me build connections between concepts. Aristotilean actualization seems to fit an optional boolean, but Christian Trinity certainly doesn’t.

Finally, of course, it is pretty neat in its own right.