QM Bites – The two sides of Boolean Parameters

QM Bites – The two sides of Boolean Parameters

By Matthew Wilson

Overload, 23(130):16-17, December 2015


Boolean parameters are tempting but make life difficult. Matthew Wilson advises us to avoid them (almost) all the time.

QM Bites - Introduction

Welcome to QM Bites!

Those gentle readers of patience and good memory will remember that I write the Quality Matters column in this journal, only I haven’t done so in quite some time. The problem is a simple one: I’m stuck halfway in my exceptions series, I’m a perfectionist (and not in a good way, in truth), and I haven’t been able to get past my commitment to finish the series and move on to the many other topics I’d planned (and still intend) to cover.

Our patient editor, Frances Buontempo, has offered gentle encouragement from time to time, and very recently had the liberating (for me) insight that I should write about other things until my exception-mojo is fully charged. Further, I’ve just taken on a new long-term role as Application Architect for a company that does extremely high-performance software (in many technologies, but mainly C++), with a remit to transform and modernise. This means I’m going to have a tremendous amount of new material to draw on and huge motivation to rekindle my previous intentions to wander the software quality landscape dropping my magic pixie dust.

Thus: QM Bites. This new vehicle will let me guarantee my contributions to every (or most) Overload issue, usually two or three Bites and the occasional full-size Quality Matters instalment when I’m able. It’s win-win, baby! ;-)

Recap

I’ll be relying on a host of previously discussed topics in the Bites. As I examine each one, I’ll provide a short definition, reference to previously discussed points in QM, and relevant references to established works.

TL;DR

Even prior to the advent of the Twitter age I was informed with disheartening frequency that my written prolixity was enervating to an unsettling and, often, self-defeating degree. As a consequence, not only will I be putting very real effort into being succinct, I will also pander to the 140-character generation by including a pithiest-possible executive summary at the head of each Bite. (Sigh!)

TL;DR

Writing fns with bool params quick&easy; costs maintainers of cli-code far more effort than U save

Bite

As I’ve discussed previously on a number of occasions ([ XSTLv1 , QM#1 , QM#2 ]) and as is evident from deductive reasoning alone, combinations of characteristics of software quality are often in conflict: expressiveness vs efficiency ; efficiency vs portability ; and so forth. This is not always the case, however, and usually the sub-divisions of the composite characteristic discoverability & transparency (see sidebar) collaborate well and, further, tend to also to work well with others, especially modularity , but also (depending on how good is the design of the given component) with expressiveness , flexibility , portability , correctness / robustness / reliability , and, even, efficiency .

However, sometimes these very collegial subdivisions work against each other. In my experience, the most common example of this is when it comes to using Boolean parameters.

Consider a programmer tasked with writing an API for the manipulation of fonts, such that one is able to create a font from a base family along with selecting emboldenment, italicisation, underlining, and superscripting. The API might look like the following:

  Font CreateFont(string family, bool bold, bool
  italicised, bool underlined, bool superscripted);

From the perspective of discoverability of the API, this is great: As a user I specify the family, then each of my (Boolean) choices as to whether it is emboldened, italicised, underlined, and superscripted. What could be clearer?

Similarly, the transparency of the implementation of this is likely to be high, since the name of each of the parameters clearly indicates its intent.

Definition of Discoverability & Transparency

Discoverability is how easy it is to understand a component in order to be able to use it.

Transparency is how easy it is to understand a component in order to be able to change it.

However, the problem comes in the transparency of the client code . What does any of us know of the majority of the intended semantics of the following statement:

  Font f = CreateFont("Courier", true, false,
  false, false);

This violates one of the most important of the Principles of UNIX Programming (PoUP) [ AoUP , XSTLv1 ]:

Principle of Transparency : Design for visibility to make inspection and debugging easier.

If I want to understand the statement in the client code, I have to look at the API. The use of booleans has made me do work I should not need to do in an ideal world. Thus, there’s another PoUP violation:

Principle of Economy : Programmer time is expensive; conserve it in preference to machine time.

(NOTE: I’m not even going to touch on the nightmare of what happens if the API designer decides to reorder some of the parameters …)

So what’s the humble programmer to do? The answer is simple to state and, at least for those languages that support enumeration(-like) types, straightforward to implement: make each parameter be of a different type.

API:

  Font CreateFont(string family, Emboldenment bold,
  Italicisation italicised, Underlining underlined,
  Superscripting superscripted);

Client-code:

  Font f = CreateFont("Courier", Emboldenment.Bold,
  Italicisation.None, Underlining.None,
  Superscripting.None);

For certain, this is somewhat more effort to write (although if you have an Intellisense-like editor it may well be less effort and faster). But without a doubt your maintenance efforts will be massively less.

Note that this phenomenon doesn’t even have to involve multiple parameters. One of my longest standing mistakes in this respect was in the constructors of reference-counting smart pointers, as seen in listing 1.

// namespace stlsoft
  template <typename T>
  class ref_ptr
  {
    . . .
  public: // Construction
    ref_ptr(
      T* pt
    , bool addRef
    );
    . . .
			
Listing 1

To be sure, when looking at uses of this in client code you don’t have the ambiguity of multiple parameters, but you still have to know what the second parameter of stlsoft::ref_ptr ’s constructor does. And it’s harder to grep your code for reference copying vs owning in a codebase.

So, the advice is: Avoid Boolean parameters (almost) all the time.

References

[AoUP] The Art of UNIX Programming , Eric S. Raymond, Addison-Wesley, 2003

[QM#1] Quality Matters: Introductions and Nomenclature, Matthew Wilson, Overload 92, August 2009

[QM#2] Quality Matters: Correctness, Robustness, and Reliability, Matthew Wilson, Overload 93, October 2009

[XSTLv1] Extended STL, volume 1: Collections and Iterators , Matthew Wilson, Addison-Wesley, 2007






Your Privacy

By clicking "Accept Non-Essential Cookies" you agree ACCU can store non-essential cookies on your device and disclose information in accordance with our Privacy Policy and Cookie Policy.

Current Setting: Non-Essential Cookies REJECTED


By clicking "Include Third Party Content" you agree ACCU can forward your IP address to third-party sites (such as YouTube) to enhance the information presented on this site, and that third-party sites may store cookies on your device.

Current Setting: Third Party Content EXCLUDED



Settings can be changed at any time from the Cookie Policy page.