RINGMesh  Version 5.0.0
A programming library for geological model meshes
RINGMesh Programming Guidelines

This very short guidelines are non-exhaustive and the developer is invited to read the very nice core C++ guidelines proposed here by Mr Stroustrup and Sutter.

Code formating tool

clang-format

clang-format is a tool which formats the code according to specific rules. These rules are listed in the file .clang-format at the RINGMesh root directory. More information about these rules can be found here. The current clamg-format version used in RINGMesh is 3.8 (should be compatible with newer versions).

Install clang-format

In Linux, just install clang package. Binaries for Windows are here.

How to run clang-format

For Eclipde IDE users, there is a build configuration, called clang-format, to run clang-format. For VisualStudio users, make sure that clang binary directory is in the system path. This path should look like: C: Files (x86). Use CMake to generate the VisualStudio project and launch VisualStudio. Then build the project called format.

Editor integration

For VisualStudio users, there is a tool to use clang-format directly within this IDE. In VisualStudio, just select the code that you want to format, then press ctrl-R, and finally press ctrl-F. For other integration, see the clang-format documentation.

Style and naming conventions

Style conventions

  • Tabulations are to be replaced by 4 space indentation
  • Opening brackets are at the end of the opening block (for, while if...) with a blank space before
  • Closing brackets are at the same level as opening block instruction. Then, go to line for beginning a new block. Exception for the closing bracket of "else"
  • Always open a new block after if, for...
  • Space after '(' and before ')'
  • No space after '[' and before ']'
  • Space after '<' and before '>' for templates
  • Space after ',' and ';'
  • Space before ';' at the end of an instruction
  • Space after and before mathematic operators and comparators (<, >, =, <=, ==, !=, * , +, -, /, ...)
  • No particular rules for blank lines. Please make your code readable.
  • No more than 85 characters per line. If longer, go to next line and add an indentation (4 characters)

Sample code:

for( index_t i = 0; i < N; i++ ) {
double a = 0 ;
if( a < 0. ) {
double b = 6 ;
my_function( a, b ) ;
std::vector< double > c( 6 ) ;
double& d = c[2] ;
} else {
... other instructions ...
}
}

Naming Conventions

  • Use English words to name classes, functions, variables etc.
  • Abbreviations and acronyms are minimized
  • Each word of Class and NameSpace names is capitalized
  • Function and local variables names are lowercase
  • Member variables names are lowercase

Sample code:

namespace RINGMesh {
namespace MatrixUtils {
class DiagonalMatrix: public Matrix {
public:
DiagonalMatrix() ;
void compute_trace() ;
private:
double trace_ ;
} ;
}
}

Documentation

  • Write comments in English
  • Document all classes, functions and variables in doxygen-readable format, preferably in .h files
  • Use // or ///, in implementation comments
void add( int a, double& b )
{
// a commentary
b += a ;
}

Writing Functions

Philosophy

  • A function should perform a single logical operation
  • Keep functions short and simple (less than 10 lines)
  • Prefer pure functions i.e. functions that does not depend on anything else and have no side-effects
  • Use the macro RINGMESH_API if you want your function to be imported in the windows library

Parameters

  • For "in" parameters, pass cheaply copied types by value and others by reference to const
  • For "in-out" parameters, pass by reference to non-const
  • "in" parameters appear before "out" parameters

Style

  • If all the parameters does not fit in the line, write them down in a new line
  • The '{" is opened next line. The instructions are written next line. '}'is placed in a new line too.

Sample code:

void RINGMESH_API compute_next_border_on_surface(
const Surface& surface,
const Border& from_border,
Border& next_border )
{
// instructions
}

Writing Classes

Philosophy

  • Declare a member function that does not modify the state of its object const
  • Define a destructor if a class needs an explicit action at object destruction
  • Be careful, a lot of class have to forbid copy, using
  • Use the macro RINGMESH_API if you want your class to be imported in the windows library
  • For virtual functions in child classes (with the virtual function defined in the mother class), add at the end of the function prototype the keyword "override". This prevents issues of prototypes in virtual functions. In the case of virtual functions which should not be reimplemented in child classes, use the keyword "final" instead.

Style

  • You have to follow the order: public: protected: private: for methods and then again public: protected: private: data members
  • Always put a "_" at the end of the data member names
  • There are no particular rules for blank lines, it is the developer responsibility to make its code clear and well readable

Sample code:

class RINGMesh_API MyClass {
public:
MyClass() ;
void compute_a_thing() ;
public:
int attribute_a_ ;
protected:
double compute_another_thing() ;
protected:
double attribute_b_ ;
private:
void compute_another_thing_just_for_me() const ;
private:
std::vector< double > vector_of_things_ ;
} ;

Source Files

  • Use a .cpp suffix for code files and .h for interface files.
  • Include first third party headers , then RINGMesh Headers
  • Configure CMake in order to use < > instead of " "
  • Avoid cyclic dependencies among source files
  • Corollary: minimize number of #include in .h files (use forward declarations instead)

Sample code:

// Use this
#include <ringmesh/geo_model_mesh.h>
// DO NOT use this
#include <../../include/ringmesh/geo_model_mesh.h>

Pointers

  • Use nullptr from the standard library to define null pointer.
  • Do not use NULL nor nil to define a null pointer.