In one of his most well know experiments, B. F. Skinner – the founder of branch of psychology known as Radical Behaviorism, set an automated mechanism to give pigeons food pellets on every predefined constant interval. Nothing the pigeons did had anything to do with whether or not they will get the food. Yet the pigeons appeared to associate getting it with whatever they were doing at the time. One of the birds walked in circles around the cage, others repeatedly moved their body in a particular way and some birds did nothing.
No matter what a pigeon did, at the end (of the time interval) it was rewarded with a delicious pellet of food. Providing further proof that whatever it was doing worked yet again which lead in turn, to a repetition of the action during the next waiting period.
This simple experiment tried to explain how people come to associate events in their life to unrelated behaviors and believes also known as superstitions.
While we developers do not work for food pellets (unless you consider pizza) we are known to be sensitive to our software not working as expected. Misbehaving software leads to all kinds of unpleasantness ranging from uncomfortable embarrassment, through a never ending all-nighters and all the way to billions of dollars in losses. In an attempt to avoid these uncomfortable situations, and similar to Skinner’s pigeons, many of us developed a few rituals in our code serving no real purpose other than warding off imaginary code failures.
here are a few examples I run into :
1. Checking for a null when calling a new operator I am sure everyone has seen something similar to this code snip:
With any modern C++ compiler, the if statement will never get executed. The new operator’s default behavior is throwing an exception when failing to create the object. Years ago this kind of code made sense in C code when as C dynamic allocation function malloc returned a 0 (NULL) on failure. Later in 1998 , due to one of many noncompliances with the standard , Microsoft’s Visual Studio 6 C++ compiler, generated code which returned a null by default instead of throwing and exception. It was fixed in the next version of VS – 15 years ago! My best guess is that new developer notices this pattern in old code and end up copying it to their own new code “just to be on the safe side” copying it to their own new code and unwittingly continuing the chain.
It is, in fact, possible to have the new operator return a null by calling
or, by overloading the new operator, but usually this is not the case.
2. Using NULL or even worse – 0 instead of nullptr: the nullptr keyword was introduced in C++11 , ending years of having to define the line:
In a header file visible to all source files. Yet, more than 5 years later people keep using a syntax similar to the if statement in the previous example. Just in case the compiler didn’t get the memo that nullptr is an invalid pointer evaluating to 0.
3. Inilizieing an std:string to an empty string:
The of std::string’s default constructor, guarantees the newly created string is empty. Assigning it an empty string literal has no practical value.
3. having an else clause after a throw
If the string is indeed null triggering the throw statement, program execution path will be redirected to the closes suitable catch clause skipping the code following the if . The only way the else code will ever get executed is if somehow the throw keyword is ignored by the compiler, but then with the compiler producing unpredictable code wouldn’t an empty string be least of our worries ?
Superstitions code may seem harmless at first glance, but it has a hidden price in code readability and possibly in performance. This kind of code is often difficult to root out as over time we no longer question its validity. Doing code review and/or paying close attention to the compiler or static analyzer’s warning is the best way to clean up these parasitic code segments.
Leave a comment with other examples of superstitions code