Community Programming Style Guide

http://vinci.org/style
Release Date: 2005-08-19

Editor: Ralph L. Vinciguerra, Trinity Research and Development Corporation.
Contributors: ALPHATECH, BAE Systems

The goal of the CPSG (this document) is to create a flexible and evolving programming style guide that is freely available.

This work is licensed under a Creative Commons License called "Attribution". See Appendix C for details.
[Creative Commons License] [By:]

This document is maintained in XML format, from which an HTML version is generated (and should never be edited). See Appendix A for details. Note: before trying to rewrite this document for another project, consider instead maintaining a "delta document" as described in the introduction.

Contents


Introduction

This document defines the programming style that is used in a community of developers. It is a reference document combining the best programming styles in common use. The goal is to make source code more readable and transportable among teams of programmers. By adhering to these guidelines, it will be easier for programmers new to a project to locate and recognize sections of the program and to be able to discern the program semantics, structure, and control flow.

Please note that this document is broken into two parts, a prose documentation section, and a reference-like rules section.

Multiple Language Support

To support the use of multiple languages, this style guide is maintained as a database of rules. Each rule identifies one style element, and also indicates the following additional attributes:

Usage Categories

Programming styles can be a source of controversy among programmers on a team, and the best strategy is to label the severity of any particular style component and allow each team to fine tune the style guide. However, the best results are obtained when all teams ascribe to precisely the same style guide. To facilitate consensus, each guideline includes a justification when possible.

The usage categories are:

The names were selected to be meaningful, and to also have unique first letters in case abbreviations are needed (M,R,S,E).

Delta Documents and Unique Rule IDs

Before you create "yet another style guide", consider using this document as a baseline, and instead maintain a "delta document" that describes the differences from this document. Your delta document must refer to the exact version of this document it is based on. The version history here will always identify those rules that have changed so that your delta document can be updated to new versions easily.

Each single recommendation will have a unique 4 digit number to support cross referencing. The numbers are not necessarily in sequence, but serve simply as unique IDs.

By having a unique tag for each rule, a project may elect to follow this guide, and only note the differences as necessary. New rules should be numbers prefixed with an X (for eXtension). These can be submitted to the CPSG Editor for future versions of the style guide.

An example:

PROGRAM_NAME specific Style Guide

Based on the Community Programming Style Guide release 1.2

Change rule 0027:
  Usage: Mandatory->Suggested
  Languages: C++ -> C++, Java
Change rule 0030:
  ...
Add rule X0001:
  Usage: ...
  Languages: ...
  

C++ Rationale

C++ is a very flexible language that aims to keep the programmer unrestricted; free to explore any object-oriented techniques. The downside is that there is essentially no enforcement of what are commonly considered to be good idioms for object oriented programming. Also, certain dangerous techniques should be avoided. This guide includes numerous rules to address these topics.

Tom Mueller stated the situation well in an issue of C++ Report:

Using C++ on a project of this size did not come without problems. Some of the problems were related to the technology being new to the development team. With so many people on the project, at so many different times, and with such a wide variance in experience level, the flexibility of C++ led to inconsistent code quality and design drift. Sometimes language features would be used without knowing the true intent of the feature. For example, while passing a constant reference parameter for efficient pass-by-value is reasonable language use, declaring a pass-by-value parameter as a constant really does not add significant semantic value to a program. This minor aberration in language [use] would be inconsequential for a one-person project or for a small team. But for a larger project, where an individual may read code written by dozens of people in a short period of time, all of it having different types of these aberrations, a nontrivial amount of effort is spent trying to figure out if the developer who originally wrote the code was doing something tricky, unfamiliar, or just wrong.

Java Rationale

Java is designed to be a safer language. Many of the flexible, yet confusing, aspects of C++ are removed. This guide also covers Java, and it's interesting to note how many of the rules are not needed for Java. However, the old adage "Give someone enough rope, and they'll hang themselves" applies here, and Java deserves numerous rules as well.

Version History

Date Changes
2005-08-19 Rule 0109 reworded, since method inheritance is an override and not an overload. Also, issues with static overrides are addressed.
Rule 0012 reworded to be clearer.
Rule 0002 added to address the use of namespaces in header files.
Rule 0065 relaxed from Manditory to Recommended.
2005-05-17 Cleanup of licensing text. Since we downgraded from Attribution-ShareAlike to only Atttribution, the introductory text needed to be adjusted. Also, several icons that were referring directly to the CreativeCommons site have been cached locally for speed.
2005-05-11 Changed to Creative Commons Licensing. Specifically the Attribution license.
2004-01-23 Some trouble with the XML mapping to HTML left some sections missing on the published version. This should correct that as we continue to transition to proper XML generation techniques.
2003-08-14 Typographic corrections to rules 0041, 0112, 0115.
2003-08-12 The licensing is relocated to a companion file, and this release is ready for a new review cycle.
2003-08-11 Extensive input from the ALPHATECH staff lead to the following changes.

New rules 0149, 0150, 0152, 0153.
Deleted rules: 0124, 0125.
Edited rules: 0012, 0022, 0026, 0043, 0044, 0045, 0065, 0071, 0072, 0079, 0098, 0105, 0109, 0110, 0143.
Rule 0112 reworked and rule 0113 pulled in.
Rule 0036 reworked, and rule 0037 pulled in.
Rule 0042 reworked, and rule 0043 pulled in.
Renumbered the second duplicate rule ID 0082 to new rule 0151.
Many rules were edited for gramatical reasons and are not listed here since the intent of the rule has not changed.
2003-07-31 Moved examples to separate files in an example subdirectory.
Merged rules 0003, 0005, 0011, and 0014 into a restored rule 0001, with a new table.
2003-07-15 Reworked title to CPSG, and completed licensing under the GFDL.
2002-03-14 Renamed the "Exceptions" section to "Errors and Exceptions".
Rule 0142 altered: updated text and relocated to the Errors and Exceptions section.
Changed usage tags so that "Required" is replaced by "Mandatory" (same meaning).
Ran spell checker on entire document.
2002-01-28 Established a new style guide for TRDC.

Remaining Work

Here are items which still need attention. Remove them from this area once they are completed.

References

[cxxcs]
Herb Sutter, Andrei Alexandrescu, C++ Coding Standards - 101 Rules, Guidelines, and Best Practices, Addison Wesley C++ In-depth Series 2005.
[EC++]
Scott Myers, Effective C++ - 50 Ways to Improve Your Programs and Designs, Addison Wesley Professional Computing Series, 1992.
[C++ST]
Robert B. Murray, C++ Strategies and Tactics, Addison Wesley Professional Computing Series, 1993.
[Sun]
Sun's Software Code Conventions for Java { online, local copy}
[Netscape]
Netscape's Software Coding Standards Guide for Java { online, local copy}
[Poss]
{ online, local copy}
[X1]
Software C & C++ Coding Standards - of unknown origin
[Doxy]
Doxygen - main web site

Appendix A - Style Document Generation

The original source document is maintained in XML format, from which other formats can be generated. The most common generated format is HTML.

A small Java application named rlv.resub.RESub is used temporarily to generate an HTML version by using simple substitution rules. The next version will be generated with a proper XML parser from the package "org.apache.xalan".

Appendix B - Example Files

Example files for several languages are provided in a example subdirectory. Note that the file headers use CVS automatic keywords. If you do not use CVS, substitute the literal file name for the "Id" keywords, and removed the "Source" keywords.

Appendix C - License Summary

Creative Commons License [By:]
This work is licensed under a Creative Commons License called "Attribution".

Attribution 2.0

You are free:

  • to copy, distribute, display, and perform the work
  • to make derivative works
  • to make commercial use of the work

Under the following conditions:

  • [By:] - You must give the original author credit.
  • For any reuse or distribution, you must make clear to others the license terms of this work.
  • Any of these conditions can be waived if you get permission from the copyright holder.

Your fair use and other rights are in no way affected by the above.


The Rules


Naming Conventions

ID: 0001
Topic: Naming
Usage: Recommended
Languages: OO, C++, C, Java
Description: Use of case in program symbols

This table details the proper form for symbols representing classes, methods (functions), and fields (variables). We avoid the used of "_", this takes more characters, is harder to type, and is not typical of most developers. Also, leading underbars can be confused with some automatically generated internall compiler symbols.

TypeRuleExample
Classes Capitalize class names Indicator, CalculatorNumberRegister
Fields (Variables) Do not capitalize fields, used embedded capitalizations for word concatenation. altitude,lastBufferEntry,imageHeader
Methods (Functions) Do not capitalize methods, used embedded capitalizations. update, setRegisterCounter

ID: 0004
Topic: Naming
Usage: Suggested
Languages: OO, C++, C, Java
Description: Capitalize acronyms in names

Acronyms should stay completely capitalized if they are embedded in a name. Underbars may be used to divide pairs of acronyms when they occur adjacent to each other. It is better to pick a different name though, instead of using underbars and acronyms.

Examples:

ID: 0008
Topic: Naming
Usage: Recommended
Languages: OO, C++, C, Java
Description: Use meaningful names

All names should be understandable English, and meaningful. The name should serve as documentation for a reader rather than a mnemonic shorthand for the writer. For example: loopCounter is preferable to lpCtr.

An exception would be to user shorter names for heavily used iteration or access variables. For example a loop performing extensive indexing might use a variable named "i", instead of "loopIndex".

ID: 0013
Topic: Naming,Classes
Usage: Recommended
Languages: OO, Java C++
Description: Use specific names for classes, avoid generic words

Avoid class names which use common words like Object that have a high probability of clashing with other libraries. Also, make the names as specific to the context as possible (Coordinate is more specific than Number).

ID: 0015
Topic: Naming,Methods
Usage: Recommended
Languages: Java, C++
Description: Methods names should contain the object of the verb

Names of methods (C++ functions) containing verbs should also contain the object of the verb ("object" in a grammatical sense) and should be in the form "verbObject," for example getSignature instead of signatureGet.

ID: 0016
Topic: Naming,Methods
Usage: Suggested
Languages: Java, C++
Description: Use a restricted set of verbs for method names when appropriate

Verbs from the following list should be used to form function names when applicable:

ID: 0017
Topic: Naming,Classses
Usage: Excepted
Languages: Java, C++
Description: Sometimes, set and get prefixes may be eliminated from method names.

In some cases, a class is composed of small, heavily accessed components. The accessor functions for these components may eliminate the "set" and "get" prefixes if appropriate. For example, a class representing a 2-dimensional point might see these accessors in use:

point.x(3);              // Set the X coordinate to 3.
point.x(4 + point.x());  // Shift in the X direction by 4.
      

ID: 0138
Topic: Naming,Methods
Usage: Suggested
Languages: Java, C++
Description: Methods returning new objects are prefixed with 'create'

Methods (C++ functions) that create new instances of a class should be prefixed with 'create'.

ID: 0019
Topic: Naming,Files
Usage: Suggested
Languages: Java, C++
Description: File names should match class names

Files are named to match their associated classes exactly, with the same capitalization. If more than one implementation file is needed, they are distinguished by suffixes. If the operating system imposes a file name length limit, select a meaningful abbreviation. More arcane operating systems may not be able to comply. We hope the last of these systems pass into history rapidly.


Scoping

ID: 0078
Topic: Scoping
Usage: Recommended
Languages: C++
Description: Avoid extern statements

To obtain declarations for external variables, files must include the relevant information rather than having literal extern statements.

ID: 0112
Topic: Scoping
Usage: Recommended
Languages: C++
Description: Limit the use of friend to specific well justified cases.

Friend functions should be used only for non-member binary operator functions and in special efficiency cases. The whole friend concept violates encapsulation and information hiding. Only classes which are very tightly coupled should be friends. One example of such tight coupling is a collection class and its iterator.

ID: 0010
Topic: Scoping,Naming,Variables
Usage: Mandatory
Languages: OO, C++
Description: Avoid global variables

Global variables should be avoided at all costs. Use class scoped static data members instead. If you are forced to use one, a g prefix is suggested to make the variable standout like a sore thumb. For example:

        int gProcessNumber;
        char gFileName;
      

Be sure to comment all global variables and give them an initial value as well.

ID: 0149
Topic: Scoping,Naming,Variables
Usage: Suggested
Languages: OO, C++, Java
Description: Use prefixes for easily identifying the scope of variables.

Many coding standards suggest a set of naming prefixes the help determine the scope or purpose of variables. This is not generally used and it may be hard to enforce across a large code base. However in certain well controlled bodies of code, it is possible to use this technique effectively. The following table demonstrates a set of prefixes:

PrefixExamplePurpose
m mCounter Identifies class member variables.
p pArray Identifies pointer variables (not applicable to Java).
g gProcessNumber Identifies global scope variables.

ID: 0002
Topic: Scoping, Naming
Usage: Recommended
Languages: C++
Description: Avoid the forced use of namespaces in widely included header files.

If a header file is widely included, for example in as a library, it should not contain "using namespace" statements since these namespaces would then be forced on dependent classes. However, in the body files, the namespace statements can be used as needed for clarity and convenience. [cxxcs, rule 59]

ID: 0110
Topic: Scoping, Naming
Usage: Recommended
Languages: C++, Java
Description: Avoid package/namespace clutter.

Keep the packages/namespaces from being cluttered by restricting names to class scope where possible. If a class X is only used by a single other class A, nest the class X inside A. Enums can be similarly scoped.

ID: 0012
Topic: Scoping,Naming,Classes
Usage: Mandatory
Languages: Java, C++
Description: Use Packages/Namespaces for class naming.

Define packages (Java) or namespaces (C++) to prevent class name collisions. If packages or namespaces are not available, then use a one or more letter prefix for class names, starting the prefix with an upper case letter to observe the convention for class naming. For example, a project named IMAX could use Ix for all it's classes. A subsystem named AIMS might use Am. Some examples:

IxImage
AmFile

ID: 0036
Topic: Scoping,Access
Usage: Mandatory
Languages: Java, C++
Description: Make all class members private, with limited exceptions.

Make all class members private to maintain the object-oriented design technique data hiding, and to keep users of classes independent of their implementation.

Exception: Use protected keyword to provide direct member access for derived subclasses, whether the subclasses are created at the same time or in the future. This is more complex class design issues that requires attention to the future evolution of the inheritance hierachy.

Exception: Use public in very restricted circumstances where a class is expected to never change it's implementation, and the access is so heavily used that the method call overhead is a problem. For example, a Coordinate class might have public members for it's x,y, and z values. Use this with caution!


Classes

ID: 0028
Topic: Classes
Usage: Mandatory
Languages: C++
Description: Define default method arguments in the header file.

Default function arguments values should be specified with the function declarations in the header files and not with the implementations in the body files.

ID: 0101
Topic: Classes,Protection
Usage: Mandatory
Languages: C++
Description: Accessor should not modify the object, and should be const.

Accessor functions should not modify the object and are declared as const as well as returning an object (copied on the stack), a reference to a const object, or a pointer to a const object. This prevents unexpected side effects from occuring later in the the control flow.

ID: 0122
Topic: Classes
Usage: Recommended
Languages: C++
Description: Avoid the ellipses argument to methods.

Functions with the ellipses argument should be avoided except in rare cases. If required, use the <stdargs.h> implementation instead of the older <varargs.h> one.

ID: 0096
Topic: Classes
Usage: Suggested
Languages: C++
Description: Match order between init list and declaration inside class.

Members in an initialization list should be in the same order as their declaration inside the class.

ID: 0032
Topic: Classes
Usage: Recommended
Languages: C++
Description: Use constructor initializer list instead of assignment.

Avoid using assignments to initialize class members; use the constructor initializer list instead. The use of these initialization techniques is expected by C++ programmers, and is also the only way to initialize reference and const members. Place the initializer list under the class name. For example:

void
Thing::func(int i, long l) : member1(i), member2(l)
{
  ...
}
      

ID: 0030
Topic: Classes
Usage: Recommended
Languages: C++
Description: All destructors should be defined as virtual.

All destructors should be defined as virtual. This handles the situation where a pointer to a base class is used by delete to deallocate an object, and it is vital for the virtual behavior to allow the most derived class to free its data members through its own destructor first.

Exceptions would be real-time or embedded applications where the virtual table traversal may not be justified in space or time impact.

ID: 0093
Topic: Classes
Usage: Mandatory
Languages: C++
Description: Assignment operator should set all attributes.

In the assignment operator all data members and base classes should be assigned values to bring the object a known state.

ID: 0094
Topic: Classes
Usage: Mandatory
Languages: C++
Description: Assignment operator should test for self assignment.

The assignment operator must test for assignment to itself as its first act. If this case is executed, the left hand object may be destroyed (as many assignment operators do) before it can be assigned values from the right hand object.

ID: 0095
Topic: Classes
Usage: Mandatory
Languages: C++
Description: Assignment operator return type should be const reference to class.

The return type of the assignment operator should be a const reference to the class and should return *this:

const Thing&
operator=(const Thing& thing)
{
  if(thing == this) return(*this);
  else
  {
    ...
    return(*this);
  }
}
      

ID: 0059
Topic: Class
Usage: Recommended
Languages: C++
Description: Use constructor format for variable initialization.

Member variable initialization when performed in the declaration statement is performed in constructor format. For example:

typedef UINT4 Time;
Time t(0);          // Correct.
Time t = 0;         // Incorrect.
      

ID: 0060
Topic: Methods
Usage: Recommended
Languages: Java,C++,C
Description: Divide up lengthy argument lists across lines.

Lengthy function argument lists should be divided across several lines, giving the opportunity to comment each argument on each line. Also, the first argument begins on a new line so that the length of the function name does not affect the indentation of the arguments making them easier to spot. Also note the aligned indents for the one line comments. An example:

int
manyArgumentMethod(
  char c,     // A single character.
  Time time,  // The time in seconds.
  Date date); // The Gregorian date.
      

ID: 0098
Topic: Class,Methods
Usage: Mandatory
Languages: C++
Description: Unmodified arguments to methods should be passed as a const reference.

Reference or pointer parameters which are not modified by a member function should be declared as const, allowing the compiler to enforce the designer's intentions. Passing parameters as a const reference can be more efficient than passing them by value, since only a pointer is placed on the call stack, instead of a copy of the value. So, for example, if a pointer (4 bytes) is shorter than a copy of an entire class (many bytes) the call stack loading and unloading will be faster.

ID: 0099
Topic: Class
Usage: Recommended
Languages: C++
Description: Non mutating methods should be declared const.

Member functions which do not change an object's logical state should be declared const while the implementation casts away the const internally. This protects the caller from performing a dangerous cast that only the class implementer should address. This also allows the compiler to enforce the designer's intentions.

ID: 0141
Topic: Classes
Usage: Mandatory
Languages: Java, C++
Description: Implement all canonical methods

Regarding canonical methods (constructors, copy constructors, destructors) please do at least one of the following:

We do not want each compiler making arbitrary decisions about where each method is implemented.

ID: 0150
Topic: Classes
Usage: Recommended
Languages: Java, C++
Description: Order the class implementation.

To aid readability, order the class implementation into these sections:

ID: 0038
Topic: Method Declarations
Usage: Recommended
Languages: C++
Description: Define methods as virtual to allow sub classes to express virtual behavior.

In general, member functions (except the constructors and assignment operators) should be declared virtual to allow derived classes to express virtual behavior. If a member function must explicitly avoid virtual behavior, then leave out the virtual keyword.


Comments

ID: 0082
Topic: Comments
Usage: Recommended
Languages: Java, C++, C
Description: Use English language comments.

All comment text is in the English language. This is meant to match the largest common base of programmer fluency. Translations to other languages can be included if needed.

ID: 0151
Topic: Comments
Usage: Mandatory
Languages: Java, C++, C
Description: Do not disable code with commenting

Do not use C-style comments to 'comment-out' sections of code. If other C comments are encountered some compilers may not nest the comments properly. In C++, use the preprocessor directives like #ifdef ENABLE_THIS / #endif instead. In Java, us a simple if(false) { ... } instead.

ID: 0021
Topic: Comments
Usage: Mandatory
Languages: Java, C++, C
Description: Comments for statements have matching indent depth.

When comment lines are associated with statements, the indent depth is matched (Java code is shown):

// The main loop.
//
int fact = 1;
int fib = 0;
for(int i=1; i<=4; i++)
{
  // Perform the calculations.
  fact *= i;
  fib += i;

  // Display our progress.
  Susyem.out.println("Factorial so far is "+fact);
  System.out.println("Fibonacci so far is "+fib);
}
    

ID: 0022
Topic: Comments
Usage: Suggested
Languages: Java, C++, C
Description: Single line comments are placed at the end of the statement.

If a short single line comment applies to one or more statements, it can be placed after the statement on the same line preceded by the usual "// " introduction.

ID: 0023
Topic: Comments
Usage: Suggested
Languages: Java, C++, C
Description: Align trailing comments

If multiple statements are near each other with trailing comments, try to align the comments vertically. If a few statements are exceptionally long, don't let them force all the other comments out. For example:

int   i;          // Iteration variable.
Image inputData;  // The input image.
char  string;     // A temporary buffer.
Image imageWithManyPixels;  // The big image.
int   depth;      // The water depth.
      


Files

ID: 0018
Topic: Files
Usage: Mandatory
Languages: Java, C++
Description: Use specific files to implement classes

In Java, each public class is implemented in a single file This is enforced by the compiler. Inner and private classes can be placed into the same file.

In C++, Each class has two files: one header file and one or more implementation files. The header file should define one class only, or a small group of very tightly coupled classes. It should also be named to match the class name exactly.

ID: 0145
Topic: Files
Usage: Mandatory
Languages: Java
Description: Use proper file name suffixes

For Java the source files are suffixed with ".java". This is the only choice, and is enforced by the compiler.

ID: 0072
Topic: Files
Usage: Recommended
Languages: C++,sh,csh,ksh,perl,python,matlab
Description: Use common file name suffixes

For Java, long ago Sun established the suffix java and it is now written in stone. The shorter j would have been welcome but probably conflicted with some other preexisting system.

For C++, the file name suffixes are .hh for header files and .cc for implementation files. The lower case doubled letters distinguish these file from C source files, and are the easiest to type (no shifting, and a repeated single character us very fast to type). These are less desirable, but often seen alternatives:

.hpp .cpp Extra characters.
.hxx .cxx More characters to type, and cryptic rotate "+" concept.
.h .C Header file not distinguished between C/C++. Needs Shift key. Dangerous on case-insensitive systems.
.H .C Needs shift key. Dangerous on case-insensitive systems.

For scripts, an official script suffix is best. The inconvenience of the extra suffix when executing scripts can be addressed by creating a symbolic link (on UNIX), or a "shortcut" (on Windows) with the shortened name if desired. The suffixes have proven to be useful for development tools as well as certain operating system file classification systems which need this extra information when processing or analyzing files.

ID: 0024
Topic: Files
Usage: Mandatory
Languages: Java, C++, C
Description: Keep lines shorter than 78 characters.

Each line in the file should be less than or equal to 78 characters long to avoid problems with printing and various screen editors.

ID: 0025
Topic: Files
Usage: Mandatory
Languages: Java, C++, C
Description: Break long lines just before operators

If a language statement must be broken across a line, break the statement just before an operator, and start the next line indented, with the operator at the front. This reinforces the fact that the start of the second line is a continuation of the previous line.

ID: 0026
Topic: Files
Usage: Recomended
Languages: Java, C++, C
Description: Supply header comment blocks for every file.

Each file also has specific requirements for commenting content. All files need to have the starting comments similar to these:

// Example.java
// Copyright 2001-2003 YoyoDyne, all rights reserved.
    

If you are using the CVS or related version control systems you can use the special tags that are automatically substituted instead. Refer to the example subdirectory.

Any extra header information beyond the copyright is less important now that Javadoc and Doxygen solutions are available. See the other rules for class and method documentation for details.

ID: 0143
Topic: Files
Usage: Recommended
Languages: Java
Description: Make import statements as literal as possible.

It is not a good practice in import statements to use the "*" wildcard character to allow access to an entire level of the package hierarchy. Instead, it's more useful to call out individual classes with separate import statements. This makes it easier to determine the dependencies between java source files.

The exception to this rule is the use of standard Java packages in which a large number of the classes are in use, and the number of import statements would be prohibitive.

ID: 0027
Topic: Files
Usage: Suggested
Languages: Java, C++, C
Description: Mark spots in the code that need further attention.

Mark spots in the code which require future attention in comments with the special sequence XXX:. This can be used as a search field to locate problem areas. This is in keeping with common practice for open source development (Linux, FreeBSD, etc).

It is also an advantage to append include your own initials if resolution of the issue should be referred to you.

Examples:

ID: 0039
Topic: Files,Inclusion
Usage: Mandatory
Languages: C++, C
Description: Never include an implementation file.

Implementation files must never include other implementation files. Although the compilers will support this, it is unexpected and can confuse developers working on the program.

ID: 0076
Topic: File Inclusion
Usage: Recommended
Languages: C++
Description: Use forward declaration where possible.

Header files only include header files for classes used in that classes declaration, otherwise, forward declarations are used instead. This speeds compilations. Forward declarations merely identify the particular name as a class:

class Foo;

class Bar
{
   Bar(Foo* x);
}
      

ID: 0006
Topic: Variable/Scoping
Usage: Recommended
Languages: Java, C++, C
Description: Declare variables in the smallest enclosing scope possible.

Variables should be declared in the smallest enclosing scope possible. This makes it easier to locate their declarations.

ID: 0007
Topic: Variable/Declaration
Usage: Recommended
Languages: Java,C++,C
Description: Declare only one variable per line.

All variables should be separately declared, one variable per line. This promotes proper commenting of each variable. In some cases a group of variables are tightly coupled and can exist on one line: (e.g. x,y,z).


Header Files and General Documentation

ID: 0152
Topic: Documentation
Usage: Recommended
Languages: Java,C++,C
Description: When using Doxygen, stay compatible with Javadoc

Doxygen supports both an "at" sign prefix and a backslash prefix. Use only the "at"sign prefix to maintain compatibility with Javadoc. The backslash form can only be used if you can guarantee your source code won't be reused by another project that might want to use a more common tool like Javadoc.

ID: 0040
Topic: Files/Classes
Usage: Mandatory
Languages: C++,Java
Description: One class per file

Each file (header file in C++) should declare only one class. Mixing multiple classes into single header files makes it difficult to locate the code for any given class. In Java, nested classes are allowed for this purpose, but should be used carefully.

ID: 0077
Topic: Files/Header
Usage: Recommended
Languages: C++,C
Description: Header file contents.

Each header file has the following basic order of contents:

ID: 0041
Topic: Preprocessor
Usage: Suggested
Languages: C++, C
Description: Use the preprocessor to prevent multiple processing of includes.

The very first and the last lines of each header file contain special preprocessor lines to prevent multiple processing of the same header file during compilation. A unique symbol is defined which can be tested by the compiler. At the top of each header file:

#ifndef EXAMPLE_HH
#define EXAMPLE_HH
    

At the very end of each header file there's a companion line:

#endif
    

Then in each effort to include the designated include file, Any #include statements are each individually wrapped as follows to improve compiler efficiency. This allows the compiler to avoid even opening any additional files unless the files have not yet been seen. See a later rule which shows how the tested symbol is defined. In code control systems like ClearCASE (tm), the speed improvements can be dramatic. An example follows:

#ifndef EXAMPLE_HH
#include "Example.hh"
#endif
      

ID: 0043
Topic: Comments/Class
Usage: Mandatory
Languages: Java,C++
Description: Precede each class definition by a comment header.

Each class definition will be preceded by a comment block to describe the class. See the example subdirectory.

The specialized tags shown work in several documentation generating systems including Javadoc, and Doxygen.

ID: 0044
Topic: Comments/Method
Usage: Mandatory
Languages: Java, C++
Description: Precede each method with a comment block

Within the class declaration, each member function or attribute is preceded by a comment block which has a very specific format. This is the prime location for general information used by people calling the class methods. In C++ the header file should be preferred over the body file as the body file is not always distributed. See the example subdirectory. This format is compatible across javadoc and Doxygen.

Optional: Also note that the example's the method name is placed on it's own line, left justified to make it easier to scan visually down through a class for a particular method by name. If the usual technique of putting the keywords and method name on one lines are used, the method name ends up at an unpredictable depth making it difficult to spot.

ID: 0045
Topic: Comments/Methods
Usage: Suggested
Languages: Java,C++,C
Description: Break methods into related groups

Methods can be broken into groups by using a horizontal lines in comments and a title. For example:

  //
  //---- Method Group 1 ---------------------------------
  //

  ...

  //
  //---- Method Group 2  ---------------------------
  //
    

Unfortunately Javadoc does not support this formally, as it alphabetizes all the methods instead. This is an interesting tradeoff, but the organization of the source code this way can still be valuable. Doxygen does support this through specialized tags, but unfortunately, this would be lost in Javadoc processing.

ID: 0046
Topic: Method/Arguments
Usage: Recommended
Languages: C++
Description: Use const on method arguments when possible.

Const should be used as the default designation for function arguments, unless the function needs to return information through the arguments in question. Many believe that const should be the the language default and a new keyword like volatile would be available for non-const needs. The following C++ example function shows a const in every possible location:

  const Point& convert(const Point& point) const;
        

ID: 0047
Topic: Comments/Method
Usage: Mandatory
Languages: C++
Description: Put a comment block before each inline method.

In-line member functions have special needs. For each function, put a conventional declaration inside the class declaration block with it's associated preceding comment block describing it's use. After all, inline functions are used in exactly the same manner as regular functions. After the end of the class declaration block place the complete implementations for all the in-line member functions. For example:

  /**
   * An inline function of note.
   */
  inline void
  Example::func()
  {
    ...
  }

  /**
   * Yet another inline function of note.
   */
  inline void
  Example::func2()
  {
    ...
  }
      

ID: 0074
Topic: Methods/Inline
Usage: Mandatory
Languages: C++
Description: Contructors, destructors, and virtual methods are not inline.

Constructors, destructors, and virtual methods must not be declared inline. The address of these methods may be preserved, possibly implicitly, and would result in multiple copies of the code being created.

ID: 0102
Topic: Methods/Inline
Usage: Recommended
Languages: C++
Description: Only very small functions should be inlined.

Only accessor, mutator, and very short functions can be declared inline. Code bloat can be severe otherwise.

ID: 0103
Topic: Methods/Inline
Usage: Recommended
Languages: C++
Description: Avoid I/O in inline methods.

I/O (via iostream.h) should not be performed within inline functions, otherwise code bloat via the include of iostream.h can occur.

ID: 0048
Topic: typedefs
Usage: Suggested
Languages: C++
Description: Gather typedefs in a single file

All system-wide typedefs are collected in a shared header file. If the system is divided into reusable subsystems, then each sub-system has it's own shared header file with typedefs.

ID: 0049
Topic: Enumerations
Usage: Recommended
Languages: C++
Description: Declare enumerations in a relevant class.

Enumerations should be declared within a relevant class to obtain qualified name scoping. The enum itself should be named with the same conventions as a class (capitalized). The enum members are similar to symbolic constants and should be each all upper case. Also, its very useful to define an explicit illegal value for error checking. Enums values can order themselves automatically, so the illegal value is forced to -1 at the end of the list, allowing automatic numbering for the regular values. Here is an example:

class Display
{
  enum Color { RED, GREEN, BLUE, ILLEGAL=-1};
};
      
Accessing one of these enums would be as follows:
color = Display::RED;
      

ID: 0050
Topic: Inheritance
Usage: Mandatory
Languages: Java
Description: Divide lengthy extension lists (derivation in C++) across lines

Lengthy derivation lists should be divided across lines. In Java:

class SubClass extends
  SuperClass1, SuperClass2, SuperClass3, ...
      

ID: 0051
Topic: Access
Usage: Suggested
Languages: Java, C++
Description: Order the access identifiers

Member access identifiers in class declarations should be ordered public, protected, then private, with the private identifier explicitly specified; it is the default if no designator is present can be confusing if absent.

ID: 0075
Topic: Class/Layout
Usage: Suggested
Languages: Java, C++
Description: In a class, methods first, then attributes

In the class declaration, member functions are declared first, followed by data members.


Implementation Files

ID: 0079
Topic: Files/Layout
Usage: Suggested
Languages: C++
Description: Implementation file layout

Each implementation file has the following components:

See the example subdirectory.

ID: 0052
Topic: Files/Layout
Usage: Suggested
Languages: C++
Description: Precede method implementations by comment blocks

Each function is preceded by a comment block with a description of its detailed implementation as needed. This information is an extension to the short information provided in the header file for each function. The user of this class should only need to read the header file comments and declarations to effectively use this function and only consult the implementation file when studying the implementation is warranted.

ID: 0054
Topic: Methods
Usage: Suggested
Languages: Java, C++
Description: Keep method implementations under 100 lines of code.

Try to keep method implementations less than 100 lines in length. Methods that are shorter are easier to comprehend and maintain. Shorter methods also support a modular approach where complex operations are subdivided into simpler operations.

ID: 0080
Topic: Classes,Scoping
Usage: Suggested
Languages: Java, C++
Description: Do not use the "this" prefix to access members.

In the definition of methods, references to class data members should not use the historical this pointer, since the language supplies it implicitly. Since the most common activity in methods is the manipulation of member data, this assumption is justified. Some style guides recommend the use of a special prefix for all data members; although this is better than using the this pointer, it still is not justified as above. However, many projects and libraries have started using special prefixes like "my" for class data members so if it can be consistently applied across a related set of classes, then this is reasonable.

ID: 0055
Topic: Syntax
Usage: Suggested
Languages: Java, C++, C
Description: Make operator priority explicit with parentheses.

Parenthesize complex expressions if operator priority is in doubt. For example:

result = (one + two) * three;
      

ID: 0056
Topic: Conversion
Usage: Suggested
Languages: C++
Description: Use function-style type conversion.

Instead of "casts" for explicit type conversion, apply a function style conversion with the name of the required data type to the variable or value:

int i(4);
float x = float(i);
      

ID: 0057
Topic: Syntax
Usage: Suggested
Languages: Java, C++, C
Description: Use compound assignment operators

Use compound assignment operators whenever possible, as they are natural to Java, C++, and C. They aid rapid comprehension of the operation. For example, use:

result += 2;
      
instead of:
result = result + 2;
      

ID: 0058
Topic: Syntax
Usage: Suggested
Languages: Java,C++,C
Description: Use monadic operators over compound operators if possible.

If a compound assignment operator += or -=only requires changing the value by one, use the monadic increment or decrement operators:

result++;
++result;
      

ID: 0061
Topic: Variables
Usage: Recommended
Languages: C++
Description: Initialize pointers.

Initialize pointers when they are defined. If no value is ready, initialize them to 0. For example:

int two(2);
int* twoPtr(&two);     // twoPtr is a pointer to an int
      

ID: 0062
Topic: Pointers
Usage: Recommended
Languages: C++,C
Description: Test for null pointers wherever practical

Test for 0 pointers explicitly when possible:

if(pointerVar == 0) cout << "Economic Module: Oops!" << endl;
else pointerVar->computeGrossNationalProduct();
      

ID: 0127
Topic: Class,Variables,Assignment
Usage: Suggested
Languages: C++
Description: Use initialization instead of assignment for efficiency.

Use initialization instead of assignment for efficiency. Thus a declaration followed by an assignment requires calls to the constructor and the assignment operator, whereas initialization will simply call the constructor.


Indentation

Indentation of the code supports readability, and it needs to be consistent across all the software so that the developers can learn to recognize the spatial patterns in the source code. Each section below deals with a single code layout issue.

ID: 0063
Topic: Indentation
Usage: Mandatory
Languages: Java,C++,C
Description: Do not uses tab characters for indentation.

All indentation is performed with space characters instead of tabs. Tabs can confuse printers and editors. Many text editors can be adjusted to map the tab key to the correct number of spaces automatically.

ID: 0064
Topic: Indentation
Usage: Recommended
Languages: Java,C++,C
Description: Use 2 spaces for indentation when possible.

All indentation is done with two spaces per indent level. Two spaces is optimal for supporting deeply nested code and is more convenient than typing three or more spaces to achieve each indent level. If small changes are in progress on a file with a different indentation scheme, conform to the existing scheme. Each file should exhibit only one scheme.

ID: 0065
Topic: Indentation
Usage: Recommended
Languages: Java,C++,C
Description: Line up the curly brace code blocks vertically.

The curly braces mark code blocks and are lined up with the statement with which they are associated. The statements within the block are indented within those braces. This provides a reasonable visual form for the block. One can quickly scan for the block starts and ends and it easier to perceive nested cases. The old Kernigan&Ritchie technique of "hiding" an open brace at the end of a line tends to obscure this visual form, and makes the visualization of the code structure more difficult. An example with one level of code block nesting, notice how your eye can pick out the nesting immediately:

if(value == true)
{
  System.out.println("The value is true");
  if(value2 == true)
  {
    System.out.println("The other value is true too.");
  }
}
    

ID: 0066
Topic: Code Structure
Usage: Suggested
Languages: Java, C++, C
Description: Put special ending comments on long code blocks.

If a code block ({}) is exceptionally long, put an in-line comment after the closing brace to correlate with the conditional that may be present at the start of the block, otherwise select a unique phrase.

if(value == true)
{
  ...many, many lines....
}  // if(value == true)
      

ID: 0067
Topic: Indentation
Usage: Suggested
Languages: Java,C++,C
Description: Single statement code blocks on a single line can extend a conditional.

If a conditional statement has a short executable result, then it may be placed after the test without the braces as follows:

if(value == YABBA) Yabba();
if(value == DABBA) Dabba();
if(value == DOO) Doo();
      
This is best used for a set of short test and dispatch cases, and makes it easier to read. However, this can cause trouble during debugging in the setting of breakpoints to note whether the case has executed. See rule 0068 for an alternative.

ID: 0068
Topic: Indentation
Usage: Recommended
Languages: Java,C++,C
Description: No conditional statements on their own line without braces.

A single statement which is the result of a conditional test should not be placed on it's own line without braces to surround it. Without the braces the statement relies on indentation as the sole means to define the code structure which is risky, and can lead to errors and difficult to find bugs.

Correct:

if(value == true)
{
  System.out.println("The value is true.");
}
if(otherValue == true)
{
  System.out.println("The otherValue is true.");
}
    

Incorrect:

if(value == true)
  System.out.println("The value is true.");
if(otherValue == true)
  System.out.println("The otherValue is true.");
    

The down side, for blocks with only one statement, is that the code uses extra vertical space (2 extra lines). With caution, one can break this recommended rule, realizing the danger to the proper perception of program structure, that is then only clearly indicated by indentation. The tradeoff between conciseness and easily perceived structure is at issue here. We recommend structural clarity over conciseness.


Declarations

ID: 0153
Topic: Variables/Declaration
Usage: Recommended
Languages: Java, C++
Description: Declare variables in the narrowest appropriate scope.

If a variable is only needed within a code block, declare that variable in the narrowed scope of that code block rather than at class or method scope. This also makes it easier to locate the relevant declarations.

ID: 0084
Topic: Variables/Declaration
Usage: Recommended
Languages: Java,C++,C
Description: Do not use the for loop initializer to declare extended scope variables.

Declarations of variables should not be used in the initializer section of for statements if the variables value will be used after the for loop exits. The newer language specifications are changing the scope of initializer section variables limiting them to the for statement and the enclosed block only. Instead, it is best to place them just before the for statement.

int i;
for(i=0; i<10; i++) { ... }
      

ID: 0085
Topic: Variables/Declarations
Usage: Recommended
Languages: C++
Description: Do not use unamed structures or classes

All Class and structure declarations should have a name and should not also be used to declare instances. Below shows the proper separation of a structure and its instances.

struct Coord
{
  int x,  // X Coordinate.
  int y   // Y coordinate.
};
struct Coord c1,c2;
      

ID: 0086
Topic: Methods
Usage: Mandatory
Languages: C++
Description: All methods must have return types specified.

A functions should have explicitly stated return types. This includes the function main() that should now return int as the old exit() function can now be replaced by a return(). In older C compilers, functions which had no defined return types defaulted to int and supported a bad habit of underspecified function declarations.

ID: 0087
Topic: Indentation
Usage: Recommended
Languages: Java, C++, C
Description: Left justify the method name in declarations.

The return type of all method declarations and definitions should be placed on a separate line before the method name allowing the method name to be left justified and easier to spot in the code. Example of a method declaration:

/**
 * The locate method
 */
int
locate(int i);
      

ID: 0088
Topic: Method Arguments
Usage: Recommended
Languages: Java,C++,C
Description: Provide argument dummy names, and keep them consistent.

The names used for the arguments to functions should be provided in all cases. In C++ that dummy argument name should be the same for the declaration and definition. The name should be selected to help indicate the use of that particular argument:

long
power(long base, long exp);
    

Object Ownership and Safety

ID: 0092
Topic: Object Ownership
Usage: Mandatory
Languages: OO, C++, Java
Description: Sharing access to instances

Avoid writing functions which return non-const pointers or references to their member data. This undermines encapsulation and information hiding, making the caller dependent on the internal operations of the classes.

Under no circumstances should you ever cast away a const on a return value. The const expresses a contract that the caller is being given access to a potentially private component which must not be modified. This is used on rare occasions for efficiency reasons to prevent an extra copy operation. However one should generally return copies of the data element if the size is not prohibitive.

C++ Example:

class Foo
{
  private:
    int x;
  public:
    const int& getX() { return x; }
}
    
main()
{
  ...
  Foo* f = new Foo();
  int& myX = (int*)f->getX();  // Error: cast away the const!
  myX++;                       // Consequence: Modified private data member of Foo!
}
    

ID: 0091
Topic: Ownership
Usage: Mandatory
Languages: C++
Description: Non const returned pointers assume the passage of object ownership

If a function returns a non-const pointer to an object, the ownership is passed to the caller who becomes responsible for deletion and management of the object. In all other cases, the caller is not the owner of the returned object.

ID: 0034
Topic: Object Lifespan
Usage: Mandatory
Languages: C++, C
Description: Set unused pointers to 0.

Pointers must be set to 0 unless they point to additional constructed objects. The older NULL practice should be replaced with a typeless 0, to prevent newer compilers from choking on NULL being set to (void*)0.

ID: 0035
Topic: Object Lifespan
Usage: Mandatory
Languages: C++
Description: Destructors can be used on null pointers in some compilers.

Destructors can be invoked on pointers which are either valid or 0. For most compilers the delete call will properly handle a 0 argument. If your compiler does not, or you need to support multiple compilers, consider using a macro named DELETE_SAFE as shown below:

#define DELETE_SAFE (p) { if(p) delete (p); }
    

ID: 0089
Topic: Ownership
Usage: Recommended
Languages: C++
Description: Use reference arguments when possible

The arguments to function should be a reference to an object instead of the object itself when appropriate. Passing without the reference designation will cause a copy of the object to be created on the stack which can waste time and space of the object is large. There are special cases when the argument needs to be copied in case it might be changes by complex control flows.

When passing arguments for input only also consider the use of the const keyword for those arguments.

ID: 0137
Topic: Ownership
Usage: Mandatory
Languages: C++
Description: Functions should not store pointers to reference arguments.

Functions must not store pointers to arguments passed by reference. This is called the Linton Convention.

ID: 0090
Topic: Ownership
Usage: Mandatory
Languages: C++
Description: Non const pointer arguments should be assumed to pass object ownership unless otherwise documented.

Unless otherwise documented, if a function argument is passed by non-const pointer the ownership should be assumed to be passed to the function, which then becomes responsible for the deletion and management of the object if so documented. All other cases leave the function's caller as the object owner. If the documentation does not indicate the assumption of ownership, the Linton Convention applies, and the caller must exercise care since the function might maintain an internal copy of the pointer which can become invalid after the call.

Exceptions: this rule does not apply to cases where the caller is expecting a function to have the side effect of modifying the object passed by pointer. Another case is where the caller allocates a fresh object and then passes it in to be filled. In these kinds of cases, the documentation must clearly indicate these specialized behaviors.

ID: 0031
Topic: Ownership
Usage: Mandatory
Languages: C++
Description: Code blocks that allocate objects must deallocate or pass ownership.

Each block of code which allocates new objects must delete them or pass ownership during their control flow. A memory leak will occur otherwise.

ID: 0100
Topic: Scope
Usage: Mandatory
Languages: Java,C++
Description: Avoid the use of public or protected data members.

Data members should not be marked as public or protected. This exposes the class implementation and violates encapsulation and information hiding. Inline functions should provide ways to modify or access an object's state instead; this also maintains efficiency.


Allocation

ID: 0029
Topic: Allocation
Usage: Mandatory
Languages: C++
Description: Classes that allocate on the heap or use external resources should clean up properly.

All classes which allocate their own additional objects on the heap (not the stack) or consume other shared resources must have definitions which support, as a minimum, the following member functions, making up a canonical class:

class Thing
{
public:
  Thing();                  // Default constructor
  Thing(const Thing&);  // Copy constructor
  virtual ~Thing();         // Destructor
  Thing&
  operator=(const Thing&);  // Assignment operator
protected:
private:
}
      
The compiler generated copy constructor and assignment operator will not attend to the complex internal data properly. Generally, these can be expected to act as simplistic shallow copies. If you desire deep copy semantics, you should define an explicit member function named deepCopy. If, for some reason you need the regular copy constructor syntax to have this behavior, comment the reasons well, and make the copy constructor simply call through to the deepCopy function. This is not recommended, since the compiler behavior has already set the assumption that copy constructors are shallow. By being explicit, the code will be easier to understand.

ID: 0033
Topic: Allocation
Usage: Mandatory
Languages: C++
Description: Constructors should initialize all class data.

All constructors must initialize all their data members. Unknown and unpredictable value can creep around can hide serious bugs.

ID: 0104
Topic: Allocation
Usage: Mandatory
Languages: C++
Description: Use new and delete instead of malloc and free

Use new and delete instead of malloc() and free(), and never mix both in a program. The newer constructs are easier to understand, and easier to overload.

Exception: if you are calling an older function (like something in libC) that may return "malloc"'d memory, they you should use free for that memory.

ID: 0105
Topic: Allocation
Usage: Mandatory
Languages: C++
Description: Use the array delete form on array deletions.

When an array is allocated with new directly, use the array form of delete. Some older compilers require this, but it also improves understanding.

int array[] = new int[20];
...
delete[] array;
      

ID: 0148
Topic: Allocation
Usage: Mandatory
Languages: Java
Description: Use finalize method only for class local resources.

The delayed nature of garbage collection makes the finalize method only appropriate for the release of resources local to the instance of the class. External resources, and methods on other classes that might block can cause JVM lockups. Manage these resources explicitly instead, outside of the finalize method.

Rewritten from original material in JOOP, v11 n 1, Mar/Apr 1998.


Design

ID: 0126
Topic: Design
Usage: Mandatory
Languages: Java, C++
Description: Avoid static initialization problems.

Static objects from other files should not be used in functions called at static constructor time. The order of inter-file static construction is undefined by the C++ standards.

ID: 0132
Topic: Design
Usage: Mandatory
Languages: OO, C++, Java
Description: Law of Demeter

A class should not depend on the internal structure of another class. This is often called the "Law of Demeter".

Stated more formally: In each method M of class C, only call methods of the following classes:

ID: 0111
Topic: Design
Usage: Suggested
Languages: Java,C++
Description: Reuse existing packages (libraries for C++).

Where possible use existing class packages (libraries) rather than implementing them. This can save time spent debugging classes which may never be as robust as public or commercial class libraries.

ID: 0073
Topic: Design,Inheritance
Usage: Recommended
Languages: C++
Description: Inheritance declarations should specify the protection

Class inheritance declarations must specifically indicate the protection, since private is the default and is counter-intuitive. If private is desired, the following example shows the correct form:

class Derived : private Base { ... };
      

ID: 0109
Topic: Design,Inheritance
Usage: Mandatory
Languages: C++
Description: A non-static method defined in a super class as non-virtual should not be overridden.

A non-static method defined in a super class as non-virtual should not be overridden, as the super classes' function will be hidden. If the method must be static, it cannot be virtual and special care must be given to call up to the super class to preserve the inherited behavior if that is appropriate to the method's intent.

ID: 0108
Topic: Design,Inheritance
Usage: Mandatory
Languages: C++
Description: Never redefine an inherited default parameter value.

Never redefine an inherited default parameter value. Virtual functions are dynamically bound, default parameters are statically bound. This can produce unpredictable results [EC++, item 38].

ID: 0117
Topic: Design,Conversions
Usage: Recommended
Languages: C++
Description: Use implicit conversions sparingly.

Provide and use implicit conversions sparingly. For example the following conversion from a C string to a String class instance is reasonable to provide and use:

class String
{
public:
  String(const char* = "");
};
...
void printOut(const String&);
...
printOut("Testing");  // Uses implicit conversion.
      
Remember that single argument constructors are conversion functions which can be called explicitly or implicitly.

ID: 0123
Topic: Design,Conversion
Usage: Recommended
Languages: C++
Description: Avoid type casts

Avoid type casts unless absolutely necessary. They undermine the type safety offered by C++.

ID: 0128
Topic: Design,Inheritance
Usage: Suggested
Languages: OO,Java,C++
Description: Avoid deep inheritance hierarchies

Inheritance hierarchies more than 3 levels deep should be watched, as the complexity may be too high.

ID: 0129
Topic: Design,Inheritance
Usage: Suggested
Languages: OO,Java,C++
Description: Wide inheritance hierarchies may signal a design problem.

Wide class hierarchies with more than 3 children from a base class should be watched, and more commonality may be captured with inheritance or templates.

ID: 0130
Topic: Design,Classes
Usage: Suggested
Languages: OO,Java,C++
Description: Classes with fewer than 3 methods may need merging.

Classes with less than 3 methods are usually candidates for elimination by merging with other classes. Classes are expensive to maintain and should justify their presence.

ID: 0131
Topic: Design,Inheritance
Usage: Suggested
Languages: OO,Java,C++
Description: Classes with too many methods may need to be split

Classes with too many member functions are candidates for splitting into separate classes.

ID: 0133
Topic: Design
Usage: Suggested
Languages: OO,Java,C++
Description: Minimize class coupling

Minimize class coupling to make classes resistant to changes in the system at large. This aids reusability.

ToDo: an example is needed.

ID: 0134
Topic: Design
Usage: Suggested
Languages: C++
Description: Use templates instead of inheritance for families of classes.

Use templates instead of inheritance when a family of classes only differ through member function argument and data member types.

ID: 0135
Topic: Design,Inheritance
Usage: Recommended
Languages: OO,Java,C++
Description: Use inheritance to represent the "is a" relationship.

Only use inheritance to express an "is a" relationship. Not for "has a".

ID: 0136
Topic: Design,Inheritance
Usage: Mandatory
Languages: OO,C++
Description: Use multiple inheritance sparingly

Use multiple inheritance sparingly. It can often introduce potential ambiguities and complexity into programs, and these issues should be well understood before proceeding. Often the capability of multiple inheritance can be implemented with single inheritance and enlightened containment (inheritance by delegation).

ID: 0144
Topic: Design
Usage: Suggested
Languages: Java
Description: Use abstract super classes only when appropriate

Using an abstract class to embody pure design, i.e. nothing but abstract methods, is better accomplished in Java by using an interface. Whenever, a design calls for an abstraction that includes instance/state and/or a partial implementation, however, an abstract class is the correct choice.

From Teach Yourself Java in 21 Days by Laura Lemay and Charles Perkins.


Operator Overloading

Operator overloading only applies to C++ and it must be used with caution as it can suprise people reading the code who expect the usual behavior associated with operators. For example, redefining "+" to do something drastically different than an addition-related operation is risky.

A common goal in the implementation of overloaded operators is to suppress the implicit conversions of arguments since implicit operations are harder to recognize and to understand.

In C++, the operators that can be overloaded are:

+    -    *    /    =    <    >    +=   -=   *=   /=   <<   >>
<<=  >>=  ==   !=   <=   >=   ++   --   %    &    ^    !    |      
~    &=   ^=   |=   &&   ||   %=   []   ()   ->   ->   new  delete

ID: 0118
Topic: Overloading
Usage: Excluded
Languages: C++
Description: Unary operators should be defined as member functions

All unary operators should be defined as member functions. This will suppress implicit conversions of the argument.

ID: 0119
Topic: Overloading
Usage: Excluded
Languages: C++
Description: Certain operators must be member functions per the language specification

The functions operator=, operator[], operator(), and operator-> must be member functions based on the C++ language definition. These cannot be non-member functions.

ID: 0120
Topic: Overloading
Usage: Excluded
Languages: C++
Description: Compound assignment operators should be defined as member functions

Compound assignment operators (+=, -=, *=, /=, ^=, &=, |=, ~=, %=, >>=, <<=) should be defined as member functions to suppress implicit conversions.

ID: 0121
Topic: Overloading
Usage: Excluded
Languages: C++
Description: Define non-assignment binary operations as non-member friends.

All other binary operator functions should be defined as non-member friend functions so that both arguments are subject to the same access to implicit conversions.

ID: 0115
Topic: Overloading
Usage: Recommended
Languages: C++
Description: Align with conventional meaning for overloaded operators.

Overloaded operator functions should mimic the built-in C++ operators, rather than inventing new operator concepts. For example operator+ should be used for adding, concatenating, etc, but not for more complex operations.

ID: 0114
Topic: Overloading
Usage: Recommended
Languages: C++
Description: Use overloading of functions carefully

Reserve overloading for functions that perform the same activity from unrelated arguments (except for constructors). Flagrant use of overloading leads to confusing class designs.

ID: 0116
Topic: Overloading
Usage: Recommended
Languages: C++
Description: Define compliments to operators in terms of the original operator.

If an operator has a complement, that complementary operator should be defined in terms of the original operator. This prevents the implementations from drifting apart. For example:

int
operator==(const Foo& left, const Foo& right)
{
  ...
}

int
operator!=(const Foo& left, const Foo& right)
{
  return( !(left == right));
}
      


Preprocessor

The C preprocessor is quite powerful, but also must be used carefully to avoid unexpected expansions before compilation. Fewer of its functions are needed with C++.

ID: 0069
Topic: Preprocessing
Usage: Mandatory
Languages: C++
Description: Use heavy parenthesizing in macro definitions

All arguments and the final result of a macro expansion string are surrounded by sets of parentheses to prevent complex expressions from interacting during expansion. Expressions can be placed into the arguments or the whole macro may be part of a complex expression.

#define ADD(x,y) ((x)+(y))
      

ID: 0070
Topic: Preprocessing
Usage: Mandatory
Languages: C++
Description: Do not use the preprocesor to redefine language keywords.

No preprocessor commands which redefine or replace common language elements are allowed. This confuses C++ programmers reading the code, subverting their experience in recognizing the code structure. For example, do not use techniques like these:

#define then
#define begin {
#define end }

if (x == 1) then
begin
  cout << "X is 1." << endl;
end
      

ID: 0139
Topic: Preprocessor
Usage: Mandatory
Languages: C++
Description: Do not use "//" style comments in multiline macro definitions.

Do not use "//" style comments in the definition of a multi-line macro. Since a macro definition can be composed of only one line (a clue that complex macros are a bad idea) all text after the first "//" will be considered a comment. For example:

#define MY_MACRO(arg) arg+one+two+three+four+ \
// Now let's add five and six \
five+six;
      
If you would like to comment the macro, put it before the macro definition, or use "/* */" style comments.

ID: 0071
Topic: Preprocessing
Usage: Mandatory
Languages: C++
Description: Define certain typedefs and #defines for convenience.

The following typedefs and #defines should be implemented or inherited from supporting header files:

typedef int bool;
#define true 1  // As assumed by ANSI C++.
#define false 0 // As assumed by ANSI C++.
#define null 0  // 0, a typeless 0, to allow the compiler to convert it.
                // This prevents older code which uses NULL to properly
                // use a typeless 0 instead.
       

ID: 0106
Topic: Preprocessing
Usage: Recommended
Languages: C++
Description: Use const and enum instead of #define

const and enum should replace the use of #define for manifest constants. This allows more additional type safety, and also is more efficient since it is evaluated at compile time (called "constant folding").

ID: 0107
Topic: Preprocessing
Usage: Recommended
Languages: C++
Description: Use inline functions and templates instead of macros.

Inline functions and templates should replace the use of macros.


Errors and Exceptions

ID: 0140
Topic: Exceptions
Usage: Suggested
Languages: C++, Java
Description: Subsystem Exception Management

Each subsystem has a base exception, from which each class derived it's own base exception, which can then have sub exceptions as required for the methods of that class.

The implementor of the subsystem decides how far down to supply detail.

This allows the caller to deal with the exceptions at any of three levels as provided: complete details for all exceptions, details only on which class (one base exception for each class), or no details at all, for the entire subsystem.

ID: 0142
Topic: Design,Execution
Usage: Mandatory
Languages: Java, C++, C
Description: Reusable packages should not exit.

If a package is meant as a reusable component for building larger systems, it should almost never stop the execution of the overall system. In Java this means no calls to System.exit(). In C++ and C this means no calls to exit(). By keeping the execution alive, other parts of the system may be able to continue execution and prevent data loss if the error is properly signaled. Consider the use of Exceptions instead (except C).


Multithreading

ID: 0146
Topic: Multithreading
Usage: Recommended
Languages: OO, Java, C++
Description: Handle inter-subsystem calls under multithreading

Many modern applications employ multithreading to allow a single body of code to execute in several sections simultaneously. However, when these sections try to call each other, blocking can become a problem.

Whenever one thread of control invokes another section of the system (called a "handler" here), especially over a network, it is best for the handler to return the thread of control as rapidly as possible to the caller. One way to achieve this is to make note of the message inside the handler, and then return immediately, allowing another thread belonging to the handler to work off the request. If the handler blocks, it puts the caller at risk while it is blocked.


Date Representation

ID: 0147
Topic: Representing the year
Usage: Mandatory
Languages: OO, Java, C++, C
Description: Use sufficient precision when representing the year

When any date is represented, in running code or when stored in any persistent or transient storage (everywhere folks!), the date must be represented with at least 4 digits as a text string, or an integer of at least 16 bits as an internal number.

Problems arise when computations compare pairs of dates that straddle January 1st, 2000 (2000-01-01). Although many clever schemes exist for making specialized assumptions and continuing to use 2 digit dates (for text strings) or 8-bit integers, these are perilous. Be advised that the trouble can occur any time the dates straddle 2000-01-01. So these have been occurring for years, and will continue to occur in the future for software that is incorrectly implemented with insufficient precision in the year representation.

Please overlook the storage size implications, as the reduction of latent bugs in the code is worth the impact.


$Id: style.html,v 1.34 2005-08-19 15:44:01 rlv Exp $
$Source: /h/cm/style/style.html,v $

Ralph L. Vinciguerra - TRDC - Editor