The Dying Art of Pragmatism in Software Development
Wednesday, January 29, 2020

If you've read my article The Stigma of Simple Software, you know that I'm a big proponent of keeping things simple... and this includes making design decisions. Now obviously, I'm not advocating throwing things at the wall and hoping they stick. I'm advocating being pragmatic.

From The Pragmatic Programmer (Andrew Hunt, David Thomas):

In order to be a Pragmatic Programmer, we're challenging you to think about what you're doing while you're doing it. This isn't a one-time audit of current practices--it's an ongoing critical appraisal of every decision you make, every day, and on every development. Never run on auto-pilot. Constantly be thinking, critiquing your work in real time.

This is generally sound advice, but "critically appraising every decision you make" does – at its core – fly a bit in the face of being pragmatic (where we're urged to make decisions based on what makes sense practically). Practically speaking, not every decision warrants such critical scrutiny.

One debate that I think is really an example of well-intentioned pragmatism gone off the rails is that of "boolean parameters are evil". Martin Fowler has written about this, as have many others.

The gist of the argument is exactly what it sounds like: using boolean parameters for functions is a bad thing. Doing so can negatively impact readability and cohesion, can make the underlying function messy, and can violate other design principals. As one pundit put it:

A Boolean Parameter effectively permits a method's caller to decide which execution path to take. This is a case of bad cohesion. You're creating a dependency between methods that is not really necessary, thus increasing coupling.

from https://github.com/troessner/reek/blob/master/docs/Boolean-Parameter.md

First off, the same argument could be made about any number of parameter types. A function such as MakeApiRequest(string url, bool useHttpPost) could just as well be MakeApiRequest(string url, string getOrPost) or MakeApiRequest(string url, HttpGetOrPost method). Each one of these functions is allowing the caller to determine an execution path at some point.

A commonly-cited example of an "evil boolean" is a function which displays a dialog box and takes a boolean parameter such as "showAnimated". Some folks will argue that this is a problem and that there should instead be both a ShowDialog and ShowDialogAnimated function, for example. Someone will undoubtedly cry, "Single Responsibility Principle! SRP! That function should be doing one thing only!" And that's where I feel that things start to get a bit silly.

Without knowing the underlying implementation that displays the dialog box, it's unfair (and unwise) to make a blanket statement that using a boolean "showAnimated" parameter is the wrong design decision.

Nonetheless, to appease our critics, we take our ShowDialog method and split it up into two methods. Once we've done that, we point out how much more "SRP" we are now – as well as how much less DRY (don't repeat yourself) we are. In an effort to "do one thing" (and to avoid an evil boolean), we duplicated some amount of code between the two methods. At this point, the discussion could go any number of directions (or could just fall apart altogether...)

Now, don't get me wrong. If a boolean "doItTheOtherWay" parameter (here, showAnimated) causes the implementation to go down two drastically different code paths – or, as in Fowler's example, causes a lot of interleaving checks for if (doItTheOtherWay) – then sure, maybe a boolean parameter in this case isn't the best approach and two separate methods would be preferable. To use one example, however, as a guideline or mantra (boolean parameters are evil!) is simply not being pragmatic. Just because there are cases where using a boolean parameter may not be the best option, this is no reason to declare boolean parameters evil – or even a "code smell" for that matter.

Some will argue the point from the perspective of code readability. "I see the call to ShowDialog(true), but how am I supposed to know what 'true' means here? I don't want to have to look at the implementation/docs/etc. to find out!" Well, my short answer to this is, "That's your job."

Some will argue that a more-readable enum should be used instead: ShowDialog(DisplayMode.Animated). Sure, this is more apparent on the surface, but does it really matter here? Is introducing a new enum simply to avoid using a boolean really necessary? Is it really practical?

So, we rub our magic lamp, a genie pops out, and we wish for no more evil boolean parameters. Poof! Wish granted. We scroll down a few lines, however, and we find this:

DisplayAsciiBanner(80, 25, 2);

Now what? Declare int parameters evil? Where does the madness end?

With respect to readability, the two examples are really no different: in both cases, we need to check something (Intellisense, the function signature, docs, whatever) to determine what the parameters represent. "true" means nothing more or nothing less here in ShowDialog than do 80, 25, and 2 in DisplayAsciiBanner.

Sure, something like this (if/when supported by the language) would be nicer, perhaps:

DisplayAsciiBanner(targetWidth: 80, targetHeight: 25, lineSpacing: 2);

Tools like ReSharper can provide this insight automatically for you if not done explicitly in the code. But again, if you're expecting to know what every line of code is doing without having to dig a bit, you may need to re-evaluate your expectations.

Part of being pragmatic is keeping in mind that nothing is cut-and-dried, so trying to blindly adhere to SRP, DRY, etc. because "that's the right way to do it" is basically the antithesis of being pragmatic. Being pragmatic requires us to realize that everything is a balancing act: Will adhering to SRP violate DRY? Will adhering to DRY violate SRP? Does it matter in a given instance?

If you're a student or a hobbyist programmer and you go through these types of exercises strictly for the theoretical insight, then more power to you, I say. As a professional programmer, however, part of being pragmatic is asking yourself, "does it matter?"

In the time you spent thinking about whether to use a boolean parameter or two separate methods, then checking opinions on Stack Overflow, then going down the rabbit hole with articles about evil boolean parameters, you could have written one version of the code, refactored it 180 degrees, come to the realization that it doesn't really matter in your case (both approaches work just fine and are equally easy to read and maintain), and been on to other more pressing items.

Being a truly pragmatic programmer is about more than simply critiquing our design decisions – it's about knowing which decisions are worth spending the time and effort to critique.

Blog engine and all content © 2024 Jason Plackey