Not all binary state is boolean
Boolean types represent binary state: true
↔false
, 1
↔0
, on
↔off
.
But just because boolean types are technically capable of expressing binary state, they may not always be an ideal choice from a semantic point of view.
Consider the following Java interface, which describes the view state of a graphical user interface by means of two boolean methods:
interface UserInterface {
boolean hasFocus();
boolean isDarkModeEnabled();
}
In my book, a boolean
type would be an appropriate choice for hasFocus()
. However, for isDarkModeEnabled()
, I would prefer a different modelling approach:
enum ColourScheme { LIGHT, DARK }
interface UserInterface {
boolean hasFocus();
ColourScheme getColourScheme();
}
When evaluating whether to use a boolean type, I ask myself two questions:
- Is my state binary by nature or binary by accident?
- Can the inverse state be clearly deduced?
Whether or not a UI window has focus is binary by nature. There is no possible third option, and the answer can never be something in between, like “it’s a little bit focussed”.
In contrast, the colour scheme is binary by accident. While there may only be two options available right now (“dark” and “light”), it’s easy to imagine how we could extend the list of colour schemes as we please – think: “no colour”, “colourblind-friendly”, or “user-defined”.
It’s also not strictly obvious what the inverse of “dark mode” would be. If isDarkModeEnabled()
isn’t true
, we can at best infer that the user interface must probably be in “light mode”.
if (!userInterface.isDarkModeEnabled()) {
// Ok, so the UI mode isn’t dark...
// But what is it then?
}
Using a named return value, in contrast, makes the call-side code clear and expressive:
if (userInterface.getColourScheme() == LIGHT) {
// Ah, it’s light!
}
A by-effect of the enum
approach is that it doesn’t involuntarily overemphasise one option via the method name, but it rather presents all possible states as equal choices.