Not An Engineering
Not An Engineering
Programming
13. Code Conventions
Federico Busato
2023-11-14
Table of Context
3 #include
1/80
Table of Context
5 namespace
6 Variables
7 Functions
2/80
Table of Context
9 Control Flow
10 Modern C++ Features
11 Maintainability
12 Naming
13 Readability and Formatting
14 Code Documentation
3/80
C++ Project
Organization
“Common” Project Organization
4/80
Project Directories 1/2
Fundamental directories
include Project public header files
src Project source files and private headers
test (or tests) Source files for testing the project
Empty directories
bin Output executables
build All intermediate files
doc (or docs) Project documentation
5/80
Project Directories 2/2
Optional directories
submodules Project submodules
utils (or tools, or script) Scripts and utilities related to the project
README.md
• README template:
- Embedded Artistry README Template
- Your Project is Great, So Let’s Make Your README Great Too
LICENSE
8/80
File extensions
Common conventions:
• .h .c .cc Google
• .hh .cc
• .hpp .cpp
• .hxx .cxx 9/80
Common Rules
The file should have the same name of the class/namespace that they
implement
• class MyClass
my class.hpp (MyClass.hpp)
my class.i.hpp (MyClass.i.hpp)
my class.cpp (MyClass.cpp)
• namespace my np
my np.hpp (MyNP.hpp)
my np.i.hpp (MyNP.i.hpp)
my np.cpp (MyNP.cpp)
10/80
“Common” Project Organization Notes
• The main file (if present) can be placed in src/ and called main.cpp
• Code tests, unit and functional (see C++ Ecosystem I slides), can be
placed in test/ , or unit tests can appear in the same directory of the
component under test with the same filename and include .test suffix,
e.g. my file.test.cpp
11/80
“Common” Project Organization Example
<project name>
include/ README.md
public header.hpp CMakeLists.txt
src/ Doxyfile
private header.hpp LICENSE
templ class.hpp build/ (empty)
templ class.i.hpp bin/ (empty)
(template/inline functions) doc/ (empty)
templ class.cpp test/
(specialization) my test.hpp
subdir/ my test.cpp
my file.cpp ...
12/80
“Common” Project Organization - Improvements
13/80
Alternative - “Canonical” Project Organization 1/2
• Header and source files (or module interface and implementation files) are next
to each other (no include/ and src/ split)
• Headers are included with <> and contain the project directory prefix, for
example, <hello/hello.hpp> (no need of "" syntax)
• Header and source file extensions are .hpp / .cpp ( .mpp for module
interfaces). No special characters other than and - in file names with . only
used for extensions
• A source file that implements a module’s unit tests should be placed next to that
module’s files and be called with the module’s name plus the .test second-level
extension
16/80
Coding Styles and
Conventions
Overview
17/80
Overview
18/80
Overview
19/80
Code Quality
20/80
Bad Code
21/80
abstrusegoose.com/432
Coding Styles 1/3
22/80
Coding Styles 2/3
※ → Important!
Highlight potential code issues such as bugs, inefficiency, and can compromise
readability. Should not be ignored
∗ → Useful
It is not fundamental but it emphasizes good practices and can help to prevent
bugs. Should be followed if possible
• → Minor / Obvious
Style choice or not very common issue
25/80
#include
#include 1/5
26/80
#include 2/5
• space
• space
27/80
#include 3/5
28/80
#include 4/5
30/80
Macro and
Preprocessing
Macro and Preprocessing 1/4
※ Use a prefix for all macros related to the project MYPROJECT MACRO
Google, Unreal
31/80
Macro and Preprocessing 2/4
32/80
Macro and Preprocessing - Style 3/4
• The hash mark that starts a preprocessor directive should always be at the
beginning of the line Google
# if defined(MACRO)
# define MACRO2
# endif
33/80
Macro and Preprocessing - Style 4/4
34/80
namespace
Namespace 1/3
35/80
Namespace- Anonymous 2/3
void f() {}
37/80
Variables
Variable 1/3
38/80
Variable - Arithmetic Types 2/3
∗ Use true , false for boolean variables instead numeric values 0, 1 WebKit
39/80
Variables - Arithmetic Types 3/3
Style:
40/80
Functions
Functions 1/3
∗ Split up large functions into logical sub-functions for improving readability and
compile time Unreal, Google, Core
• Use inline only for small functions (e.g. < 10 lines) Google, Hic
※ Never return pointers for new objects. Use std::unique ptr instead
Chromium, Core
int* f() { return new int[10]; } // wrong!!
std::unique_ptr<int> f() { return new int[10]; } // correct
41/80
Functions - Parameters 2/3
※ Prefer pass by-reference instead by-value except for raw arrays and built-in
types WebKit
• All parameters should be aligned if they do not fit in a single line (especially in the
declaration) Google
void f(int a,
const int* b);
• Parameter names should be the same for declaration and definition Clang-Tidy
• Do not use inline when declaring a function (only in the definition) LLVM
• Do not separate declaration and definition for template and inline functions
Google
43/80
Structs and Classes
Structs and Classes 1/3
∗ Use a struct only for passive objects that carry data; everything else is a
class Google
∗ Do not define implicit conversions. Use the explicit keyword for conversion
operators and constructors Google, Core
45/80
Structs and Classes 3/3
• Use braced initializer lists for aggregate types A{1, 2} LLVM, Google
• Do not use braced initializer lists {} for constructors (at least for containers, e.g.
std::vector ). It can be confused with std::initializer list LLVM
46/80
Inheritance 1/2
48/80
Structs and Classes - Style 1/3
class B {
public:
B();
void public_function();
protected:
int _a; // in general, it is not public in derived classes
void _protected_function(); // "protected_function()" is not wrong
// it may be public in derived classes
private:
int _x;
float _y;
void _private_function();
50/80
};
Structs and Classes - Style 3/3
51/80
Control Flow
Control Flow 1/6
• Do not use default labels in fully covered switches over enumerations LLVM
52/80
Control Flow - if/else 2/6
if (condition) { // wrong!!
< code1 >
return;
}
else // <-- redundant
< code2 >
//---------------------------
if (condition) { // Corret
< code1 >
return;
}
< code2 >
if (condition) // wrong!!
return true;
else
return false;
//-------------------------
return condition; // Corret 53/80
Control Flow - Loops 3/6
• Use early exits ( continue , break , return ) to simplify the code LLVM
for (<condition1>) { // wrong!!
if (<condition2>)
...
}
//-----------------------------
for (<condition1>) { // Correct
if (!<condition2>)
continue;
...
}
※ Prefer (ptr == nullptr) and x > 0 over (nullptr == ptr) and 0 < x
Chromium
Google, WebKit
∗ Multi-lines statements and complex conditions require curly braces Google
if (c1 && ... &&
c2 && ...) { // correct
<statement>
}
• Curly braces are not required for single-line statements (but allowed)
( for, while, if ) Google, WebKit
if (c1) { // not mandatory
<statement>
} 57/80
Modern C++
Features
Modern C++ Features 1/4
∗ Do not define implicit conversions. Use the explicit keyword for conversion
operators and constructors Google, µOS
58/80
Modern C++ Features - C++11/14/17 2/4
※ Use auto to avoid type names that are noisy, obvious, or unimportant
auto array = new int[10];
auto var = static cast<int>(var); LLVM, Google
lambdas, iterators, template expressions Unreal (only)
62/80
Maintainability 2/3
※ Do not use reinterpret cast or union for type punning Core, Hic
∗ Prefer core-language features over library facilities, e.g. char vs. std::byte
64/80
Prefer core-language features over library facilities
Naming
Naming Conventions for Variables 1/2
※ Use full words, except in the rare case where an abbreviation would be more
canonical and easier to understand, e.g. tmp WebKit
∗ Avoid short and very long names. Remember that the average word length in
English is 4.8
∗ The length of a variable should be proportional to the size of the scope that
contains it. For example, i is fine within a loop scope.
65/80
Naming Conventions for Variables 2/2
66/80
Naming Conventions for Functions
∗ Functions that return boolean values should start with boolean verbs, like
is, has, should, does µOS
• Do not use get for observer methods ( const ) without parameters, e.g.
size() WebKit
67/80
Style Conventions
Camel style Uppercase first word letter (sometimes called Pascal style or Capital case)
(less readable, shorter names)
CamelStyle
Snake style Lower case words separated by single underscore (good readability, longer
names)
snake_style
Macro style Upper case words separated by single underscore (sometimes called
Screaming style) (best readability, longer names)
MACRO_STYLE
68/80
Entity Names 1/2
69/80
Entity Names 2/2
Personal Comment: Macro style needs to be used only for macros to avoid subtle bugs. I adopt
snake style for almost everything as it has the best readability. On the other hand, I don’t want to
confuse typenames and variables, so I use camel style for the former ones. Finally, I also use camel
style for compile-time constants as they are very relevant in my work and I need to identify what is
evaluated at compile-time easily
71/80
Readability and
Formatting
Basics
※ Limit line length (width) to be at most 80 characters long (or 100, or 120) →
help code view on a terminal LLVM, Google, Mozilla, µOS
Personal Comment: I was tempted several times to use a line length > 80 to reduce the
number of lines, and therefore improve the readability. Many of my colleagues use split-screens or
even the notebook during travels. A small line length is a good compromise for everyone.
72/80
• Is the 80 character limit still relevant in times of widescreen monitors?
Spacing 1/2
73/80
Spacing 2/2
Personal Comment: C++ is a very verbose language. ”Same line” convention helps to keep the
code more compact, improving the readability
75/80
Formatting 2/2
76/80
Other Issues
∗ Use the same line ending (e.g. '\n' ) for all files Mozilla, Chromium
• Never put trailing white space or tabs at the end of a line Google, Mozilla
77/80
* Trojan Source attack for introducing invisible vulnerabilities
Code
Documentation
Code Documentation 1/3
• Document each entity (functions, classes, namespaces, definitions, etc.) and only
in the declarations, e.g. header files
78/80
Code Documentation 2/3
• Use anchors for indicating special issues: TODO , FIXME , BUG , etc.
WebKit, Chromium
79/80
Code Documentation 3/3