LIBPF® Coding Standard

Introduction

Intended audience

This document addresses those who wish to develop models with LIBPF® (model developers).

Scope

This document describes the suggested coding standard for LIBPF®, the LIBrary for Process Flowsheeting version 1.1 and UIPF, the User Interface for Process Flowsheeting version 1.1.

Also see (1), (2), (3), (4) and (5) for more generic stuff.

Prerequisites

Files

Programming language: use C++14 (8), with no proprietary extensions.

File extensions: use h for headers, and cc for C++ sources.

One file per class, file name same as class name; exceptions: homogeneous, small classes and classes within namespaces can be grouped in a single file.

File encoding: use 7-bit US-ASCII (we don’t allow UNICODE in source files for this reason):

7-bit US-ASCII table

Include guard in header files, use PROJECT_FILENAME_H macro, replace PROJECT substring with {LIBPF, UIPF* and replace FILENAME substring with uppercase file name without extension.

Header file skeleton


Source file skeleton


Types and constants

Identifier naming conventions

The order of the words is by decreasing importance (so that when classes or identifiers are sorted alphabetically, homogeneous items are naturally grouped), i.e. the reverse w.r.t. the intuitive ordering in English and German.

First example: Donau-Dampf-Schiff-Fahrt-Gesellschaft-Schiffs-Kapitän-Kabine class name should be: KabineKapitaenSchiffGesellschaftFahrtSchiffDampfDonau.

Second example: the instance name for the yellow box is: boxYellow.

Getter/setter: for getter use variable name, for setter use setVariable.

Comprehensive example:

class MyClass {
private:
   long myVar_;
public:
  long myVar(void);
  void setMyVar(long i);
};
MyClass myInstance;

Abstract classes

Interface-suffixed classes are for pure abstract types that provide no implementation (13).

Most other non-user-facing classes will be mixin classes: abstract types that provide an incomplete implementation, to be used as part of a derived or “including” concrete type to compose a complete implementation (14).

Modules

Module names are single word, lowecase.

Use singular for modules that provide a single class or functionality (core, flowsheet, persistency, utility, user, value) and plural for modules that provide a group of classes (components, phases, streams, units).

TODO flowsheet dove sta ??? TODO add module reactions ?

For API stability and ease of use, there is a single include file for each module:

and a single global include file libpf/libpf.h that includes all the per-module ones.

Namespaces

The whole library is within the Libpf namespace. User-facing types must be in this flat namespace.

Nested namespaces should be used for module-internal, non-user-facing types.

The module namespace must be the module name, uppercased, singular:

Example class names for phases module:

Compilation and link warnings

Follow the guidelines in (10).

In particular:

TODO update here !

Formatting

Do not use tabs, use two blanks for indenting.

Uncrustify indenting standard: see file uncrustify.cfg, tested with uncrustify 0.48

In declarations and definitions use (void) rather than () for a function without parameters.

For an empty code block use { } not ; or {}.

Comments and documentation

Code reading helps

Use this 120-columns, 3-line heading to separate classes whenever there are several interfaces / implementations in one file:

/*====================================================================================================================*/
/*==  ClassName  =====================================================================================================*/
/*====================================================================================================================*/

Decoration: repeat the member function name after the closing curled bracket, skip return value, templates and arguments unless there are several overloads

template<class T> void MyClass<T>::Member(void) {
} // MyClass::Member
template<class T> void MyClass<T>::Member(int) {
} // MyClass::Member int

Group and highlight the getter/setter members, the pure virtual members, the implementations for parent classes’ pure virtual members.

Literate programming

Use doxygen-style literate programming (6), details follow.

  1. In all files:

    • @file

    • @brief

    • @author

  2. In header files:

    • for each class, brief description using the special C++ style on-line comment with ///

      /// Only a short description for the class
      
    • for each method, brief description using the special postponed C++ style on-line comment with ///<

      long var; ///< Only a short description after the member
      
  3. In source files:

    • (if applicable) for a class, detailed description using a block of at least two C++ comment lines, i.e. the a C++ style multiline comment with ///

        /// ... text ...
        /// ... text ...
      
    • (if applicable) for a method:

      • detailed description using the special C++ style multiline comment with ///

      • return using @return

      • parameter documentation using @param

      • documentation on thrown exceptions using @exception

Error reporting

To decide what error reporting mechanism to use in library production code, use this checklist:

References

  1. Todd Hoff, C++ Coding Standard, 2008-03-01

  2. Geotechnical Software Services, C++ Programming Style Guidelines, Version 4.7, October 2008

  3. High Integrity C++ Coding Standard, Version 4.0

  4. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

  5. Dimitri van Heesch, Doxygen Manual

  6. CamelCase on Wikipedia

  7. ISO, “Programming Language C++” ISO/IEC 14882:2014

  8. Bjarne Stroustrup “The C++ Programming Language” 4th ed. Addison-Wesley 2013

  9. Boost: Managing Warnings from Compilers (and other tools)

  10. Exceptions, error codes, and assertions in C++

  11. snake_case on Wikipedia

  12. Abstract type on Wikipedia

  13. Mixin on Wikipedia