Confusing bool(ean) variables
Pretty much all of us has done something similar to this:
bool isAvailable = true; // Is something in stock?
if (isAvailable) {
System.Console.WriteLine("Not Avaialble"); // Uh oh
} else {
System.Console.WriteLine("Available");
}
// Prints... "Not Available"...???
...or, an accidental reversal of the if
logics.
This one is very simple as the only mistake is the swapped labels. However, if the content inside of the if
gets bigger or in the case of else
being no-op, you may start to make this kind of mistakes. Heck, I still do it.
But I wanted to put a stop to it and looked back all the code for the project I was working on. There I found a potential way that I can prevent some of the errors - defining a more robust naming convention.
Of course, this is not the silver bullet - some of you may even think that what I'm about to write is more confusing than ever! So use this convention at your discretions.
Naming the boolean values
Variables with type boolean can only take two values: true
and false
. For this reason, most of the use-cases are to store some state that can be answered by YES/NO.
Such nature of boolean usually leads us to naming them like:
is....
has...
can...
This is my base convention. When I declare a boolean value (be it local var or property,) I always prepend it with a be
or an auxiliary verb.
This part is not much of the problem, however. It is the next part of the name that I found a potential problem.
Words that explain states
The part in question is a word or a phrase that explain what state the variable is supposed to mean. Let me call that part "State Words." I reckon that there are three categories for state words. Two of them being: Positive Words or Negative Words. E.g.,
- Positive words
- Available
- Succeeded
- Negative Words
- Unavailable
- Failed
I have found that improper mixing of those category leads to a burst of human error in writing codes for me.
Mixing the Categories
When the values refer to different states and those values use state words from different categories, it won't be an immediate problem. It may be naturally done for the simplicity or the readability of the logic/code.
using System;
bool hasFetchFailed = false; // Negative
bool isAvailable = false; // Positive
if (hasFetchFailed) {
Console.WriteLine("Communication failed?!?");
return;
}
if (isAvailable) {
Console.WriteLine("Available");
} else {
Console.WriteLine("Not Available");
}
But they still may become problematic once you start mixing them together.
if (!hasFetchFailed && isAvailable) {
// is this when the fetch has failed or not? It is hard to deduce it within a second
// and also, we'll have a bad time when we try to reverse this expression.
}
And all the hell breaks loose when those variables points to the same state, but the state words used is from different categories. This situation is much more annoying as it occurs across the code within the project, like in different classes or methods. When the state is very important in the project, referring to it using both positive state words and negative ones is just asking for problem.
class A {
bool hasSucceded; // This bool uses positive state word
}
class B {
bool hasFailed; // but this one's negative!
}
As I found those cases in my code base, I came to a conclusion that I probably should decide which category to use for common states, and for others, I should decide once and stick with my decision all the way. Below is an example, but you could also prohibit one category altogether (although this is a bit too extreme.)
Ex)
State | Category | State Word(s) | Reason |
---|---|---|---|
Communication Result | Negative | failed | enables early return without negating the value |
Stock availability | Positive | available | Less prone to make mistakes when writing code for Views |
What about the last category?
At the start, I mentioned that there are three patterns for state words. The last one is, of course, words that does not fall within either of them.
Since this category is pretty much the very reason I wrote this article, allow me to explain my specific situation.
I created a rhythm game called Twin Horizons, which is played with two sets of four lanes that exist on the top and the bottom. This game provides "Full Lanes" mode where you use all the lane and "Half Lanes" mode where you use only the bottom four. Those modes are called lane styles.
And this game contains a logic where it is important to know which lane style the player has played. It is when I was looking back such part of my code base that I found something like this:
// This value exists as the parameter from the other scene
bool isHalf = ???; // by which I mean "Is the player playing in Half Lanes mode?"
// ...which is used later down the logic.
int rewardCoin;
if (isHalf) {
rewardCoin = 700;
} else {
rewardCoin = 800;
}
This "state word" is not even positive or negative!
And then I remembered that this very state word was causing all kinds of trouble when I was working on this part.
Let me put it in this way: What does isHalf == false
even mean???
Well, I just explained what the game was, so we may have some idea, but can anybody, like literally anybody that knows nothing about the game realize that isHalf == false
means that the player is playing in Full Lanes mode?
if (!isHalf) {
// *We* know that this part is run when the "Full Lanes"
// is played, but can *everybody& know?
}
What makes this matter worse is that this value is passed as a part of a struct
that contains the information from the other scenes (for context, I use Unity for this game.) As the definition cannot be changed easily, we are locked down to using either isHalf
or isFull
.
If in some unfortunate situation where the procedure that run only on Half and the one on Full resides in the same scene, we're gonna be in a big trouble.
Some of you may have noticed: it may not be advisable to use boolean in this case. The sheer fact to express "is the player playing with Half Lanes style?" was wrong. The fact that these would be pretty much the only two lane styles in the game for foreseeable future did not help at all.
So to avoid the confusion altogether, I decided to ditch bool
and use enum
.
enum LaneStyle {
Half,
Full,
}
LaneStyle style;
This forces me to write which style I'm talking about which reduces the amount of confusion.
if (style == LaneStyle.Half) {
// 100% for Half Lanes
}
Conclusion
We can name variables virtually however we want, and that flexibility makes us make bad choices. So how about purposefully restricting how we name them to avoid that?
- Can anybody immediately know what the reverse of the state words mean?
- If yes... (e.g., Available --Negated--> Unavailable)
- Variables that points to the same state should be using the same state words - don't mix words from both categories
- If no...
- Consider not using boolean and try enum
Rules simple as this may help you write readable code and avoid human errors.
Extra talks (rants?)
-
!
for negating bool being somewhat easy to miss
if (!isPlayable) {
// I sometimes get confused b/c I did not notice
// the "!" at the start because the font is bad
// And when "!" is in between parentheses, well......
}
- When negating a boolean property of a class instance, the
!
gets physically farther from the actual property name
if (!instance.isActive) {
// When you only read `isActive` part...
// well, say goodbye to your sanity
}
Top comments (0)