Merge pull request #11515 from blckmn/release_artifacts
[betaflight.git] / docs / development / CodingStyle.md
blobbc51b8c7740cd281cbc0791748a80a20c1466215
1 # General
3 This document overrides the original Baseflight style that was referenced before.
4 This document has taken inspiration from that style, from Eclipse defaults and from Linux, as well as from some Cleanflight and Betaflight developers and existing code.
6 There are not so many changes from the old style, if you managed to find it.
8 # Formatting style
10 ## Indentation
12 [1TBS](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)) (based K&R) indent style with 4 space indent, NO hard tabs (all tabs replaced by spaces).
14 ## Tool support
16 Any of these tools can get you pretty close:
18 Eclipse built in "K&R" style, after changing the indent to 4 spaces and change Braces after function declarations to Next line.
19 ```
20 astyle --style=kr --indent=spaces=4 --min-conditional-indent=0 --max-instatement-indent=80 --pad-header --pad-oper --align-pointer=name --align-reference=name --max-code-length=120 --convert-tabs --preserve-date --suffix=none --mode=c
21 ```
22 ```
23 indent -kr -i4 -nut
24 ```
25 (the options for these commands can be tuned more to comply even better)
27 Note: These tools are not authorative.
28 Sometimes, for example, you may want other columns and line breaks so it looks like a matrix.
30 Note2: The Astyle settings have been tested and will produce a nice result. Many files will be changed, mostly to the better but maybe not always, so use with care. 
32 ## Curly Braces
33 ### Functions
34 Functions shall have the opening and closing braces at the beginning of the next line, and followed by a line break.
35 ```
36 int function(int x)
38     body of function
40 ```
41 ### Non-function statement blocks
43 #### Opening braces
44 All non-function statement blocks (i.e. `if`, ` switch`, `for`, as well as any others) shall have the opening brace last on the same line, with the following statement on the next line.
46 #### Closing braces
47 Closing braces shall be but on the line after the last statement in the block.
48 ```
49 if (x is true) {
50     we do y
51     ...
53 ```
55 ```
56 switch (action) {
57 case ADD:
58     return "add";
59 case REMOVE:
60     return "remove";
61 case CHANGE:
62     return "change";
63 default:
64     return NULL;
66 ```
68 If the closing brace is followed by an `else` or `else if` that shall be on the same line, again with the opening brace on the same line.
69 ```
70 if (x is true) {
71     we do y
72     ...
73 } else {
74     we do z
75     ...
77 ```
78 ###Braces are required
79 Omission of "unnecessary" braces in cases where an `if` or `else` block consists only of a single statement is not permissible in any case. These "single statement blocks" are future bugs waiting to happen when more statements are added without enclosing the block in braces.
81 ## Spaces
83 Use a space after (most) keywords.  The notable exceptions are sizeof, typeof, alignof, and __attribute__, which look somewhat like functions (and are usually used with parentheses).
84 So use a space after these keywords:
85 ```
86 if, switch, case, for, do, while
87 ```
88 but not with sizeof, typeof, alignof, or __attribute__.  E.g.,
89 ```
90 s = sizeof(struct file);
91 ```
92 When declaring pointer data or a function that returns a pointer type, the preferred use of '*' is adjacent to the data name or function name and not adjacent to the type name.  Examples:
93 ```
94 char *linux_banner;
95 memparse(char *ptr, char **retptr);
96 char *match_strdup(substring_t *s);
97 ```
98 Use one space around (on each side of) most binary and ternary operators, such as any of these:
99 ```
100 =  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
102 but no space after unary operators:
104 &  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
106 no space before the postfix increment & decrement unary operators:
108 ++  --
110 no space after the prefix increment & decrement unary operators:
112 ++  --
114 and no space around the '.' and "->" structure member operators.
116 '*' and '&', when used for pointer and reference, shall have no space between it and the following variable name.
118 # typedef
120 enums that do not have a count or some other form of terminator element shall have a comma after their last element:
123 typedef enum {
124     MSP_RESULT_ACK = 1,
125     MSP_RESULT_ERROR = -1,
126     MSP_RESULT_NO_REPLY = 0,
127     MSP_RESULT_CMD_UNKNOWN = -2,
128 } mspResult_e;
131 This ensures that, if more elements are added at a later stage, only the additional lines show up in the review, making it easier to review.
133 enums with a count should have that count declared as the last item in the enumeration list,
134 so that it is automatically maintained, e.g.:
136 typedef enum {
137     PID_CONTROLLER_MW23 = 0,
138     PID_CONTROLLER_MWREWRITE,
139     PID_CONTROLLER_LUX_FLOAT,
140     PID_COUNT
141 } pidControllerType_e;
143 It shall not be calculated afterwards, e.g. using PID\_CONTROLLER\_LUX\_FLOAT + 1;
145 typedef struct definitions should include the struct name, so that the type can be forward referenced, that is in:
147 typedef struct motorMixer_s {
148     float throttle;
150     float yaw;
151 } motorMixer_t;
153 the motorMixer\_s name is required.
155 # Variables
157 ## Naming
160 Generally, descriptive lowerCamelCase names are preferred for function names, variables, arguments, etc.
161 For configuration variables that are user accessible via CLI or similar, all\_lowercase with underscore is preferred.
163 Variable names should be nouns.
165 Simple temporary variables with a very small scope may be short where it aligns with common practice.
166 Such as "i" as a temporary counter in a `for` loop, like `for (int i = 0; i < 4; i++)`.
167 Using "temporaryCounter" in that case would not improve readability.
169 ## Declarations
171 Avoid global variables.
173 Variables should be declared at the top of the smallest scope where the variable is used.
174 Variable re-use should be avoided - use distinct variabes when their use is unrelated.
175 One blank line should follow the declaration(s).
177 Hint: Sometimes you can create a block, i.e. add curly braces, to reduce the scope further.
178 For example to limit variable scope to a single `case` branch.
180 Variables with limited use may be declared at the point of first use. It makes PR-review easier (but that point is lost if the variable is used everywhere anyway).
182 ## Initialisation
184 The pattern with "lazy initialisation" may be advantageous in the Configurator to speed up the start when the initialisation is "expensive" in some way.
185 In the FC, however, it’s always better to use some milliseconds extra before take-off than to use them while flying.
187 So don't use "lazy initialisation".
189 An explicit "init" function, is preferred.
191 ## Data types
193 Be aware of the data types you use and do not trust implicit type casting to be correct.
195 Angles are sometimes represented as degrees in a float. Sometimes as decidegrees in a uint8\_t.
196 You have been warned.
198 Avoid implicit double conversions and only use float-argument functions.
200 Check .map file to make sure no conversions sneak in, and use -Wdouble-promotion warning for the compiler
202 Instead of `sin()` and `cos()`, use `sin_approx()` and `cos_approx()` from common/math.h.
204 Float constants should be defined with "f" suffix, like 1.0f and 3.1415926f, otherwise double conversion might occur.
206 # Functions
208 ## Naming
210 Methods that return a boolean should be named as a question, and should not change any state. e.g. 'isOkToArm()'.
212 Methods should have verb or verb-phrase names, like deletePage or save. Tell the system to 'do' something 'with' something. e.g. deleteAllPages(pageList).
214 Non-static functions should be prefixed by their class. Eg baroUpdate and not updateCompass .
216 Groups of functions acting on an 'object' should share the same prefix, e.g.
218 float biQuadFilterApply(...);
219 void biQuadFilterInit(...);
220 boolean biQuadIsReady();
222 rather than
224 float applyBiQuadFilter(...);
225 void newBiQuadLpf(...);
226 boolean isBiQuadReady();
229 ## Parameter order
231 Data should move from right to left, as in `memcpy(void *dst, const void *src, size_t size)`.
232 This also mimics the assignment operator (e.g. dst = src;)
234 When a group of functions act on an 'object' then that object should be the first parameter for all the functions, e.g.:
236 float biQuadFilterApply(biquad_t *state, float sample);
237 void biQuadNewLpf(biquad_t *state, float filterCutFreq, uint32_t refreshRate);
239 rather than
241 float biQuadFilterApply(float sample, biquad_t *state);
242 void biQuadNewLpf(float filterCutFreq, biquad_t *state, uint32_t refreshRate);
245 ## Declarations
247 Functions not used outside their containing .c file should be declared static (or STATIC\_UNIT\_TESTED so they can be used in unit tests).
249 Non-static functions should have their declaration in a single .h file.
251 Don't make more than necessary visible for other modules, not even types. Pre-processor macros may be used to declare module internal things that must be shared with the modules test code but otherwise hidden.
253 In the .h file:
255 #ifdef MODULENAME_INTERNALS_
256 … declarations …
257 #endif
259 In the module .c file, and in the test file but nowhere else, put `#define MODULENAME_INTERNALS_` just before including the .h file.
261 Note: You can get the same effect by putting the internals in a separate .h file.
263 ## Implementation
265 Keep functions short and distinctive.
266 Think about unit test when you define your functions. Ideally you should implement the test cases before implementing the function.
268 Never put multiple statements on a single line.
269 Never put multiple assignments on a single line.
270 Never put multiple assignments in a single statement.
272 Defining constants using pre-processor macros is not preferred.
273 Const-correctness should be enforced.
274 This allows some errors to be picked up at compile time (for example getting the order of the parameters wrong in a call to memcpy).
276 A function should only read data from the HW once in each call, and preferably all at one place.
277 For example, if gyro angle or time is needed multiple times, read once and store in a local variable.
279 Use `for` loops (rather than `do` or `while` loops) for iteration.
281 The use of `continue` or `goto` should be avoided.
282 Same for multiple `return` from a function and multiple `break` inside a `case`.
283 In general, they reduce readability and maintainability.
284 In rare cases such constructs can be justified but only when you have considered and understood the alternatives and still have a strong reason.
286 In expressions, parentheses should only be used where they are required, i.e. where operator precedence will not evaluate in the right order, or where a compiler warning is triggered without parentheses. This brings all expressions into a canonical form, and avoids the problem of different developers having different ideas of what 'easy to read' expressions are.
288 One exception to this rule is the ternary conditional operator
291 pidStabilisationEnabled = (pidControllerState == PID_STABILISATION_ON) ? true : false
294 Here, the condition shall be enclosed in braces, to make the ternary operator easier to spot when reading left to right.
296 # Includes
298 All files must include their own dependencies and not rely on includes from the included files or that some other file was included first.
300 Do not include things you are not using.
302 `#pragma once` ([see wiki](https://en.wikipedia.org/wiki/Pragma_once)) is preferred over `#include guards` to avoid multiple includes.
305 # Other details
307 No trailing whitespace at the end of lines or at blank lines.
309 Stay within 120 columns, unless exceeding 120 columns significantly increases readability and does not hide information.
310 (Less is acceptable. More than 140 makes it difficult to read on Github so that shall never be exceeded.)
312 Take maximum possible advantage of compile time checking, so generally warnings should be as strict as possible.
314 Don't call or reference "upwards". That is don't call or use anything in a software layer that is above the current layer. The software layers are not that obvious in Betaflight, but we can certainly say that device drivers are the bottom layer and so should not call or use anything outside the device drivers.
316 Target specific code (e.g. #ifdef CC3D) is not permissible outside of the `src/main/target` directory.
318 `typedef void handlerFunc(void);` is easier to read than `typedef void (*handlerFuncPtr)(void);`.
320 Code should be spherical.
321 That is its surface area (public interfaces) relative to its functionality should be minimised.
322 Which is another way of saying that the public interfaces shall be easy to use,
323 do something essential and all implementation should be hidden and unimportant to the user
325 Code should work in theory as well as in practice.
326 It should be based on sound mathematical, physical or computer science principles rather than just heuristics.
327 This is important for test code too. Tests shall be based on such principles and real-world properties so they don't just test the current implementation as it happens to be.
329 Guidelines not tramlines: guidelines are not totally rigid - they can be broken when there is good reason.