In situations where you have a variable that can assume (for now) two possible states, it is often tempting to represent these with a Boolean variable. Especially when one state is (or seems to be) the inverse of the other.
Unless the states are "true" and "false" (which themselves can be supplemented--see ThreeValuedLogic), this is often an AntiPattern.
It's often better to use enumerations, or something similar, for this case. Use of enums gives you the following advantages:
I don't really agree. If the variable name is "isAlive", it's not really ambiguous whether true means alive or dead, is it? And it would make no sense to add a third state to "isAlive". If you want to change the entire semantics of the variable (say, from "isAlive" to "state" = [dead|dying|being born|alive]) that's a much bigger change than just adding a possible value. Anyway, you wouldn't search for "true" or "false" anyway, you'd search for "isAlive", obviously. Complicating things that are obviously binary, oppositional states seems like a clear case of YouArentGoingToNeedIt
When the scope of a variable is limited to within a single method or a simple class, the value of this can be questionable.
The biggest documentation and clarity benefits come from when you apply this to the external interface of a class - especially the methods.
For example, consider this:
List myList = new ObjectList?( true); List myOtherList = new ObjectList?( false);What does the true parameter mean? How do the two lists differ? (Some of you may be able to guess if I tell you that this is a transliterated example from real life code in BorlandDelphi.)
Using an enumeration instead makes things much clearer:
List myList = new ObjectList?( ListType?.OwnsObjects?); List myOtherList = new ObjectList?( ListType?.ReferencesObjects?);-- BevanArps
The downside of this is that class definitions become packed with 2-valued enums which sort of distract you and make the class seem impenetrable. Many times the benefits outweigh this downside, but sometimes I think it's worth using a boolean if you can come up with a good name for the variable. Especially if the variable is only used in one method or close family of methods, it's obvious from the context what 'true' and 'false' represent.
For example, move up until we reach the top, then move down until we reach the bottom, then...:
void move (float amount) { if (movingUp) moveUp (amount); else moveDown (amount); } void moveUp (float amount) { position += amount; if (position > MAX_POSITION) { position = MAX_POSITION; movingUp = false; } } void moveDown (float amount) { position -= amount; if (position > MIN_POSITION) { position = MIN_POSITION; movingUp = true; } }
How about:
void move(float amount) { switch (direction) { case DIR_UP: position += amount; if (position > MAX_POSITION) { position = MAX_POSITION; direction = DIR_DOWN; } break; case DIR_DOWN: position -= amount; if (position < MIN_POSITION) { position = MIN_POSITION; direction = DIR_UP; } break; default: break; // Uh-oh?? } }This allows for possibilities other than DIR_UP and DIR_DOWN, like DIR_STATIONARY...?
I'm confused, there seem to be two different arguments going on here. The ones who dislike booleans seem to be talking about passing them as paramaters to methods, while the dissenters are talking about local variables. If so, you are both correct. Passing a boolean as a paramater is confusing, enums are better, seeing anObject.Method(true, false, true, true) is annoying and more difficult to maintain. But in the context of local variables within methods, the variable name alone carries all the info you need, so enum is going overboard.
Ah, the voice of reason! In that light, yes, I agree with all opinions on this page! The discussion can probably be refactored into a clearer description of the "pattern" at the top. -- The guy who said "I don't really agree" uppage
I concur. I use both enums and booleans depending upon how I feel at the time. I will start with one type, change my mind days, weeks, years later and change to the other. Frankly, I am too lazy to create an enum where a boolean is satisfactory. I don't want to type in the extra definition, nor have to look back at the definition when I need to use it. I am also too lazy to combine booleans to create higher level meaning. I don't want to type in multiple, related booleans, nor have to look back at the boolean definitions to figure out the necessary combination when I need to use them. Both have their place, but there is not a clear dividing line between the two. Use whatever strikes your fancy at the time. You can always change your mind later.
A good rule of thumb seems to be: When use of a boolean would obscure the meaning of the code (such as the anObject.Method(true,false,true,true); example), enums are to be preferred. When both forms are equally readable, use either--booleans have the advantage of DoTheSimplestThingThatCouldPossiblyWork.
A second good rule of thumb seems to be: If the logical two-state datatype is used extensively throughout the code, consider making it an enum. If it's a local variable within a function, don't bother.
A third rule of thumb: If you aren't planning to use a variable as a boolean (i.e. apply boolean logic) then it probably should be an enum - types carry meaning.
See also UseEnumsNotNumbers