Boolean Arguments are BOOL-Shit

“All generalizations are false, including this one.”
— Mark Twain

In programming, little is as obscure as code that passes boolean literals to functions.

As an example, consider the following invocation of a method that sets logging options on a logger object:

What does this really mean? Even looking at the declaration of ‘setOutputControlMode’ doesn’t give a satisfying answer:

You need to delve into the implementation of the ‘Logger’ class to really see the intent:

There you go! After calling ‘setOutputControlMode’ with ‘true’ as the first argument, subsequent logging will additionally go to ‘stderr’; passing ‘true’ as second argument will automatically append a newline character after every log statement.

While you could argue that the wishy-washy name of method ‘setOutputControlMode’ was badly chosen, it was probably done so to accommodate even more options in the future. I’m convinced that sooner or later another boolean parameter will pop up — ‘buffered’, to specify whether logging should be buffered or not.

How should you deal with such obviously inferior interfaces? The strategy depends on whether you own the offending code or not. Let’s start with the first case, where you’re using some 3rd party library that you can’t directly modify.

HIDING THE DIRT

First of all, make it a habit to never feed these boolean monsters with boolean literals. Don’t even do this if the method is part of a standard library, like Java’s ‘Component.setVisible(boolean b)’ method. Stand your ground and shame the original author by working around it. But how?

One easy solution is to define a couple of boolean constants in your code:

At the expense of a little bit more typing, code that calls ‘setOutputControlMode’ becomes much more expressive:

The only risk that’s not mitigated is that one can still confuse the order of arguments. After all, the compiler will happily accept this slip:

Which is, of course, not what the developer had in mind.

A safer approach is to use wrapper functions. This is particularly useful if you don’t need all flag combinations in practice. Let’s assume you always want to emit newlines at the end of every log entry and only sometimes want to enable/disable echo to ‘stderr’. All you need to do is define two straightforward helper functions in your own code base:

Using these wrapper functions is both, highly readable and safe:

AVOIDING THE DIRT

If you can modify the source code, you have even better options. Let’s assume that a colleague of yours developed a GUI framework that has the same weakness as Java’s java.awt.Component class; that is, it provides a method which takes a boolean argument:

Now, there’s probably tons of code that uses this method, as ugly as it may be. In order to maintain backwards compatibility, I would designate ‘setVisible’ as deprecated and add two wrapper functions to your colleague’s class which clearly communicate their intend:

If backwards compatibility is not an issue or if you’re designing a completely new method, you should do it the right way, and the right way is to use enums instead of booleans:

In exchange for roughly one additional minute of work for the developer, everyone gets a readable interface:

It’s a given fact of programming, that when there are two states or modes, it won’t be long until a third one pops up. No problem, if you used enum parameters from the outset:

In the visibility example, we have mutually exclusive modes. In the ‘setOutputControlMode’ example, however, options can be combined. Still, enums are a pragmatic solution:

Notice that I added the suffix ‘FLAGS’ as a hint to the reader that these options can be freely mixed with the binary OR operator:

This, of course, only works in plain C. A C++ compiler will complain that the integer result that operator ‘|’ yields cannot be converted back to an enum type, so in order to please your C++ compiler you have to apply a ‘static_cast’:

Such casts are never pretty, but when they get the job done, they’re acceptable.

Let me bring this post to a close by driving home the following guidelines:

1. Never pass boolean literals (‘true’/’false’) to functions. Define meaningful symbolic constants instead.

2. Alternatively, consider writing wrappers around functions taking boolean arguments. Remember that the best (most readable) functions take zero arguments:

“The ideal numbers of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification ‐ and then shouldn’t be used anyway.”
— Uncle Bob (“Clean Code”)

3. If you are the author of a method that takes options, spend the effort and code dedicated, niladic setters. If that doesn’t feel right, use enum parameters. But on no account should you ever resort to boolean arguments.

Comments (0)

› No comments yet.

Leave a Reply