Skip to content

CodingConventions

Rupert Nash edited this page Oct 19, 2015 · 3 revisions

HemeLB C++ Coding Conventions

Indentation style

Use the style defined in the Eclipse project! Most importantly: Tabs: 2 spaces with no tabs to be used at all Braces: to follow on the next line with no ident and be followed by a newline. The contained block to be indented one level

Header files

HemeLB headers that are #included must be included relative to the top-level code directory, even from within their .cc file.

Header files must have an include guard of the form:

// In Code/subsystem/Class.h
#ifndef HEMELB_SUBSYSTEM_CLASS_H
#define HEMELB_SUBSYSTEM_CLASS_H
// declarations here

#endif // HEMELB_SUBSYSTEM_CLASS_H

Naming rules

  • Acronyms should only be used when they are very standard and only the first letter should be capitalised (if upper case is appropriate), e.g. BgkCollisionOperator.
  • Numbers of things should, if they are part of the public interface, be named NumberOfThings

|| Thing || Style || Notes || || Namespaces || lower_case_with_underscores || Namespace names should be kept as short as practical || || Classes || UpperCamelCase and a noun || In tickets and wiki pages, be aware this will create a wikilink unless the name is escaped with ! || || Member variables || lowerCamelCase without an "m" prefix || || || Member functions || UpperCamelCase and starting with a verb || e.g. CalculateSomething || || Function arguments || lowerCamelCase ||The ordering must be: input, in/out, output || || Local variables || lowerCamelCase || One may be terser here. Any local acronyms must be defined in a comment. || || Template parameters and constants || ALL_CAPS || To be used for symbols handled at compile time. ||

Member functions which are accessors (setters/getters) should be written as GetVariable and SetVariable except for getters which are numbers of things, which should be written as either NumberOfVariable or VariableCount (author's choice) and for boolean properties, which should be written as HasVariable or IsVariable (author's choice). The private variable name should reflect this choice.

|| Variable name || Getter || Setter || || nameOfOverlord || GetNameOfOverlord || SetNameOfOverlord || || isEvil || IsEvil || SetIsEvil || || hasMinions || HasMinions || SetHasMinions || || minionCount || MinionCount || SetMinionCount || || numberOfMinions || NumberOfMinions || SetNumberOfMinions ||

Physical Quantities

When a variable/argument/return type represents a physical quantity, the type name must indicate the dimensionality of the quantity (e.g. length) and the base of the units (lattice or physical). These must be named as a class. The two acceptable bases are lattice units and physical, SI, units. For example:

  • PhysicalLength
  • LatticeDensity

In a later milestone compatibility of quantities will be enforced at compile time (e.g. via boost). In the meantime this naming will make the programmer aware of the dimension of the quantities.

Boundaries

Some nomenclature for different types of boundaries:

boundary - any generic boundary, whether with a solid wall or an inlet/outlet wall - a solid wall hence: wall site - a site adjacent to a wall - adjacency being determined by the site having one or more links (from the active velocity set) intersected by a wall

iolet - an inlet or outlet inlet - a boundary which will generally have an inflow of fluid outlet - a boundary which will generally have an outflow of fluid

hence: iolet site - a site adjacent to an iolet, determined by the site having one or more links (from the active velocity set) intersected by an iolet.

Class interfaces

Structs are only to be used for plain old data (POD). If you add a method, you must make it into a class.

Public member variables are not acceptable. Inline getters and setters should implemented where necessary. We should implement some standard getter/setter generation macros.

Method input arguments precede method output arguments.

Visibility: protected should be preferred in most case. private should be used for helper methods that don't implement complete functionality on their own or when it is unsafe to expose them.

Avoid relying on operator precedence

Although correct due to operator precedence, expressions such as

bool participateInTopology = !reserveSteeringCore || topology::NetworkTopology::Instance()->GetLocalRank() != 0;
bool xMin = i == 0;

Tend to be brittle when modified in later code maintainance. All but the most obvious operator precedences should be made explicit through parentheses:

bool participateInTopology = !reserveSteeringCore || (topology::NetworkTopology::Instance()->GetLocalRank() != 0);
bool xMin = (i == 0);

Prefer testability over encapsulation

When doing Test Driven Design, which focuses on comprehensive unit tests, it is often necessary to make methods of classes public which could otherwise be private or protected. This is part of the unit testing paradigm, and is unfortunate, but acceptable in C++. (Some languages allow unit testing libraries to explicitly violate encapsulation, C++ does not.) While every effort should be made to maintain encapsulation, (such as use of template mocks, or producing a derived class which opens protected methods with a delegating constructor), some modification of method privacy may from time to time be necessary to achieve testability, and test coverage should not be sacrificed to maintain encapsulation.

Explicitly Include all headers

If you reference a class Foo, and Foo is defined in foo.h, then you must #include foo.h. This applies even if you also use class Bar, and Bar uses foo, so that bar.h includes foo.h. The code would compile without #including foo.h, because it would be included by bar, but you should include it separately, in case the implemenentation of bar changes. Our use of #ifdef include guards means this is safe and will not measurably increase compile times.

Clone this wiki locally