Previous | Table of Contents | Next |
The best solution to this occasional problem is neither chopping up lines nor changing the overall indenting standard to a smaller interval. Instead, a programmer can simply use a different indent interval, say four characters, for just the deeply nested section of code. This may involve a little more editing effort for those statements indented to a level not an even multiple of eight characters (although with good editors, this is quite easy to do), but the code remains readable when displayed or printed and the convenience of the eight-character interval (in the MS-DOS environment) is retained.
This example illustrates how master programmers approach standards. They focus on the underlying principles, of which consistency is a very important one. But consistency should apply to the principles, not just simplistic rules. Here the principles underlying the choice of an eight-character indentation interval were to produce a readable layout and to allow convenient manipulation (with the editor and other tools). Theres nothing sacred about an eight-character interval, however, and there may be circumstances where using some other size better serves the underlying principles.
Some of the areas that might be covered by C programming standards include:
Facing a list of standards like this may be discouraging. How can you ever expect to cover all the areas, and how will you deal with all the existing code that doesnt follow the standards? The answer: one step at a time. If you havent already developed a set of standards, start by creating a document, C Programming Standards, with sections following the list above. Preferably, use a word processing package that lets you mark index entries and automatically produce a document index. The index will be an invaluable part of the printed standards as they grow.
Then start adding guidelines and examples. The following shows a sample entry:
Follow each ( and [ with a space, and precede each ) and ] with a space.
Example: x = myfunc( item_table[ i ] );
One of the major barriers to instituting programming standards is disagreement over what the best standard is. A group of programmers might agree on some broad principle, such as indenting conditional code to show its structure, but on specific guidelines such as the size of each level of indentation there often are many defensible points of view. To avoid analysis paralysis, discuss the merits of each alternative and select one guideline as good enough to follow most of the time. This may sound like a wishy-washy way to embark on standards, but itll work fine if the programmers who develop and use the standards understand that, in most cases, following consistent guidelines across projects is more important than determining the absolute best rule. Its also important that programmers faithfully follow the standards, and that they dont view most of the time as an escape clause that lets them go their own way whenever they have a personal preference thats not consistent with the standards.
Sometimes, differing opinions about alternative guidelines may run so deep that even a good enough standard is hard to agree on. Consider a suggestion I made in Chapter 2, that macros EQ, LE, etc., be used instead of ==, <=, and the other relational symbols. The principle underlying this suggestion is to avoid the slippery errors caused by mistakenly using = (assignment) instead of == (equality). Unfortunately, this guideline conflicts with the principle that you should express program constructs in ways that are consistent with ways you express similar constructs in other contexts. The < and > symbols are widely used in other programming languages and general math discourse. The <=, and >= symbols are also widely used in other programming languages and are very similar to the and math symbols. So using LT, GT, LE, and GE instead of these symbols could be considered a step backward. Note that its this same principle that Cs use of == violates, since = is the commonly used symbol for equality in other programming languages and in math. Here we have a conflict that originates in a C flaw, and whose solution may introduce a different, if lesser, problem.
Reasonable arguments might be marshaled for either of three guidelines:
The first approach is risky and would only make sense if it were combined with some other guidelines, such as always checking a program with a compiler or lint utility that could detect the use of = where == was expected.
The second approach minimizes the amount of non-typical C code (its safe to say most C programmers today use the standard C symbols) and eliminates the dangerous ==, but it introduces an inconsistency among the various relational operators. The third approach is easy to follow and is consistent, but it is not typical for either C programs or common math expressions.
If possible, one of the latter two guidelines should be adopted as good enough. And, for this rule, followed all of the time because there are no potential conflicts with other lexical rules. If passions run deep, however, you might have to settle for a guideline that says: In any program use either Rule 2 or Rule 3 throughout the whole program. This lets a programmer use a reasonable alternative that he or she is comfortable with and maintains consistency at least at the program level. After a year or so of experience, you may be able to determine a strong preference for one or the other guidelines and be able to settle on a single good enough standard.
Permitting alternative coding styles costs a significant amount in consistency and reduces a programmers ability to understand immediately the notation of a new program. Consequently, its a tactic to use sparingly. But for some guidelines, its the best way to move forward and at least reduce the number of variations in coding style.
Previous | Table of Contents | Next |