Code Reviews#1
Series Introduction

John M. Dlugosz

The Spirit of C++

C++ is more than a set of syntax diagrams—it has a “spirit” as well as a formal definition. I’ve been studying C++ for eight years or so, and have witnessed the evolution of the language. I can remember when I eagerly awaited new versions of compilers to give me support for multiple inheritance, static members, and const functions, much as today I wait for proper template support, intrinsic bool, and namespaces. C++ has come a long way in the last decade, yet it’s perpetually not quite finished.

Today all that is old “basic” stuff, and I’m waiting for Lambda Functions, variadic templates, and other goodies!

C++ is a living language, evolving under the pressure of real programmers facing real problems. I’ve seen a lot over the years, and pretty much watched C++ grow up. The various language features and subtle points are there for reasons, because earlier versions of C++ were lacking something that real working programmers felt the need for. With a proper understanding of where it’s coming from, you can better understand, and ultimately better use the language. I want to share with you what I call the “spirit” of C++, which is understanding the language, not just the syntax.

Most of the magazines are full of C++ articles that cover syntax details, information on new features, and subtle points or pitfalls. I want to depart from that path and talk about programming in C++. Rather than covering language points in detail, I will concentrate on a design or implementation issue and show you which language features can be harnessed for that issue, but the thesis will be on the software engineering, not on the syntax.

Here is a quick overview of the main topics I will be covering.

Antibugging, Abugging, and Debugging

Everybody knows about Debugging, I’m sure. But Debugging is merely the last line of defense, to be used when all else fails. In 1989 I developed a simple system of classifying design and implementation issues which greatly aids in the practice of writing code that is correct in the first place.

Abugging is catching problems automatically. This is fairly easy to understand, and you probably do some of this already. ASSERT() macros, range checking, and user input validation are all applied abugging techniques that are applicable to most any language. C++ has its own unique pitfalls that require abugging attention, and C++ offers features that can make abugging convenient.

Antibugging, on the other hand, is a bit more subtle to understand. Antibugging is preventing the error from existing in the first place. It’s not catching misuses—it’s preventing your code from being misusable.

Antibugging is purely in the design, and prevents the design from containing places where mistakes can be made. Imagine walking through the park and saying to your companion, “Hey, have you ever noticed that this is not a mine field?” A good design is not something you notice! You only notice the problems. Abugging is putting fences around the buried mines in the park. Antibugging is building a park without buried land mines.

I advocate a systematic approach. Simply by knowing about abugging and antibugging, you can red-line items in your design. If the instructions for using a class contains important directions for the user along the lines of “you must do…” or “you can’t do…” then you should flag an antibugging issue. When comparing two designs, you can judge that one has fewer such issues than another.

When you have eliminated all the antibugging issues from the design, tackle the remaining as abugging issues during the implementation. For example, if you are not allowed to call a particular function under certain circumstances, make the code check for that.

We will be looking at specific examples of design and implementation, and analyzing the antibugging and abugging issues involved. As part of Code Reviews we will be looking at the wrong way to do things, and how to identify what’s wrong and how to make it better.

Design, Documentation, and Testing

Every piece of code has a design. It may not have been designed formally and that design may not be written down, but it does have a design. The existence of a design is central to a systematic approach to proper design and implementation. Designs are not static creatures, but evolve over time. The “software life cycle” is very much involved with the program’s design. As maintenance is performed, the design is compromised. Hacks and quick fixes introduce flaws such as improper coupling between modules. Also, programmers unaware of the proper design (due to lack of documentation) may change things without knowing they are doing things contrary to the original design. The decline of the design marks the aging process of the program.

For long-term maintainability, the design must be well thought out and properly documented. Furthermore, code must be tested to insure correctness. Testing up front can save a great deal of debugging later.

Idioms

A novice once asked me, “But isn't that hard to read?” to which I replied “No, because I can read C++.” I’ve found that novices and experienced programmers have totally different ideas on what is “readable”. In general, the more experienced programmers prefer more idiomatic code, while those still learning the language prefer uses of basic constructs. With true experts, the situation becomes even more extreme. In general, with experience we recognize larger passages of text and instantly understand what larger meaning it holds, and what the typical use of such a thing might be.

Still true! Just a week or two ago, a novice said that *p++ needed parenthesis to make it more readable, and questioned the use of for(;;) for a mid-decision loop.

In Code Reviews, I’ll be examining various idioms and how they are used. There is more to coding style than where you put your curly braces. I generally won’t mention source code formatting issues at all, but will concentrate on what is being said and how. Coding idioms generally concern small passages of code. The big brother to that is architectural issues, or how C++ is used in a more sweeping sense. But it all boils down to the same concept: Learn C++ as a language.

Today we’d refer to those larger architectural issues as “Design Patterns”

The Lessons

Sometimes a discussion in idioms or the “spirit of C++” can be a meandering romp, which doesn’t do well in the traditional essay form which demands a certain amount of sticking to the subject. Yet, most of my experience presenting this material has been centered around a white-board, or in online discussion groups. To try and bring this same presentation format to this medium, I will sometimes present “dialogs”, which read as discussion between several characters. In addition, annotated code samples will play a large role.

In conclusion

I’ll end this introduction the same way I end my programs:

return 0;

Code Reviews series | Magazine top | next part