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_cast
orC 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_PARAM
andCALLBACK_LAMBDA(...) [__VA_ARGS__](CALLBACK_PARAM)
therefore, callback declaration is made withCALLBACK_PARAM
- when using
- Aliases: use the
using
keyword instead of thetypedef
keyword and only for the function types - Lambda: use
std::function
as 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:
istringstream
instead ofstringstream
) auto
keyword: 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 Return
instruction: 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
explicit
keyword - 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
instance
in a namespace named_private
- Constructor: do not use implicit conversions, use the
- Namespaces
- Usage: use namespaces for libraries and for
from_string
andto_string
of enumerators using
instruction:using namespace
instruction 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_string
andto_string
in 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
,id
orindex
(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:
.h
if associated with a.cpp
file, else.hpp
- Content:
.h
files only contain declarations,.hpp
files 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
b
oris
- 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
b
oris
- 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
I
immediately followed by PascalCase and should end withable
(ex: IPlayable) - Abstract: leading
A
immediately 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.