docs: Add supported versions and fix-backport policy
[lttng-tools.git] / CodingStyle.md
CommitLineData
d17cc1f3
JG
1# Coding style guide
2
3It is said that there is no accounting for taste. However, when it comes to code, we are of the opinion that a _consistent_ style makes it easier to collaborate in a shared code base.
4
5Style guidelines are bound to be controversial. Some conventions laid out in this guide have objective merit. However, most boil down to personal preferences of the original authors.
6
7As such, this guide attempts to lay out the conventions used in the project so that new contributors can easily conform to them and minimize time lost during code review.
8
9Contributions are expected to adhere to these guidelines.
10
21fe6b71
KS
11## C++
12
13### Migration from C
d17cc1f3
JG
14
15As the LTTng-tools project aims at supporting a broad range of compilers -- currently starting from GCC 4.8 and Clang 3.3 -- its build system is configured to use the C++11 standard.
16
17LTTng-tools has historically been developped in C99 with liberal uses of GNU extensions. Since the release of LTTng 2.13, it has started a migration to C++.
18
19In order to ease the transition, it underwent an initial migration phase which had a limited scope: build all existing C code as C++11.
20
21As such, most of the project's code does not qualify as idiomatic C++ code. This migration is ongoing and expected to span across multiple release cycles.
22
23However, new contributions are expected to conform the C++ style described in this guide. Some exceptions are allowed for small fixes which have to be back-ported to stable branches.
24
21fe6b71 25### Automated formatting
d17cc1f3
JG
26
27All the project's C++ files follow the [clang-format](https://clang.llvm.org/docs/ClangFormat.html) [style](https://clang.llvm.org/docs/ClangFormatStyleOptions.html) of the `.clang-format` file for whitespaces, indentation, and line breaks.
28
29You _must_ format your changes with clang-format before you contribute a patch.
30
31Note that clang-format 14 is required to use the project's `.clang-format` file.
32
33Most text editors allow you to format a sub-section of a source file using clang-format to ensure it adheres to the project's style.
34
4f9b5c65 35If you are submitting a change to existing source files, _do not run clang-format on the whole file_ as this may introduce more changes than you intended and _will_ cause your changes to be rejected.
d17cc1f3 36
21fe6b71 37### Tabs VS Spaces
d17cc1f3
JG
38
39While our founding mothers and fathers eschewed any consideration for non-English languages when designing the ASCII character encoding they, in a rare moment of technical decadence, decided to dedicate a character to the sole purpose of expressing tabulations.
40
41This project makes use of this character to express indentations in its source files.
42
43Note that while tab characters are used for semantic indentation purposes, spaces are perfectly fine to use for _visual_ alignment (e.g. ascii diagrams).
44
21fe6b71 45### Single line control flow statements
d17cc1f3
JG
46
47Single line control flow statements (if/for/while) are required to use braces.
48
49```cpp
50/* bad */
51if (my_thingy)
52 do_the_thing();
53
54/* good */
55if (my_thingy) {
56 do_the_thing();
57}
58```
59
21fe6b71 60### Naming
d17cc1f3
JG
61
62- Use snake case (e.g. `a_snake_case_name`) except for template parameters, which use camel case and end with `Type` (e.g. `ACamelCaseNameType`).
63
64- Prefer using explicit and verbose names. For instance:
65 - When naming a variable that indicates a count of bananas, prefer `banana_count` to `bananas`, `count`, or `n`.
66 - When naming a function or method that validates and initializes a user profile, prefer `validate_and_initialize_user_profile()` to `set_up()`, `viup()`, `do_user_profile()`, `init()`.
67
68- Avoid the use of overly generic terms like `data`, `ptr`, and `buffer`.
69
70- Use an underscore prefix for private or protected methods and members, and member type names: `_try_connect()`, `class _user_count`, `int _version`.
71
72- Name trivial setters and getters like the property name, without a verb (e.g. `set` and `get` prefixes).
73
74 ```cpp
75 /* good, gets the session's name. */
76 session.name();
77 /* good, sets the session's name. */
78 session.name("my new name");
79
80 /* good, non-trivial accessor */
81 session.add_channel(my_channel);
82 ```
83
84- Use the `is` or `has` prefixes to name boolean properties or functions which return a `bool` type.
85
86- Do not make-up abbreviations to shorten names. Term of art abbreviations are, however, acceptable. For example: `mpeg`, `ctf`, `cfg`, `init` are accepted. A notable exception to this rule applies to namespaces, see the "Use of namespaces/Aliases" section.
87
21fe6b71 88### Comments
d17cc1f3
JG
89
90In general, comments should focus on _why_ something is done and document the assumptions the code was built upon. They should not repeat what it does in plain english except if the code is particularily complex. Keep in mind that what may be obvious to you right now may not be obvious to reviewers... or your future self.
91
92Also, write comments in grammatically-sound English and avoid writing using telegraph style:
93
94```cpp
95/* Bad: init cfg */
96
97/* Bad: init cfg before reply */
98
99/* Good: The configuration must be initialized before replying since it initializes the user's credentials. */
100```
101
21fe6b71 102### Include guards
d17cc1f3
JG
103
104Header files must use include guards to prevent multiple inclusion issues. To avoid collisions, the name of include guards must be as specific as possible and include the name of the file.
105
106```cpp
107/* In file thingy-handler.hpp */
108
109#ifndef LTTNG_CONSUMERD_THINGY_HANDLER
110#define LTTNG_CONSUMERD_THINGY_HANDLER
111
112/* Some briliant code. */
113
114#endif /* LTTNG_CONSUMERD_THINGY_HANDLER */
115```
116
117
21fe6b71 118### Use of namespaces
d17cc1f3
JG
119
120Make liberal use of namespaces. Very little should be available in the `lttng`,
121let alone global, namespace.
122
123Moreover, prefer to use anonymous namespaces to the `static` keyword to restrict the visibility of a symbol to its translation unit.
124
21fe6b71 125#### Do not pollute the global namespace
d17cc1f3
JG
126
127Never use the `using` directive to import the contents of a namespace. If a namespace is used often in a file, define an alias.
128
21fe6b71 129#### Aliases
d17cc1f3
JG
130
131Within a translation unit, it is acceptable to abbreviate commonly-used namespace names to define an alias. For instance, the file containing the implementation of the `food::fruits::citrus::grapefruit` can use the `ffc` namespace alias for brievety.
132
133```cpp
134/* In file grapefruit.cpp */
135
136namespace ffc = food::fruits::citrus;
137
138ffc::grapefruit::grapefruit()
139{
140 // ...
141}
142```
143
21fe6b71 144### File layout example
d17cc1f3
JG
145
146```cpp
147/*
148 * Copyright (C) 20xx Robert Binette <bob@codebleu.qc.ca>
149 *
150 * SPDX-License-Identifier: GPL-2.0-only
151 *
152 */
153
154#ifndef LTTNG_THING_DOER_H
155#define LTTNG_THING_DOER_H
156
157/* Mind the order of inclusions, in alphabetical order per category. */
158
159/* Project-local headers. */
160#include "my-local-stuff.hpp"
161#include "utils.hpp"
162
163/* Project-wide headers. */
164#include <vendor/optional.hpp>
165
166/* System headers. */
167#include <functional>
168#include <string>
169#include
170
171namespace lttng {
172namespace sessiond {
173
174class things;
175
176using on_new_name_function = std::function<void(const std::string& name)>;
177
178class thing_doer : public lttng::sessiond::doer {
179public:
180 explicit thing_doer(const std::string& name);
181
c1d4a65a 182 void do() override final;
d17cc1f3
JG
183 const std::string& name() const;
184
185private:
186 unsigned int _count_things(std::vector) const noexcept;
187
188 const std::string _name;
189};
190
191} /* namespace sessiond */
192} /* namespace lttng */
193
194#endif /* LTTNG_THING_DOER_H */
195```
196
21fe6b71 197### Miscelaneous guidelines
d17cc1f3
JG
198
199In general, the project’s contributors make an effort to follow, for C++11 code:
200
201[The C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
202
203[Scott Meyers’s “Effective Modern C++”](https://www.oreilly.com/library/view/effective-modern-c/9781491908419/)
204
205Here are a couple of reminders:
206* When defining a class, put constructors as the first methods, whatever their access (public/protected/private), then the destructor, and then the rest.
207
208* Declare variables as close to where they are used as possible.
209
210* Use auto when possible.
211
212* Use const as much as possible, even for pointer (const char* const) and numeric values (const unsigned int) which never need to change.
213
214* Make methods const noexcept or const as much as possible.
215
216* Make constructors explicit unless you really need an implicit constructor (which is rare).
217
218* Use `std::unique_ptr` to manage memory when possible.
219 * However, use references (`*my_unique_ptr`) and raw pointers (`my_unique_ptr.get()`) when not transferring ownership.
220 * Only use `std::shared_ptr` when ownership is conceptually shared.
221
222* Use `nullptr`, not `NULL` nor `0`.
223
224* Return by value (rvalue) instead of by output parameter (non-const lvalue reference), even complex objects, unless you can prove that the performance is improved when returning by parameter.
225
226* For a function parameter or a return value of which the type needs to be a reference or pointer, use:
227 * **If the value is mandatory**, a reference.
228 * **If the value is optional**, a raw pointer.
229
230* Don't use `std::move()` when you already have an rvalue, which means:
231 * Don't write `return std::move(...);` as this can interfere with RVO (Return Value Optimization).
232 * Don't use `std::move()` with a function call (`std::move(func())`).
233
234* For each possible move/copy constructor or assignment operator, do one of:
235 * Write a custom one.
236 * Mark it as defaulted (`default`)
237 * Mark it as deleted (`delete`).
238
239* Use scoped enumerations (`enum class`).
240
241* Mark classes known to be final with the `final` keyword.
242
243* Use type aliases (`using`), not type definitions (`typedef`).
244
245* Use anonymous namespaces for local functions instead of `static`.
246
247* Return a structure with named members instead of a generic container such as `std::pair` or `std::tuple`.
248
249* When a class inherits a base class with virtual methods, use the `override` keyword to mark overridden virtual methods, and do not use the `virtual` keyword again (as the method is already known to be virtual).
250
251* Define overloaded operators only if their meaning is obvious, unsurprising, and consistent with the corresponding built-in operators.
252
253 For example, use `|` as a bitwise or logical-or, not as a shell-style pipe.
254
255* Use RAII wrappers when managing system resources or interacting with C libraries.
256
257 In other words, don't rely on ``goto``s and error labels to clean up as you would do in C.
258
259* Throw an exception when there's an unexpected, exceptional condition,
260 [including from a constructor](https://isocpp.org/wiki/faq/exceptions#ctors-can-throw), instead of returning a status code.
261
262 However, be mindful of the exception-safety of your users. For instance, `liblttng-ctl` exposes a C interface meaning that is must catch and handle all exceptions, most likely by returning a suitable error code.
263
264* Accept a by-value parameter and move it (when it's moveable) when you intend to copy it anyway. You can do this with most STL containers.
265
cd96f17f
KS
266## Python
267
268Python code should be formatted using [black](https://github.com/psf/black).
269
9e433ef8
KS
270## Shell (BASH)
271
272New scripts and modifications to existing scripts should pass linting
273with [Shellcheck](https://www.shellcheck.net/).
274
d17cc1f3
JG
275## C Style (historical)
276
277The coding style used for this project follows the the Linux kernel guide lines, except that brackets `{`, `}` should typically be used even for single-line if/else statements. Please refer to:
278
279- doc/kernel-CodingStyle.txt (copied from the Linux 3.4.4 tree).
280
281- Linux kernel scripts/checkpatch.pl for a script which verify the patch
282 coding style.
283
284For header files, please declare the following in this order:
285
2861) `#define`
287
288 - Default values should go in: src/common/defaults.h
289 - Macros used across the project: src/common/macros.h
290
2912) Variables
292
293 - No _static_ in a header file! This is madness.
294 - Use _extern_ if the global variable is set else where.
295
2963) Function prototype
297
298Furthermore, respect the name spacing of files for each non-static symbol visiable outside the scope of the C file. For instance, for the utils.c file in libcommon, every call should be prefixed by "utils_*".
299
300### Error handling
301
302In legacy C-style code, we ask to use one single return point in a function. For that, we uses the "goto" statement for the error handling creating one single point for error handling and return code. See the following example:
303
304```c
305int some_function(...)
306{
307 int ret;
308 [...]
309
310 if (ret != 0) {
311 goto error;
312 }
313
314 [...]
315error:
316 return ret;
317}
318```
This page took 0.040642 seconds and 4 git commands to generate.