BOOL parameters are evil
Boolean parameters are everywhere. In public APIs all the way down to private internal functions, code like this is ubiquitous:
SaveData ("Bleg", TRUE);
TRUE mean here? What does
TRUE mean when dropped in the middle of a larger parameter list? A BOOL parameter is like a semantic bomb: hen you see a literal truth value, you have to stop what you’re doing, refer to the context, the documentation of the function, or perhaps more desperate measures to figure out what effect the word has. Everyone who’s been programming for more than a few weeks has been frustrated in this spot.
It’s because of this frustration that I’m going to be a heretic and say “no” to BOOL. If you find yourself writing “BOOL” in a parameter list, stop yourself. You’ll be happier later:
SaveData ("Bleg", SAVE_DATA_DO_NOT_OVERWRITE);
A better alternative
BOOL is just a poorly-named enumeration. Consider CreateEvent. It has two BOOL parameters: bManualReset and bInitialState. If instead of BOOLs, there parameters were enumeration values — say EVENT_MANUAL_RESET, EVENT_AUTO_RESET, EVENT_SIGNALED, EVENT_RESET — then calling code would be much easier to understand. The effect of the call would be immediately apparent from the text of the program. It’s important to note that the generated machine code is equally efficient†: the processor doesn’t care whether an integral value comes from a boolean or an enumeration. By the time the processor gets to it, its type information is gone.
Using enums is better than BOOL, but we can actually do better still: each of CreateEvent’s two BOOL parameters conveys only a single bit of information. We can combine them into a single flags parameter, resulting in code that remains clear to a human reader while being more extensible and arguably more efficient than the original. Our new flags parameter can be extended to support more behavior without changing the function signature, cutting down on API churn.
- Use BOOL, bool, __bool, MyBool, and so on in function parameter lists.
- Use many parameters when only a few would do.
- Replace BOOLs with either enumerations or flag parameters.
- Give meaningful names to values passed to functions. TRUE and FALSE tell the reader nothing.
† Yes, a BOOL is one byte wide, while an enumeration (on Windows) is
four bytes wide. The difference doesn’t matter in practice, but
even if it did, one could specify BYTE‡ in a function prototype instead of an enumeration
type, but nevertheless document that callers should specify
named constants for that argument .
‡ Yes, it’s possible to pass meaningful named values for a BOOL argument too. But the word
“BOOL” is just an invitation to pass TRUE and FALSE. At least BYTE
says, “I’m different”.