The most important coding rules goal is the consistency of the code (i.e. no matter who writes the code).
In order to reach this goal, the rules must be written so that it reduces the number of ways to write the code.
However, they are not absolute. Exceptions can be made if justified.
Coding rules
Rules that describe the way to implement.
- General
- Friendship: only when declaring operators (i.e.
<,==,<<, ...) - Shared pointers: only for child classes of interfaces
- Dynamic allocation: do not use (i.e. no use of
new) - Exceptions: do not use
- Cast: if possible, use
static_cast, elsereinterpret_cast. Do not usedynamic_castorC style cast - Comments for:
- implicit required condition of well running
- libraries
- class, function or variable with names that cannot be explicit enough
- Macros:
- when using
__FUNCTION__or__LINE__ - for callback declarations: 2 macros:
CALLBACK_PARAMandCALLBACK_LAMBDA(...) [__VA_ARGS__](CALLBACK_PARAM)
therefore, callback declaration is made withCALLBACK_PARAM
- when using
- Aliases: use the
usingkeyword instead of thetypedefkeyword and only for the function types - Lambda: use
std::functionas the type but declare it with alambda function - Inheritance: do not use inheritance except for interfaces. Use composition over inheritance instead
- Dead code: do not use (no what-if code)
- Files: only one class per file, except for header-only libraries
- Libraries:
- if possible, implement as header-only library
- split declarations and implementations, place all declarations at first. No split for templated classes
- Friendship: only when declaring operators (i.e.
- Headers
- Header inclusion: no forward declaration
- Header guard:
#pragma once- Declaration order
- Accessibility order:
- public
- protected
- private
- Categories order:
- Sub-classes
- Static methods
- Static members
- Non-static methods
- Non-static members
- Accessibility order:
- Declaration order
- Sources
- Definition order: same order as declared
- Include order
In alphabetical order for each category:
- Corresponding header
- Standard library headers
- External depedencies headers
- Project headers
- Include order
In alphabetical order for each category:
- Definition order: same order as declared
- Variables
- Declaration
- Instruction: only one declaration per line. This rule also applies for class members
- Initialization: if possible, initialize variable on declaration. This rule also applies for class members
- Scope: declare the variable inside a method, a class, or a namespace
- Pointer/Reference: use references instead of pointers when the value is not optionnal, unless the object is contained in a data structure
- Constness: maximize the constness of variables
- Primitive type: use only strong primitive types (ex:
uint32_t,double_t) - Type: use the most accurate types (ex:
istringstreaminstead ofstringstream) autokeyword: use only for lambda, loop-variable and types that are longer than 15 characters
- Declaration
- Functions
- Inline functions: use only trivial setters and getters
- Side effect: avoid side effect functions
Exception valid for: data structures, in-out parameters, multiple outputs Returninstruction: immediately exit a function when a required condition is not fulfilled- Parameters
- Default value: no default value
- Passing: pass primitive types by value, pass any other types by reference
- Structs
- Usage: use structs for mainly public attributes and methods
Other rules inClasses
- Usage: use structs for mainly public attributes and methods
- Classes
- Constructor: do not use implicit conversions, use the
explicitkeyword - Virtual: declare the destructor as a virtual for classes that contain virtual methods
- Sub-classes: do not use
- Accessibility: minimize the accessibility of the class members
- Constness: maximize the constness of the member functions
- Static: static class implemented as singleton, all static methods must call their corresponding private member method
- Singleton: do not use singleton for libraries, create an object named
instancein a namespace named_private
- Constructor: do not use implicit conversions, use the
- Namespaces
- Usage: use namespaces for libraries and for
from_stringandto_stringof enumerators usinginstruction:using namespaceinstruction should be avoided or used in a function scope or namespace scope (not in global scope)
- Usage: use namespaces for libraries and for
- Enumerators
- Converters: define
from_stringandto_stringin the namespace correspoding to the enum
- Converters: define
Naming rules
Rules that describe the way to name.
- General
- Language: English only
- Word
number: do not usenumber. Usecount,idorindex(ex: carId instead of carNumber) - Plural: no plural, describe as a container (ex: carList instead of cars)
- File name: same as declared/defined class, SnakeCase without leading
E_for enum
- Headers
- Extension:
.hif associated with a.cppfile, else.hpp - Content:
.hfiles only contain declarations,.hppfiles contain both declarations and definitions
- Extension:
- Sources
- Extension:
.cpp
- Extension:
- Variables
- Iteration index:
i, j, k...are reserved name for iteration index - Case: camelCase
- Naming: custom typed must have same name as type in camelCase (ex: FileWatcher fileWatcher)
- Boolean: boolean variables must start with
boris - Container: container variables must end with the type of the container (ex: std::map<string, int> nameAgeMap)
- Modifiers (as class member)
- Private/Protected/Public: do not use any marker
- Constant: SCREAMING_SNAKE_CASE
- Static: do not use any marker
- Iteration index:
- Functions
- Overloading: function names must be unique, except for templated functions
- Case: camelCase
- Boolean: boolean functions must start with
boris - Modifiers (as method member)
- Private/Protected/Public: do not use any marker
- Static: do not use any marker, only a leading
p_for the corresponding private method of the singleton
- Enumerators
- Case: SCREAMING_SNAKE_CASE with leading
E_and trailing_TYPE - Enum values case: SCREAMING_SNAKE_CASE
- Namespace: same name as enum without leading
E_
- Case: SCREAMING_SNAKE_CASE with leading
- Classes
- Naming
- Modifiers
- Interface (only virtual pure methods): leading
Iimmediately followed by PascalCase and should end withable(ex: IPlayable) - Abstract: leading
Aimmediately followed by PascalCase - Static (only static methods): do not use any marker
- Templated: do not use any marker
- Interface (only virtual pure methods): leading
- Order:
- Data involved (ex: Car, Shoe, Key) (still no plural)
- Data processing method (ex: Watcher, Cleaner, Filter)
- Extension: the child class name must end with its parent class name
Abbreviate the parent name if its length is greater than15
Add a comment just above the parent class to define the used abbreviation Other rules inTypes
- Modifiers
- Naming
- Namespaces
- Case: snake_case
- Types
- Case: PascalCase
Format rules
All of the format rules to apply are defined in the clang-format file.
MIT Licence. See LICENSE file. Please refer me with:
Copyright (c) Nicolas VENTER All rights reserved.