Coding Styleguide » History » Version 2
quintus, 03/21/2020 10:00 AM
Add ToC
1 | 1 | quintus | # Coding Styleguide |
---|---|---|---|
2 | |||
3 | 2 | quintus | {{toc}} |
4 | |||
5 | 1 | quintus | Those who have worked on the TSC project will remember the dreaded discussion about coding style. This project will avoid the trap by using a consistent coding style right from the start. It is outlined in this document. |
6 | |||
7 | The game's source code is formatted according to the [1TBS](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)) style, which is a variant of K&R, with slight adjustments. Details are documented below. |
||
8 | |||
9 | In general, try to keep your code readable. Specifically, it is often useful to leave empty lines to separate logically grouped statements from one another. |
||
10 | 2 | quintus | |
11 | 1 | quintus | |
12 | ## Indentation, line length |
||
13 | |||
14 | Source code is indented with 4 spaces, tabs are not used. Lines should be broken around 80 characters, and the resulting continuation lines should be indented so that it makes sense to look at. Example: |
||
15 | |||
16 | ~~~~~ c++ |
||
17 | if (somecondition) { |
||
18 | thisIsAVeryLongFunctionName(this_is_a_parameter, |
||
19 | this_is_another_parameter, |
||
20 | third_parameter); |
||
21 | } |
||
22 | ~~~~~ |
||
23 | |||
24 | ## Commentary |
||
25 | |||
26 | Semantically, comments should normally reflect why code is written the way it is. Normally it is not required to explain what code does, unless it is an exceptionally complex part. Syntactically, use `//` for one and two lines of comments. Starting with the third line, comments should use the bock syntax `/* ... */`. In the block syntax, align each star with the one on the preceeding line. Terminate the comment block on the last line of the comment. |
||
27 | |||
28 | ~~~~~ c++ |
||
29 | // Careful: this is used in foobar() as well |
||
30 | |||
31 | /* This code is designed to specifically fit the purpose of an example. |
||
32 | * It was not at all easy to come up with all this text, but for the |
||
33 | * sake of an example, it was required to do so. */ |
||
34 | ~~~~~ |
||
35 | |||
36 | ### Documentation comments |
||
37 | |||
38 | Where Doxygen is used to generate documentation, use Doxygen's `///` markers for short and the `/**` markers for long documentation. Other than that, the above advice applies. |
||
39 | |||
40 | ## Case of identifiers |
||
41 | |||
42 | * Macros are ALL_IN_CAPS. |
||
43 | * Structure and class identifiers use CamelCase. |
||
44 | * Member function identifiers are CamelCase as well. |
||
45 | * Member variables are snake_case. This includes static member variables, even if they are constant. |
||
46 | * Local variables use snake_case. |
||
47 | |||
48 | ## Abbreviated Hungarian Notation |
||
49 | |||
50 | Identifiers of variables and constants begin with a short sequence of characters that encodes some important information about the variable in question. This is called [Hungarian Notation](https://en.wikipedia.org/wiki/Hungarian_notation), but in full, it is cumbersome to read and leads to long identifier names. The following prefix characters have been chosen with respect to two goals: Make variable scope immediately visible, and warn of "unusual" types. |
||
51 | |||
52 | | Prefix | Meaning | |
||
53 | |--------+------------------------------------------------------------------| |
||
54 | | | No prefix: Local variable | |
||
55 | | m | Member variable | |
||
56 | | s | File-local variable | |
||
57 | | g | Global variable | |
||
58 | | p | Variable holds a pointer (both raw and managed pointers) | |
||
59 | | a | Variable holds a raw array (not: vector or other C++ containers) | |
||
60 | |||
61 | The scope prefix comes before the type prefix. Thus, `mp_foo` is a member variable holding a pointer, and `ga_argv` is a global variable holding a raw C array. |
||
62 | |||
63 | ## Compound Statements |
||
64 | |||
65 | The opening brace resides on the same line as the statement it applies to, regardless of whether this is a function, a control flow statement, or a class or enum declaration. The closing brace has a line on its own to ensure it is easily spottable where a block ends. |
||
66 | |||
67 | ~~~~~~~~~~~ c++ |
||
68 | class Foo { |
||
69 | }; |
||
70 | |||
71 | if (condition) { |
||
72 | // ... |
||
73 | } |
||
74 | |||
75 | while (condition) { |
||
76 | // ... |
||
77 | } |
||
78 | |||
79 | void main() { |
||
80 | // ... |
||
81 | } |
||
82 | ~~~~~~~~~~~ |
||
83 | |||
84 | The rare case of a terminal `while` has the `while` after the closing brace on the same line. |
||
85 | |||
86 | ~~~~~~ c++ |
||
87 | { |
||
88 | // ... |
||
89 | } while (condition) |
||
90 | ~~~~~~~ |
||
91 | |||
92 | ## Brace Cuddling |
||
93 | |||
94 | In an if/elsif/else statement, braces are cuddled to keep code compact. |
||
95 | |||
96 | ~~~~~~~~~~ c++ |
||
97 | if (condition1) { |
||
98 | // ... |
||
99 | } else if (condition2) { |
||
100 | // ... |
||
101 | } else { |
||
102 | // ... |
||
103 | } |
||
104 | ~~~~~~~~~~~ |
||
105 | |||
106 | ## Braces around short statements |
||
107 | |||
108 | It is okay to leave breaces out for one-line `if`, `while`, etc. statements. If the surrounding code grows sufficiently complex so that the entirety of such a statement cannot be determined with a single look (e.g. long `else` conditional), use braces even in those parts where the syntax allows to leave the braces out. It helps clarity in that case. |
||
109 | |||
110 | ~~~~~~~~~ c++ |
||
111 | // Short: good |
||
112 | if (condition) |
||
113 | doit(); |
||
114 | |||
115 | // Longer, but still okay |
||
116 | if (condition1) |
||
117 | doit(); |
||
118 | else |
||
119 | doother(); |
||
120 | |||
121 | // This is too complex, use braces everywhere to clarify |
||
122 | if (condition1) { |
||
123 | doit(); |
||
124 | } else { |
||
125 | doother1(); |
||
126 | if (condition2) { |
||
127 | something(); |
||
128 | } |
||
129 | else { |
||
130 | andmore(); |
||
131 | } |
||
132 | } |
||
133 | ~~~~~~~~~ |
||
134 | |||
135 | ## Parantheses and spacing |
||
136 | |||
137 | Between a keyword and the opening paranthesis is exactly one space. Between the closing paranthesis and the opening curly brace is exactly one space as well. *There is no space between a function name and the opening paranthesis of its argument list*, neither in declaration nor in calling of a function. |
||
138 | |||
139 | ~~~~~~~~ c++ |
||
140 | void foo() { // No space between function name and (, but one space between ) and { |
||
141 | if (condition) { // One space between keyword if and (, and one space between ) and { |
||
142 | // ... |
||
143 | } |
||
144 | } |
||
145 | ~~~~~~~~ |