Code convention#

Why code conventions?#

The question seems trivial, even needless, but is truly fundamental. The reasons, shown for example on the Sun homepage are the followings:

  • 80% of the lifetime cost of a piece of software goes to maintenance.

  • Hardly any software is maintained for its whole life by the original author.

  • Code conventions improve the readability of the software, allowing engineers to understand -new code more quickly and thoroughly.

  • If you ship your source code as a product, you need to make sure it is as well packaged and clean as any other product you create.

The purpose of these conventions is to centralize information, to make decisions when ambiguities may exist, and to homogenize contributions of different programmers of a team, to make maintenance easier and to enable identification of code specific programming elements versus language specific programming elements.

The last point is the most important when we develop a code in C++, because this programming language has no true object code convention, because it is an object extended language and not a true object language. You just have to see names of STL classes, written lower-case, as C types to understand the difference between object languages such as Java and the modelling language UML. This is the reason why we will have conventions in the mainframe of the XLiFE++ project : a naming convention, a code convention, and an API documentation convention. The last one is dedicated to standardize comments, in order to use Doxygen.

Naming convention#

General points#

  • The reference language is English.

  • User objects and only user objects can be aliased in other languages than English.

  • The encoding of every file is UTF-8

  • An acronym used in the name of a class, function, variable, … behaves like a word. It is written lowercase except the first letter in specific cases we will see in the following.

  • Explicit abbreviations are strongly encouraged. Ex: Ref for Reference, Geom for Geometry, Elem for Element, Nb for Number, …

Directories#

Directories behave like libraries. That is evidence for Java programmers. Their names are defined in the same way.

  1. A directory name is written with words joined without delimiters. Each word is capitalized except the first one. Ex: essentialConditions

  2. The _ symbol is forbidden.

Files#

  1. The encoding of every file is UTF-8

  2. A header file extension is .hpp

  3. A source file extension is .cpp

  4. The name of a file that defines at least one class is the same as the main class defined in it. As a result, the name is written with capitalized words joined without delimiters. Ex: PrintStream.hpp

  5. The name of a file that defines only external functions is written with capitalized words joined without delimiters, except the first word that is lower-cased. Ex: printUtils.cpp

Class, enum, struct and typedef#

In the following, we will not make differences between the four types, unless specific mentions.

  1. The name of a class is written with capitalized words joined without delimiters. Ex : GeomRefElemSide

  2. The name of a typedef on a class is written with capitalized words joined without delimiters. It is a short name remembering the original class name with the suffix _t.

  3. The name of a typedef on a variable is written with capitalized words joined without delimiters except for the first one that is lower-cased. It is a short name remembering the original variable name with the suffix _t.

  4. An enum item is written with capitalized words joined without delimiters except for the first one that is lowercased, with the prefix _

  5. The _ symbol is forbidden except for the typedefs and the following cases : For a template class: if a template parameter is devoted to be an iterator, you will add the suffix _it.

  6. If a class is dedicated to be a collection or if it inherits of a collection from the STL, you will use the plural and not the suffix List. Ex: Parameters

Functions#

  1. The name of a function is written with capitalized words joined without delimiters, except the first word that is lowercase. Ex : printTheDomains

  2. The _ symbol is forbidden.

Variables#

  1. The name of a variable is written with capitalized words joined without delimiters, except the first word that is lowercase. Ex : refElements

  2. The _ symbol can be used only in the following cases:

    1. For a private or protected attribute, except for pointers, you will add the suffix _. Ex: point_

    2. For a pointer, public or not, you will add the suffix _p. Ex: parentDomain_p`

    3. For an iterator, you will add the prefix it_ if you want to give a name different from it. You may use the variable name to which the iterator is defined. Ex: an iterator on a Matrix object named a should be called it_a.

  3. If a variable is a collection, you will use the plural instead of the suffix List. Ex: elements

Macros#

  1. The name of a macro is written with uppercase words joined with the _ delimiter. Ex : #define XLIFEPP_WITH_GMSH

  2. For macros dedicated to multi-include protection, the name is based on the file name and a _ replaces the dot. Ex : #define GEOM_REF_ELEMENT_SIDE_HPP for GeomRefElementSide.hpp

C++ convention#

General points#

  • The reference language is English.

  • User objects and only user objects can be aliased in other languages than English.

  • The encoding of every file is UTF-8

  • Minimal C++ standard is C++11

  • In any case, you will use exceptions functionalities. You use the messages’ manager developed in the code.

  • In any case, user classes are template classes. The main program has to be the easiest possible.

  • Each piece of code is protected by a namespace defined in header files. The namespace is xlifepp.

  • In any case, you will use the using keyword in a header file. You can use it in source files. Then, the user has the choice in the main program to use it or not.

Files#

When you define a class, you define a header file (extension .hpp) and a source file (extension .cpp). 2 cases may occur:

  1. The header file is included only by other header files from the same library (i.e. the same directory). In this case, there is nothing more to do, it is an “internal header file”.

  2. The header file is included by headers from others libraries (i.e. other directories). In this case, you define a header file with the same name, .h as extension, place it in the include directory, and include the original header files (extension .hpp)

    When you compile your class, you will only need what is in the library you are in and what is in the include directory. This is a way to hide the file organisation to each piece of the code.

Class, enum, struct and typedef#

It is highly recommended using the pointer on current object this inside class operations to avoid ambiguities between external functions and class operations of the same name. An external developer will have better and quicker access to the understanding of your piece of code.

Loops and conditional syntaxes#

Only the 2 following forms are authorized:

  1. The one-line syntax, with or without braces. Ex:

    if (n>0) { a(n) = 1; }
    
  2. The multi-lines syntax with braces, whatever their position. Ex:

    for (int i=0; i<n; i++) {
      a(i)=1;
    }
    for (int j=0; j<n; j++)
    {
      b(j)=2;
    }
    

API documentation policy#

The API reference documentation is compliant with Doxygen syntax and the HTML documentation is automatically generated with majors updates by the source control manager.

It is the responsibility and the duty of the developers to write these documentations in English.

General points#

  1. The reference language of the documentation is English.

  2. Function or operation declarations are documented with brief (one-line, one-sentence) comments and only brief comments.

  3. Function or operation definitions (inline or not) are documented by detailed comments.

Files#

Here is the structure of the comment you have to write to document a file (header or source):

/*!
  Brief comment

  \file Parameter.hpp
  \author T. Anderson
  \date 25 jan 2011
  \since 3 mar 2007

  Next part of detailed comment
 */

This comment is dedicated to present the content of the file: list of classes, list of external functions, … It is written at the top of the file before everything else.

Some additional remarks:

  • Thanks to the QT_AUTOBRIEF = YES parameter, the first line of the comment is interpreted as the brief comment. Therefore, the brief comment has to be placed before everything else. There is another solution with the macro \brief:

    /*!
      \file Parameter.hpp
      \author T. Anderson
      \date 25 jan 2011
      \since 3 mar 2007
    
      \brief Brief comment
    
      Next part of detailed comment
     */
    
  • The \date macro is the last modification date.

  • The \since macro is the file creation date.

  • When there are several authors, you will use the authors macro:

    /*!
      Brief comment
    
      \file Parameter.hpp
      \authors T. Anderson, R. Cypher
      \date 25 jan 2011
      \since 3 mar 2007
    
      Next part of detailed comment
     */
    

    In this case, authors are separated by commas.

The file documentation rules are:

  1. The file documentation is written at the top of the file, before everything else,

  2. The file documentation follows one of the previous syntaxes, with the 4 pieces of information file name, author(s), creation date and last modification date.

Class, typedef, enum or struct#

  1. A class documentation is written just before the class declaration/definition in the header file.

  2. The structure of the class documentation is as follows:

    /*!
      \class A
      Brief comment associated to A
    
      Next part of detailed comment associated to A
    */
    class A {
      ...
    };
    
  3. To document a typedef, you will use the \typedef macro instead of the \class macro;

  4. To document a struct, you will use the \struct macro instead of the \class macro;

  5. To document an enum, you will use the \enum macro instead of the \class macro.

Member data#

  1. Member data can be documented according to one of the following syntax:

    class A {
      public :
        //! Comment associated to i
        int i;
        double j; //!< Comment associated to j
        /*!
          Comment associated to k
        */
        B k;
        ...
    

Functions#

  1. Functions and operations declarations are documented with a brief comment, and only a brief comment. The syntax, shown here for operations but valid for external functions, is one of the following:

    class A {
      public :
        ...
      //! Brief comment associated to declaration of f
      void f();
    
      /*!
        Brief comment associated to declaration of g
       */
      void g();
    
      void h(); //!< Comment associated to declaration of h
    };
    
  2. Functions and operations definitions (inline or not) are documented with detailed comments. If the declaration has not been commented first, the first line of the comment will be the brief comment, as seen in previous sections. The syntax, shown here for inline operations but valid for the others types, is one of the following:

    class A {
      public :
        B b;
        ...
      //! Detailed comment associated to definition of f
      void f() {
      ...
      }
      void g() //! Comment associated to definition of g
      {
        ...
      }
      A() //! Comment associated to definition of composite constructor
      : B()
      {
        ...
      }
    
      /*!
        Detailed comment
        associated to definition of h
       */
      void h() {
        ...
      }
    };
    

    Attention

    For the function g, the comment marking is //! and not //!< and that for the constructor in the same case, the comment is placed before components constructor calls.

Let’s see how to document function arguments.

Input parameters#

In the only case of a function definition (or an operation definition), you may want to document arguments and return value. The syntax is one of the following:

/*!
  Comment on function f
 */
int f (double d, //!< Comment on d
       int i     //!< Comment on i
      ) {
  ...
}
/*!
  Comment on function g
  \param d Comment on d
  \param i Comment on i
  \return Comment on return value
 */
int g (double d, int i) {
  ...
}