Suggested coding standard
Contents
General policies
This page documents some current coding standards being used by various contributors. It is meant as a starting point for a formalised OPM standard at some point in the future, and is therefore subject to change.
As a guideline, most rules suggested in C++ coding standards by Sutter and Alexandrescu should be considered in force. Some exceptions may be made, to be listed later. Among the things explicitly not covered by the book are administrative and editing rules, given below.
Administrative considerations
Naming of files
- C++ header files should always end with .hpp.
- A file defining a class SomeClass should be called SomeClass.hpp.
- Files implementing templates should end with _impl.hpp, for example SomeClass_impl.hpp
- C++ implementation files (other than templates) should always end with .cpp.
- A file implementing a class SomeClass should be called SomeClass.cpp.
- C headers end with .h.
- C implementation files end with .c.
Naming of classes, functions, variables etc.
- Class names start with a capital letter. Extra words in the name start with capital letters (UpperCamelCase).
- Function names (including both members and free functions) start with a lower-case letter. Extra words start with capital letters (lowerCamelCase).
- Variables have names in all lower case, separated by underscores (in_other_words_like_this).
- Member variables end in an additional underscore (like_this_).
- Macros are sometimes necessary, but always dangerous. So they are named with only capitals, and underscores if several words (LIKE_THIS).
- Enums and the names they contain are named like classes.
- Template arguments that are completely arbitrary, and that may be satisfied by int, double and other builtin types, are generally called T, or T, U, V etc. if more are needed. In this case you should also use typename, as in 'template <typename T>'. Examples in this category include the arguments of generic containers, smart pointers etc.
- Template arguments with more requirements, such as the argument being a forward iterator, or a well type, or a pressure solver, should be named like classes.
Whitespace
- Indentation is 4 spaces.
- K&R style placing of braces (with modifications):
- For namespaces, classes and functions, place starting braces on a separate line, not indented.
- For control structures such as for, if, switch and else, place starting braces on the same line.
- Ending braces always go on separate lines, except when followed by else or else if.
- Always put one space around the parentheses of for, if and similar statements.
- Never put space between a function name and its parentheses.
- After separators like commas, or semicolons in for statements, always put a single space.
- (recommended) Put spaces around binary operators.
- In particular assignments (mandatory).
- In mathematical expressions, you may or may not use spaces around the multiplication operator.
- Use blank lines to make code readable. Too much whitespace in the wrong spot makes the code less readable, not more.
- Separate logical blocks by a single blank line in functions.
- Never use more than a single blank line inside functions.
- For separating methods of a class, use blank lines if implementations are inline, else use blank lines to separate blocks of related functions.
- To separate classes, functions, namespaces, use plenty of blank lines. Especially if there are huge template arguments involved.
Example:
namespace Opm { void freeFunction() { for (int i = 0; i < num_stuff; ++i) { const bool ok = foo(); if (!ok) { bar(); } else { foobar(); } } } class SomeClass { public: SomeClass() : var_(-1) { } someMethod(const double alpha) { // Math stuff const int factorial_of_3_plus_5 = 1*2*3 + 5; const double cos_alpha_approx = 1.0 - alpha*alpha; // Other stuff OtherClass::staticMethod(); } private: int var_; }; } // namespace Opm
Use of source code version control systems (git, svn, hg etc.)
- All development shall use a version control system.
- Code in common repositories shall compile.
- When making any changes, even trivial whitespace or organizational edits, write a log message.
- The first (keep to 60 chars) line of the log message shall be a concise summary of the changes. Elaborate on successive lines if necessary.
- Make multiple small, concise commits instead of big, sweeping changes.
- With distributed systems (hg, git), committing in the middle of non-working changes is ok, but postpone pushing to common repositories until it compiles.
Programming guidelines
- Use const whenever possible, including for simple function arguments.
- Always use braces to enclose blocks of if, while, for statements, even if only a single line.
- When writing #include directives, always use full paths, i.e. #include <opm/core/utility/SparseTable.hpp>.
- Preferred ordering of #include directives:
- The header file for the current class or function
- Other OPM headers
- Third-party headers (Dune, Boost etc.)
- System headers (<algorithm>, <vector> etc.)
Some helper files
These files make it simpler to follow the above rules.
If you use emacs, the .emacs file below will ensure that you use 4 spaces for indentation and avoid tabs. It will also insert a copyright header that is suitable for OPM at the start of every new C++ file you create, you may want to edit this part (especially the organization or name) or remove it.
The astyle program is a simple program that formats source code according to rules and definitions. The .astylerc file contains suitable definitions for OPM.