Example Guidelines
The sample guidelines in this section have the following as their root causes:
- Lack of programming language knowledge
- Lack of source code knowledge
- A common mode failure
- Complexity
An example of programming language semantics whose details few developers have fully learned is what are known as the "usual arithmetic conversions" in C and C++. These conversions deal with the implicit operations that take place when the operands of a binary operator have different types. For instance, in the assignment x=y+z, the three variables can each have a different arithmetic type and the operands of the + operator will need to be converted to a common type before the addition takes place. The result will then need to be converted to the same type as x (unless it already has that type). While developers are generally aware of the behavior of the common cases, the less-common cases can sometimes produce completely unexpected results. Possible coding guideline solutions to this problem include making recommendations ensuring that the conversions that occur are visible in the source, usually by requiring explicit conversions (the hope is that this visibility reminds developers about the conversions that will occur), or recommendations ensuring that operands of binary operators never have types that could result in surprising results (usually by restricting the types that objects may be declared to have).
An example of application source code knowledge is the large number of different variables visible at any point in the code. If two different variables share the same name, it’s possible for apparently innocuous changes to the source to have unexpected consequences. For instance, assume that a variable called foo is defined and used within a function definition, and that there happens to be a variable declared globally with the same name. The local definition is the one accessed by all references to foo within the function definition. It’s possible that later modification to the function may remove the need for the locally defined foo. If the developer who removes all references to foo within the function definition overlooks an assignment to a variable of that name, then the source may still compile without complaint. The unremoved instance of foo will access the globally declared foo, which now receives an unexpected assignment. The coding guideline solution to this problem scenario is to restrict the set of names a variable can have at any point to those that differ from any other variable visible at that point. If this guideline is followed, no other identifier is available for unremoved references to access, and the resulting compiler diagnostic will highlight the developer oversight.
A common mode failure in C++, C, or Java is for developers to mistype or confuse the = and == operators. That is, they accidentally type one character sequence when the other was intended, or read one character sequence when the other actually appeared in the visible source. In an if expression context, for example, the character sequence == is very common and experience has shown that developers sometimes incorrectly read the single = character as being ==.
For a subject that is frequently talked about, software complexity is a difficult idea to quantify. Metrics such as Halstead’s complexity measure and cyclomatic complexity have been proposed, but studies have found that they all tend to correlate very highly with lines of code, and there have been no serious studies of how developer performance depends on any of these factors. Miller’s famous 7+/-2 paper is often incorrectly cited as a rationale for recommending that the depth of nesting of constructs be no greater than seven.
In many ways, the level of complexity is inherent in the problem being solved and the algorithms used. Without a model of how developers handle nested constructs, or sequences of constructs, it’s impossible to specify any guidelines that relate to complexity. There is nothing to show that any of the existing guidelines do anything more than cause code to be structured in a way that it adheres to a guideline without changing the underlying complexity as viewed by developers.