B.2. POOMA Coding Conventions

POOMA has been written by several different sets of developers. We describe the coding conventions generally used throughout the code, but there are, of course, exceptions. To see the coding conventions in practice, view random files in the src subdirectory. The src/FileTemplates subdirectory contains very short files illustrating some of the coding conventions.

B.2.1. POOMA Namespace

Most implementation functions and classes are placed within the Pooma namespace. Some user-level functions are also within this namespace, e.g., Pooma::initialize and Pooma::finalize. This is incompletely implemented because some C++ compilers did not correctly implement namespaces.

B.2.2. Formatting

Indentation follows the GNU Emacs's C++ mode guidelines. Most increases in indentation levels start two characters to the right.

Most brackets, e.g., in function definitions, occur on separate lines. Exceptions are for very short functions.

There is no space between a function's name and the left parenthesis starting its parameter list.

B.2.3. Preprocessor

B.2.3.1. Comments

Almost all comments begin with //. /* … */ comments occasionally occur when commenting an intraline value.

C files, including header files, exclusively use /* … */ comments.

B.2.3.2. Preprocessor Symbols

Preprocessor symbols are used only for preprocessor conditional expressions, not to define constants. Such symbols consist of all capital letters with underscore symbols separating words. They begin with a POOMA_ prefix. For example, if POOMA_BOUNDS_CHECK represents a true value, then conditionally included code to check that indices are within a domain should be included.

Header guards also consist of all capital letters with underscore symbols separating words. They begin with POOMA_, continue with names of directories and files, and end with _H. For example, POOMA_UTILITIES_MODELELEMENT_H guards src/Utilities/ModelElement.h.

B.2.3.3. Preprocessor Macros

Inline functions are preferred over preprocessor macros. The latter do occasionally occur. Usually their scope is quite limited (sometimes to just one file), and their purpose is to avoid writing repetitive code. For example, src/PETE/PETE.h defines PETE_EMPTY_CONSTRUCTORS(CLASS) as the three types of constructors for classes with parameterless constructors.

The main other use is to define macros that need access to the __FILE__ and __LINE__ preprocessor symbols to produce error messages. For example, CTAssert in src/Utilities/PAssert.h uses this.

B.2.4. Global Variables

Global variables are avoided whenever possible. Where necessary, their names are the concatenation of capitalized words such that the first word is not capitalized and a suffix of _g is appended, e.g., veryFewGlobalVariables_g.

B.2.5. Classes

In this section, we describe coding conventions for classes, both templated and not templated.

In files declaring classes, the comments near the beginning frequently begin with a listing of the classes followed by a high-level explanation of the classes' public interface. A longer explanation including implementation details usually precedes the class declaration.

Class names tend to be concatenations of capitalized words without underscores, e.g., Field and RefCountedPtr.

Most classes are declared using class, not struct. The latter is frequently used for implementation and compile-time classes that have only public members.

Template parameters are declared using the class keyword, rather than the typename keyword. The latter is used when required by C++ to resolve parsing problems.

Default template parameters are sometimes used.

The order of class members is usually:

public

internal types

Usually end with _t. Name consists of the concatenation of capitalized words without intervening underscores.

constructors

destructors

member functions

Usually named by the concatenation of capitalized words without intervening underscores but having an uncapitalized first word.

protected

This section is frequently empty. If so, do not list the protected tag.

private

This section contains private data members and less frequently private functions. If this section is empty, do not list the private tag.

The order sometimes changes if required to be correct C++ or eases the ordering. Two different sections are frequently separated by a one-line comment with seventy-six hyphens. An explanatory comment usually precedes each member.

Member data is almost always private or protected. Function accessors permit access.

Names of internal types usually are formed by the concatenation of capitalized words without intervening underscores followed by _t. Names of member functions are similar except the first word is not usually capitalized and they have no suffix. Names of member data are similar to names of member functions except they end with _m.

Most functions are defined directly in the class declaration. Functions with long function bodies are defined in .cpp files for templated classes and in .cmpl.cpp files for untemplated classes.

Functions make liberal use of const both to modify parameters and member functions.

Templated member functions are permitted.

Overloaded member functions are permitted. Operator overloading is permitted.

Default arguments are permitted.

Many functions are marked inline. This assumes the optimizer can handle a large number of inlined functions. Even functions defined inside class declarations are marked inline even though the C++ standard requires them to be inlined if possible even if not so marked. This is because some optimizers attempt more aggressive inlining for explicitly marked member functions.

The POOMA inheritance hierarchy is quite shallow, both from the user's and from the implementation point of view. A majority of the uses of inheritance are to factor out a common implementation and reduce coding.

Virtual functions are usually avoided because they can execute slowly.

B.2.6. Functions

Class member functions are preferred over global functions when they achieve the same purpose. Guidelines for global functions are the same as for class member functions: A function name is a concatenation of capitalized words without underscores and with the first word not capitalized. inline and const are aggressively used. Templated member functions, overloaded member functions, operator overloading, and default arguments are permitted.

Functions return references and constant references when appropriate.

B.2.7. Friends

Friend functions are rare and are usually defined directly within the class of which they are a friend. Friend class declarations do occur.

B.2.8. Compile-Time Programming

Compile-time structures and static functions occur throughout the code. Most of the classes are structs since they have only public members. The coding conventions follow those for run-time code. Enumerations are a preferred way to declare integral constants.

B.2.9. Constants

Enumerations are preferred over declaring constant integers.

Use the const keyword, not preprocessor definitions, to define constants.

B.2.10. Type Casting

Type casting usually indicates a design flaw so it is rarely used. When it is used, use static_cast, dynamic_cast, or reinterpret_cast.

B.2.11. Errors and Exceptions

POOMA code uses very few exceptions since not all C++ compilers adequately support exceptions. Thus, all uses must also have corresponding code not using exceptions. See, e.g., POOMA_EXCEPTIONS in the code.