Over 20 years ago while working on my master’s degree in electrical engineering, I took a computer science class that required a term software project. At the time I had a Hewlett-Packard 9816 computer that ran HP’s Rocky Mountain Basic (RMB).
This version of Basic was very powerful for its time and included a novel command, GOSUB, which allowed calls to subroutines to return to the caller when done. This was much better than the GOTO command, which often led to the messy and unmanageable spaghetti code that Basic was known for.
I asked my computer science professor if I could use Basic for my term project. After he coughed a little bit, he said that the program must follow good coding practices such as structured programming. I agreed, did my term project in RMB, and got an A in the class.
Even though other languages available at the time (e.g., Pascal and C) provided more and better structured programming constructs, the RMB version of Basic was a better choice for me for this project. I knew RMB better than C (still new at the time) and I had access to it at home on my own computer – I did not have to camp out in a campus computer room.
Since that time, programming practices and philosophies continued to evolve and today C++ provides advantages over C for writing quality code. Some in the C++ camp scoff at those who prefer C. Even though C++ may be technically optimal, reality forces other factors to be considered. Mike Barr stated, “C remains the dominant language in the fast growing field of embedded software development” and provides data illustrating his point. See Real men program in C. While C++ helps increase code quality, C may be a better alternative because of availability of compilers, platforms, skill sets, and legacy code. Besides those in the C++ camp scoffing at C, some in the C camp scoff at C++, also without proper consideration of facts and circumstances. Dan Saks discusses this in Poor reasons for rejecting C++.
My past two articles have generated discussions as to which is the “one and only true” way to support product differences, whether it is compile-time, build-time, or run-time switching. Although the focus two articles ago was on using compile-time switching, it does not mean that I believe it should be used to the exclusion of build- or run-time switching. On several occasions in these newsletters, in my conference presentation, and in my book, I emphasize that each best practices is the best but only for a given situation. You need to decide if that situation applies to you and adopt or adapt a given best practice as necessary.
When someone starts pulling hard for a “one and only true” way, I look very carefully at their arguments. Dan Smith forwarded to me an article by Stephen C. Dewhurst, One at a Time, Please, that claims using #if and #ifdef should be avoided. He uses hyperbole by stating that “Everyone’s wrong” for using #ifs and #ifdefs. He claims this is bad:
// Some code #ifdef DEBUG // Some debugging code #endif // Some actual code
The reason he gives is because you have to compile it twice, once with DEBUG defined and once with DEBUG undefined, to see if it is syntactically correct. He then offers that this is better:
const bool debug = false; // Some code if ( debug ) { // Some debugging code } // Some actual code
Since “debug” is a constant, the dead code will be optimized out, just like the #ifdef method. The advantage is that it will check the complete syntax with one compile, including the code that will eventually be optimized out. I agree that his method will save an extra compile pass for a syntax check, but only for code inside of the #ifdef or if() statement (which is typically a small percentage of the code base.) While his method is better for the limited amount of code inside of those statements, it may be too costly in terms of time, resources, and risk of code rewrites, changes in the build environment, and delays of the schedule.
Just because some tools (RMB, C, #ifdefs, etc.) are not as technically optimal as other tools for a given task, they may be better given other considerations and they can be used properly to minimize problems. Add tools to your toolbox and use them appropriately. Keep your mind open to new tools and methods. Don’t get stuck believing there is a “one and only true” method to address a task.
Until the next issue of the one and only true newsletter…
1 Comment
Two readers commented that they did not think that Stephen C. Dewhurst’s article was claiming a “one and only true” way of writing platform-specific code. At last month’s Embedded Systems Conference in Boston, I learned that Steve was one of the instructors so I attended his class and introduced myself afterwards. From his class and our subsequent conversation, I learned more about his teaching and writing style and approach to coding, and I now agree that he was not proposing a “one and only true” approach. In addition, he told me that he, too, is also wary of “one and only true” claims. While our backgrounds and experiences are different, in principle we agree and it was a pleasure to meet him.