CEPS  24.01
Cardiac ElectroPhysiology Simulator
Code conventions

When contributing to CEPS, developers must comply with the following set of coding conventions. Some of these rules raise an issue when analyzed with cppcheck and sonarqube, which contributes to the total number of "code smells" and lowers the maintanability rating. Additionnally, you can find on this page information on how code coverage is measured. Source files within the tests directory are not analyzed.

Naming

  • CEPS uses the CamelCase naming convention.
  • Variables, functions and methods must start with a lower case letter.
  • Protected and private attributes of classes must be prefixed with m_.
  • Class names must start with an upper case letter.
  • Function and class names should not exceed 30 characters.
  • Abstract base classes must be prefixed with Abstract.
  • When writing cpp files, use the full name of methods, including namespace prefix, instead of putting them in a namespace block.

Indentation, lines, alignment

  • Code must be indented with blocks of 2 spaces. No tabulations must be present in any file.
  • Blocks must be opened and closed as follows:
statement (condition)
{
// indented code
}
  • The public, protected, private sections of a class declaration must be indented within the class block. The methods and attributes within these blocks must be indented as well (4 spaces from the start of the line).
  • A single line must not contains more than one statement.
  • The return type of a function and templates must be written on seperate lines than the full name of the function (including class or namespace prefix)
  • Lines should not exceed 100 characters. Line breaks are authorized, alignments of code are welcome (praise vim's block selection).
  • When a list of arguments of a function is too long to fit in a single line, use the following syntax, even in header files:
template <typename T1>
void
classOrNamespace::myFunctionWithManyParameters(
type1 arg1,
longtype2 arg2,
longlongtype3 arg3
)
{
// awesome code ...
}
  • An extra empty line must be added at the end of the file for better parsing of analysis tools.

Comments

  • All declared elements must be documented using a doxygen comment.
  • The @param arguments of doxygen comments for funtions are not mandatory, especially when the argument names are explicit
  • All comments should be inlined with // for easier toggling between code and comments.
  • All source files must contain the licence and authors header (see contrib/release/generateHeaders.py)
  • All source files must contain a \file doxygen comment.

Types

  • Even if it is not compliant to the C syntax of pointer declaration, the * and & must be placed directly after the typename: const CepsReal& a; CepsVector<CepsReal*>* vec; This makes identifying types of variables faster.

Templates

  • Avoid excessive use of templates. Use class attributes instead, whenever possible.
  • Prefer the keyword typename instead of class in template declarations.
  • Place template definitions in separate .tpp files that are included from the header file containing their declarations. You can still include the .hpp from the the .tpp to make your IDE recognize the symbols without affecting compilation.

Includes

  • Specifiy the full path name from src for CEPS files.
  • Use #pragma once instead of #ifndef directives.

Debugging

  • When debugging, if you want to print some information instead of using the debugger, use the DISP or DISPR macros. They can take up to ten arguments, and display both the expression to print and its value. After debugging, make sure no other file than CepsIoMacro.hpp and the documentation file of this page contain these macros.

Code coverage

Here are the compilation flags used to determine code quality:

-fPIC --coverage -Wall -Wno-long-long -pedantic -fdiagnostics-show-option -O1 -fno-inline -fno-omit-frame-pointer -fno-optimize-sibling-calls

Then, coverage is measured with the following options:

gcovr --exclude-unreachable-branches --exclude-throw-branches -r . -x -o ceps-coverage.xml
A namespace for all utility methods.

Here are some advice to improve coverage:

  • Write very small unit tests limited to each implemented feature.
  • Use utilities that are defined in the common directory, such as ceps::getNew instead of the new operator, the macros CEPS_ABORT, CEPS_WARNS, etc.
  • Avoid boolean conditions that are too complicated as they create lots of branches. For example replace
    CepsBool isOk = s=="YES" or s=="1" or s =="TRUE" or s == "ON" or s=="OK"
    bool CepsBool
    Booleans.
    Definition: CepsTypes.hpp:124
    by
    CepsVector<CepsString> oks({"YES","TRUE","1","ON","OK"});
    CepsBool isOk = ceps::contains(oks,s);
    std::vector< _Type, _Alloc > CepsVector
    C++ vector.
    Definition: CepsTypes.hpp:155
    CepsBool contains(const CepsVector< _Type, _Alloc > &vec, const _Type &item)
    Tells if vectors contains a given item.
    Definition: CepsVector.hpp:56

Many others

  • Just follow what is already in place.
  • If you encounter some bits of code that do not follow these rules, please contribute by formatting them appropriately. Thanks.