Mercurial > malikania
annotate STYLE_CPP.md @ 139:b80d37e71b87
Client: rework dispatching between client and window, closes #711
The window backend is able to produce user events but they need to be dispatched
into the client, the state and the window.
This change makes client owner of window and dispatches events from client to
the window and the future state mechanism.
Remove the client network code temporarily to rework in the dispatcher later.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 27 Sep 2017 20:34:59 +0200 |
parents | 835c8ee3f9e5 |
children |
rev | line source |
---|---|
118 | 1 Malikania Engine C++ CODING STYLE |
2 ================================= | |
3 | |
4 Style | |
5 ----- | |
6 | |
7 - Always use 4 spaces as indentation, | |
8 - Use UTF-8 charset, | |
9 - Use Unix line endings, | |
10 - Do not exceed 120 characters for lines of code, | |
11 - Do not exceed 80 characters for comments, | |
12 - Never write two blank consecutives blank lines, | |
13 - Do not use bad words. | |
14 | |
15 ### Braces | |
16 | |
17 Braces follow the K&R style, they are never placed on their own lines except for | |
18 function definitions. | |
19 | |
20 Do not put braces for single line statements except for clarity. | |
21 | |
22 if (condition) { | |
23 apply(); | |
24 add(); | |
25 } else | |
26 ok(); | |
27 | |
28 if (condition) | |
29 validate(); | |
30 | |
31 if (foo) { | |
32 state = long + conditional + that + requires + several + lines + | |
33 to + complete; | |
34 } | |
35 | |
36 Functions require braces on their own lines. | |
37 | |
38 void function() | |
39 { | |
40 } | |
41 | |
42 And a lambda has its braces on the same lines too: | |
43 | |
44 sort([&] (auto&) { | |
45 return true; | |
46 }); | |
47 | |
48 ### Spaces | |
49 | |
50 Each reserved keyword (e.g. `if`, `for`, `while`) requires a single space before | |
51 its argument. | |
52 | |
53 Normal function calls do not require it. | |
54 | |
55 if (foo) | |
56 destroy(sizeof (int)); | |
57 | |
58 ### References and pointers | |
59 | |
60 References and pointers are always next to the type name and not the variable. | |
61 | |
62 T& get(const std::string& name); | |
63 | |
64 int* p = &x; | |
65 | |
66 ### Naming | |
67 | |
68 - English names, | |
69 - Member variables have trailing underscore (e.g foo\_bar\_), | |
70 - No hungarian notation. | |
71 | |
72 Everything is in `underscore_case` except template parameters and macros. | |
73 | |
74 #if defined(FOO) | |
75 # include <foo.hpp> | |
76 #endif | |
77 | |
78 namespace baz { | |
79 | |
80 class object { | |
81 private: | |
82 std::string name_; | |
83 | |
84 public: | |
85 inline const std::string& name() const noexcept | |
86 { | |
87 return name_; | |
88 } | |
89 }; | |
90 | |
91 template <typename Archive> | |
92 void open(const Archive& ar) | |
93 { | |
94 bool is_valid = false; | |
95 } | |
96 | |
97 } // !baz | |
98 | |
99 ### Header guards | |
100 | |
101 Do not use `#pragma once`. | |
102 | |
103 Header guards are usually named **PROJECT_COMPONENT_FILENAME_HPP**. | |
104 | |
105 #ifndef FOO_COMMON_UTIL_HPP | |
106 #define FOO_COMMON_UTIL_HPP | |
107 | |
108 #endif // !FOO_COMMON_UTIL_HPP | |
109 | |
110 ### Enums | |
111 | |
112 Enumerations constants are always defined in separate line to allow commenting | |
113 them as doxygen. | |
114 | |
115 Enum class are encouraged. | |
116 | |
117 enum class color { | |
118 blue, | |
119 red, | |
120 green | |
121 }; | |
122 | |
123 ### Files | |
124 | |
125 - Use `.cpp` and `.hpp` as file extensions, | |
126 - Filenames are all lowercase. | |
127 | |
128 ### Comments | |
129 | |
130 Avoid useless comments in source files. Comment complex things or why it is done | |
131 like this. However any public function in the .hpp **must** be documented as | |
132 doxygen without exception. | |
133 | |
134 /* | |
135 * Multi line comments look like | |
136 * this. | |
137 */ | |
138 | |
139 // Short comment | |
140 | |
141 Use `#if 0` to comment blocks of code. | |
142 | |
143 #if 0 | |
144 broken_stuff(); | |
145 #endif | |
146 | |
147 ### Includes | |
148 | |
149 The includes should always come in the following order. | |
150 | |
151 1. C++ headers | |
152 2. C header | |
153 3. Third party libraries | |
154 4. Application headers in "" | |
155 | |
156 #include <cstring> | |
157 #include <cerrno> | |
158 | |
159 #include <sys/stat.h> | |
160 | |
161 #include <libircclient.h> | |
162 | |
163 #include "foo.h" | |
164 | |
165 **Note**: always use C++ headers for C equivalent, stdio.h -> cstdio, etc. | |
166 | |
167 ### Commit messages | |
168 | |
169 Commit messages are written using the following syntax: | |
170 | |
171 Topic: short message less than 80 characters | |
172 | |
173 Optional additional description if needed. | |
174 | |
175 Replace `Topic` with one of the following: | |
176 | |
177 - **Client**: client library and executable, | |
178 - **CMake**: for the build system, | |
179 - **Common**: common library, | |
180 - **Docs**: for the documentation, | |
181 - **Misc**: for miscellaneous files, | |
182 - **Server**: server library and executable, | |
183 - **Tests**: for the unit tests. | |
184 | |
185 Programming | |
186 ----------- | |
187 | |
188 ### C language | |
189 | |
190 Do not use old C stuff like `void *`, `srand/rand`, `printf` or anything that | |
191 can be rewritten in modern C++. | |
192 | |
193 ### RTTI | |
194 | |
195 Usage of `dynamic_cast` and `typeid` are completely disallowed in any shape of | |
196 form. | |
197 | |
198 ### Arguments | |
199 | |
200 It is recommended to pass parameters by value or const reference. Usage of | |
201 non-const reference as output parameter is **discouraged** and should be avoided | |
202 in many case because it does not allow chaining of expressions like: | |
203 | |
204 std::cout << reverse(upper(clean(" hello world! "))) << std::endl; | |
205 | |
206 If your function is designed to return a modified value passed as argument, it | |
207 is better to take it by value and modify it directly. | |
208 | |
209 std::string clean(std::string input) | |
210 { | |
211 if (!input.empty() && input.back() == '\r') | |
212 input.pop_back(); | |
213 | |
214 return input; | |
215 } | |
216 | |
217 Never pass primitive types as const value. | |
218 | |
219 ### Assertions | |
220 | |
221 Use the `assert` macro from the cassert header file to verify programming | |
222 errors. | |
223 | |
224 For example, you may use `assert` to verify that the developer access the data | |
225 between the bounds of an array: | |
226 | |
227 T& operator[](unsigned index) | |
228 { | |
229 assert(index < length_); | |
230 | |
231 return data_[index]; | |
232 } | |
233 | |
234 The `assert` macro is not meant to check that a function succeeded, this code | |
235 must not be written that way: | |
236 | |
237 assert(listen(10)); | |
238 | |
239 ### Exceptions | |
240 | |
241 You must use exceptions to indicate an error that was unexpected such as: | |
242 | |
243 - Failing to open a file, | |
244 - I/O unexpected errors, | |
245 - Parsing errors, | |
246 - User errors. | |
247 | |
248 You may use the C++ standard exceptions defined in the stdexcept header but if | |
249 you need to carry more data within your exception, you should derive from | |
250 `std::exception`. | |
251 | |
252 ### Error code | |
253 | |
254 You should not use error codes to indicate errors, instead use exceptions. | |
255 Error codes are allowed in Boost.Asio though. | |
256 | |
257 ### Free functions | |
258 | |
259 Basic utility functions should be defined in a namespace as a free function not | |
260 as a static member function, we're doing C++ not Java. | |
261 | |
262 Example: | |
263 | |
264 namespace util { | |
265 | |
266 std::string clean(std::string input); | |
267 | |
268 } // !util | |
269 | |
270 ### Variables initialization | |
271 | |
272 Use parentheses to initialize non primitive types: | |
273 | |
274 throw std::runtime_error("foo"); | |
275 | |
276 my_class obj("bar"); | |
277 | |
278 Use brace initialization when you want to use an initializer list, type | |
279 elision: | |
280 | |
281 std::vector<int> v{1, 2, 3}; | |
282 | |
283 foo({1, 2}); // type deduced | |
284 | |
285 return { "true", false }; // std::pair returned | |
286 | |
287 Use the assignment for primitive types: | |
288 | |
289 int x = 123; | |
290 bool is_valid = true; | |
291 | |
292 ### Classes | |
293 | |
294 Classes are usually defined in the following order: | |
295 | |
296 1. Public inner types (enums, classes), | |
297 2. Protected/private members | |
298 3. Public functions | |
299 | |
300 class foo { | |
301 public: | |
302 enum class type { | |
303 a, | |
304 b | |
305 }; | |
306 | |
307 private: | |
308 int member_{0}; | |
309 | |
310 public: | |
311 void some_function(); | |
312 }; | |
313 | |
314 ### Structs | |
315 | |
316 Do not use C structs unless you have very good reason to do so. If you want to | |
317 pack some data, just use `class` and make all fields public. | |
318 | |
319 class point { | |
320 public: | |
321 int x{0}; | |
322 int y{0}; | |
323 }; | |
324 | |
325 ### Return | |
326 | |
327 The preferred style is to return early in case of errors. That makes the code | |
328 more linear and not highly indented. | |
329 | |
330 This code is preferred: | |
331 | |
332 if (a_condition_is_not_valid) | |
333 return nullptr; | |
334 if (an_other_condition) | |
335 return nullptr; | |
336 | |
337 auto x = std::make_shared<object>(); | |
338 | |
339 x->start(); | |
340 x->save(); | |
341 | |
342 return x; | |
343 | |
344 Additional rules: | |
345 | |
346 - Do never put parentheses between the returned value, | |
347 - Do not put a else branch after a return. | |
348 | |
349 ### Auto | |
350 | |
351 We encorage usage of `auto`, it reduces code maintainance as you don't need to | |
352 change your code when your rename types. | |
353 | |
136
835c8ee3f9e5
Docs: use ``` as fenced code blocks
David Demelier <markand@malikania.fr>
parents:
118
diff
changeset
|
354 ```cpp |
118 | 355 auto it = std::find_if(v.begin(), v.end(), [&] (const auto& obj) { |
356 return obj.key() == "foo"; | |
357 }); | |
358 | |
359 for (const auto& pair : a_map) | |
360 std::cout << pair.first << " = " << pair.second << std::endl; | |
136
835c8ee3f9e5
Docs: use ``` as fenced code blocks
David Demelier <markand@malikania.fr>
parents:
118
diff
changeset
|
361 ``` |
118 | 362 |
363 But do not use `auto` to write code like in python, this is not acceptable: | |
364 | |
136
835c8ee3f9e5
Docs: use ``` as fenced code blocks
David Demelier <markand@malikania.fr>
parents:
118
diff
changeset
|
365 ```cpp |
118 | 366 auto o = my_object("foo"); |
136
835c8ee3f9e5
Docs: use ``` as fenced code blocks
David Demelier <markand@malikania.fr>
parents:
118
diff
changeset
|
367 ``` |