Coding Conventions

Here we have laid down the coding conventions used throughout the SENF framework. Please ad here to these conventions when changing or adding code. If you use emacs, you can use the C++ IDE for emacs from http://g0dil.de which greatly simplifies following these conventions.

Files should be named according to the main class they define. A single header file should define only one main class. Exceptions to this rule are OK.

Rationale:
This simplifies finding the implementation/header for a given class and also reduces the size of each single file.
The implementation is divided into a number of different files:
.h C public header
.hh C++ public header
.ih C++ internal header used only by the implementation. This header will probably be included indirectly by the public header but is not meant to be perused by the library user
.c C implementation
.cc C++ implementation of non-inline non-template functions and members
.ct C++ implementation of non-inline template functions and members
.cci C++ implementation of inline non-template functions and members
.cti C++ implementation of inline template functions and members
.mpp Special include file used for external iteration by the Boost.Preprocessor library
Rationale:
There are two part's to this: First, separating the implementation of inlines and templates out of the header file makes the header file much easier to read. This is important, since the header file will be used as a reference by the developers.
Separating inline from non-inline members is used together with the prefix_ convention below to ensure the correct placement of inline vs non-inline members in the source code. The C++ language requires, that inline members must be included into every compilation unit, non-inline members however must be included only in one compilation unit. Placing the inline members into a separate file allows to automate this: Simply moving an implementation from one of the inline files into one of the non-inline files will change the type of implementation accordingly.

SENF prefers the use of the CapitalziedLettersToSeparateWords convention for class names. In this case, class names must start with a capital letter. There are some exceptions to this rule: Types which define new basic data types to be used like other built-in types may be named using lowercase letters plus underscores. Also, if a type or class is directly related to some other library (STL or Boost) which uses the underscore convention, it might be more sensible to follow this convention. This is open to debate.

Rationale:
Naming types with capital letters nicely gives a visual clue, that a symbol is a type name. This can also be used by the editor to highlight type names correctly. Additionally, this convention is compact and does not add additional or repeated overhead.

Only in very few places, SENF allows the use of inline implementations (not to be confused with inline functions). An implementation is inline, if it is written directly into the class definition in the header file. Again there are exceptions to this rule but they are very few:

  • When defining simple exception classes, the 'what()' member may be defined inline if it returns a string constant.
  • It may be OK to use inline implementations for one-line implementations in internal headers.
  • The Packet library allows inline implementations for the definition of parsers since doing so outside the declaration just gets to verbose and parsers definitions are quite length but very simple and straight forward.
Rationale:
Implementing members inline inside the class declaration makes the declaration much harder to read. Since the declaration in the header file will be used as a reference by the developer, the header files should be as readable as possible.
Every function or method implementation in one of the implementation files must always be prefixed with prefix_. This symbol is defined at the beginning of the file and undefined at the end. The symbol must be defined to be inline in the .cti and .cci files and must be defined empty in the .cc and .ct files.
Rationale:
Together with splitting inlines and non-inlines into separate files, this allows to automatically include the inline definitions at the right places. See above.
Private data members are named with a trailing underscore character.
Rationale:
This helps distinguishing local variables from parameter names. The trailing underscore does not interfere with other naming conventions and is allowed by the standard (underscore at the beginning of the name are problematic since some classes of names beginning with an underscore are reserved for the standard library implementation)