Zen of Defensive Programming: Source Code is Cheap

Now that we’ve covered the preliminaries, it is time to dive into specific examples to illustrate what defensive programming habits you can build to improve your code. More importantly, I’ll also explain, why they are a good choice.

Perhaps the single most important thing to remember is that source code is cheap!

This takes us straight back to the readability pillar. I have worked with a lot of third-party source code throughout my career. From reference implementations to tutorials and examples, to code libraries and entire projects. Not all of it was good.

Poorly formatted source code is prevalent in these projects. Oftentimes they follow odd bracketing and indentation standards and avoid any kind of extraneous spacing. As if saving a space character somehow made the code run faster, the reasoning behind these habits is unclear to me. The visual layout of your source code makes absolutely no difference to the code generated by the compiler, so why make life harder for yourself?

Let me repeat it…

Source code is cheap!

It costs us nothing but a few additional keystrokes to write, yet it can make all the difference in the world. It is certainly cheaper than spending an afternoon trying to hunt down a bug that would have been preventable in the first place. If your code is unstructured and, consequently, unreadable, you may spend hours debugging, trying to locate a defect that may have been caused by a misplaced brace or some mistake hidden in an unreadable expression.

There is absolutely no need to skimp on your source code. Shorter source code does not generate faster programs!

Keeping source code layouts tight is a thing of the past. It used to be necessary during the 80s and 90s when display dimensions and resolutions were severely limited. Today’s displays are detailed enough, wide enough, and tall enough to display many lines of code at any given time. By not properly laying out and structuring your code, you are hurting yourself and your fellow teammates. You have plenty of screen real estate, so make use of it!

Safety through formatting

Take a look at the following C/C++/C#/Java examples. This code…

if ( !value )
  value = 100;

…and this code…

if ( !value ) value = 100;

…is identical to this code.

if ( !value )
{
  value = 100;
}

When you compile it, the resulting machine code will be identical for all three cases. However, one of them is safer than the others. Why? Let’s explore…

The first version can easily introduce a bug if a second operation has to be added to the conditional branch. The modifying programmer could forget to properly surround the new block with braces. It is an easy mistake to make, particularly, if the new operation is added on the same line, giving it the impression as if it were one continuous expression.

if ( !value )
  value = 100; top = 50;

It still looks like a valid expression at first glance, right? But now it is a bug.
The same is essentially true for the second version. If you add an instruction, you will also have to add the braces. Those, however, are easily forgotten and can have far-reaching consequences.

if ( !value ) value = 100; top = 50;

Once again, this may look like good code at a glance but as before, you just introduced a defect.

If you have to switch between languages a lot in your work, as I do, it is easy to accidentally write it like this…

if ( !value )
  value = 100;
  top = 50;

At a glance, you may still overlook the potential bug here because in languages like Python, without braces, the indentation level is relevant. You may not even think about braces at that moment because even though you’re writing C++ code, your brain may not have made the mental switch just yet.

A few extra keystrokes save the day

The good news is that there is an easy remedy to avoid all these mistakes. You can prevent them completely by always putting braces around code blocks in C-style languages. As you saw above, just because the language allows you to drop the braces in certain cases does not mean that you should!

More important than saving a few extra keystrokes is to write safe code that avoids problems—now and for the future. Aside from the risk described above, when encountering a condition without braces, there’s also always the possibility that their omission was unintentional. Imagine you were writing the statement and before you completed it, you got distracted by a phone call. By the time you return to your code, you no longer think about the braces and might simply continue coding under the misguided impression that your statement was complete. It happens!

However, if you make it a habit to always surround all blocks with braces, the incomplete condition would stand out like a sore thumb right away and remind you that something is amiss. You would look at it and realize that the expression was not complete and that you got distracted halfway through.

This is the power of defensive programming habits. They become routine and every break from it will jump out at us as we read the code. That way, it will guide our attention and prevent us from making completely avoidable mistakes.

if ( !value )
{
  value = 100;
}

Make it a habit

Make it a habit to always put braces around every code block! Add them while you’re still in the right frame of mind, writing the code in the first place, and you’re making it foolproof going forward. Now, no one has to remember to add braces as they extend the block. You are actively preventing a future bug from happening and all it took was a few extra keystrokes!

It is also easier to read because it has a clear structure that you can grasp with a glimpse. There is no question about where the branch starts or ends, and which operations are executed as part of the branch. It makes its purpose and meaning clear!

Apply it anywhere

Loops are also candidates that could often benefit from more foresight. Occasionally, for example, we have to write infinite loops—think of a thread loop or a notification system. These loops have no exit condition because they run forever or because more complex logic will eventually break out of them. I’ve noticed that there are usually two ways how programmers implement such a loop, and both are equally bad.

for( ;; )
{
}

and

while ( ; )
{
}

Both of these versions are valid in most languages but let’s be honest. They don’t mean much. Let me stress once again how important it is to make your intentions clear. Anytime someone looking at the code has to make assumptions or guess as to what exactly it was that you were trying to do, it’s just not a good thing.

If you start typing a for loop, in modern editors, usually an auto-complete feature will instantly create a template for you that most likely looks like one of the above. Let’s play devil’s advocate again and assume that at just that time, a phone call comes in again, distracting you before you were able to fill in the respective conditions. As you return to your work, you see a perfectly valid loop construct, give it no more thought, and go from there. Only, you may have forgotten to fill in the conditions…

Be safe anywhere

Once again, there is a really easy way to avoid this altogether by making your intention clear. Simply write your forever-loop like this.

while ( true )
{
}

Now, anyone can tell that this is an infinite loop by design. It doesn’t look nearly as cryptic as the original version either, which can be important since not every programmer is familiar with these constructs. Saying while (true) makes the meaning unmistakably clear. Admittedly, though, it could still be an incomplete condition by accident.

If you want to make it completely bulletproof, you could define a macro and make it look like this.

LOOP_FOREVER
{
}

Anyone reading this line can safely assume that this was not a mistake. No one accidentally fat-finger deleted a condition. This kind of clarity can pay big dividends down the road because it can save you hours of debugging down the road.


Zen of Defensive Programming
Part IPart IIPart IIIPart IVPart VPart VIPart VII Part VIIIPart IX


BAT Icon

Thanks for stopping by. Preparing content such as the one you have just read takes time and effort to prepare. If you enjoyed it and you are using a Brave browser, please feel free to leave a small tip as a sign of your support by clicking on the small BAT icon at the top of your browser window. Your tip is much appreciated and it encourages me to continue providing more content such as this.

Facebooktwitterredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published.