forked from CelestiaProject/Celestia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
coding-standards.html
403 lines (371 loc) · 11.2 KB
/
coding-standards.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
<html>
<head><title>Celestia Coding Standards</title>
<style type="text/css">
<!--
* {
font-size: 12;
font-family: Tahoma, Arial, Helvetica, Sans-serif;
color: black;
}
.documenttitle {
font-size: 24;
font-weight: bold;
}
.sectiontitle {
font-size: 16;
font-weight: bold;
}
.subsectiontitle {
font-weight: bold;
}
.mailaddr {
font-size: 12;
font-style: italic;
}
.newsdate {
font-style: italic;
color: #909090
}
.newsheadline {
font-weight: bold;
color: #d09040;
}
A:link { color: #5050cc }
A:hover { color: #a0a0ff }
A:active { color: #ffffff }
A:visited { color: #4040bb }
PRE
{
background-color: #dddddd;
font-family: Courier;
}
BODY
{
background-color: white;
}
-->
</style>
</head>
<body>
<p>
<span class="documenttitle">Celestia Coding Standards</span><br>
I'm not religious about any particular indentation style or naming
conventions for code, but I do believe that it is very important that
whatever standards are chosen are used consistently throughout a project.
This document describes the coding style already in use throughout the
Celestia code base. As Celestia grows, there will undoubtedly be
clarifications, additions, and edits made to this document, and I encourage
suggestions. However, recommendations that require
reformatting or renaming huge chunks of the existing code will be ignored.
No stylistic convention is so inherently superior that it's worth all that
hassle.
</p>
<div>
<span class="sectiontitle">Files</span><br>
<p>
The names of Celestia source files and data files are always lower case.
Unix is a case-sensitive OS, but Windows is not; using strictly lower case
filenames reduces confusion. The extension .cpp should be used for all C++
sources files. A process is set up to run nightly and cull all .C, .c++,
and .cc files from the CVS tree.
</p>
<p>
You should "guard defines" around include files to prevent multiple
inclusion of headers. Take care to assure that the guard macros will
be unique. The scheme for naming them in Celestia is
_<subdirectory>_<filename>_H_ Here's an example:
<blockquote>
<pre style="code">
// This header file is star.h in the celengine subdirectory.
#ifndef _CELENGINE_STAR_H_
#define _CELENGINE_STAR_H_
class Star
{
...
};
#endif // _CELENGINE_STAR_H_
</pre>
</blockquote>
Since celengine is a library, it is important include the subdirectory in the
guard macro name in order to make macro name collisions less likely.
</pre>
</blockquote>
</p>
</div>
<br><br>
<div>
<span class="sectiontitle">Language</span><br>
Celestia is unrepentantly a C++ project. C++ has many language features
which replace unsafe or awkward constructions in C; use the C++ features
wherever possible (which should be everywhere except in some cases where
you need to call functions from external libraries.)
<p><span class="subsectiontitle">STL</span><br>
Celestia makes heavy use of the Standard Template Library. Resist the urge
to write your own dynamic array or tree classes--you can almost certainly
use STL's vector or map. Don't do this in a header:
<blockquote>
<pre style="code">
#include <string>
using namespace std;
extern string foo;
</pre>
</blockquote>
Instead, when referring to an STL class or function in a header,
prefix it with std. Implementation modules shouldn't be forced to import
the entire std namespace just because they include a particular header.
The right way:
<blockquote>
<pre style="code">
#include <string>
extern std::string foo;
</pre>
</blockquote>
</p>
<p><span class="subsectiontitle">Strings</span><br>
Use C++'s string class rather than C-style zero terminated strings. The
string class is safer, more convenient, and in many cases, more efficient
than C strings. You can always call string::c_str() for a pointer to a
zero terminated string to pass to external API functions that require one,
but it's important to keep in mind that c_str() does not allocate a new
string. Methods which are declared to accept C++ string parameters can
also accept C strings, because the string class's string(char*) constructor
is automatically applied.
<blockquote>
<pre style="code">
void foo(const string& s)
{
...
}
void bar()
{
string text("Test");
// This will work properly:
foo(text);
// . . . and so will this:
foo("Test");
}
</pre>
</blockquote>
<p><span class="subsectiontitle">Casts</span><br>
Type casting should be avoided as much as possible. However, it is still
occasionally necessary to use it, particularly when calling external API
functions. When you do have to cast, favor C++ style casts
(reinterpret_cast, static_cast, and const_cast) over C casts. While
they're a pain to type, they're much easier to notice when browsing the code
(since casts are the source of so many bugs, it's important that they're
as obvious as possible.)<br><br>
<blockquote>
<pre style="code">
UINT CALLBACK DialogProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
HWND hwnd;
// Bad cast
hwnd = (HWND) lParam;
// Better cast
hwnd = reinterpret_cast<HWND>(lParam);
}
</pre>
</blockquote>
<br>
You do not need to bother with C++ style casts when casting between
numeric types.
</p>
<p><span class="subsectiontitle">Const</span><br>
Use const liberally. Properly const'd programs are safer. Const
declarations act as documentation for developers and hints for the compiler
to help it produce more efficient code. All reference parameters to a
function should be declared const unless they are intended to be modified
by the function. Make a point of declaring const any method which does not
modify class members. When iterating through the members of a container,
use const_iterator instead of iterator unless you intend to modify the
elements of the container.
</p>
<p><span class="subsectiontitle">Reference Parameters</span><br>
Favor passing parameters as references to passing them as pointers. If it is
not expected that the value of the parameter will ever be NULL, you should
certainly use a reference instead of a pointer. The current Celestia code
isn't as consistent about pointers vs. references as it should be.
</p>
<p><span class="subsectiontitle">I/O</span><br>
While C++ I/O is usually preferred, C style I/O with printf/scanf is also
also acceptable. In many cases, printf is simply more convenient and
produces much more readable code than C++'s operator overloading based I/O.
The gets function from the C standard library should never, ever be used.
It's unsafe, and gets related buffer overflows have been the source of
many security holes.
</p>
</div>
<br>
<div>
<span class="sectiontitle">Indentation and Spacing</span><br>
<ul>
<li>Always set your editor to use spaces for indentation. Text editors
interpret tabs in various incompatible ways, but a space is always a space.
<li>The bodies of functions, compound statements, and class definitions
should be indented four spaces.
<li>The braces around a function or compound statement should be on lines
by themselves but not indented with the body of the statement:
<pre style="code">
if (x)
{
cout << "The value of x is: " << x;
}
</pre>
<li>Labels of switch statements are not indented, but the body is:
<pre style="code">
switch (foo)
{
case 1:
x = 1;
break;
case 2:
x = 4;
break;
default:
x = 0;
break;
}
</pre>
<li>Access control labels are indented one space:
<pre style="code">
class Foo
{
public:
Foo();
private:
int x;
};
</pre>
</ul>
<ul>
<li>Put one space on either side of all binary operators except
for ->
<pre style="code">
// Celestia style
x = y + z;
x = y || z;
a = b->c;
// Not Celestia style
x=y;
x = y+z;
a = b -> c;
</pre>
<li>There should be no space between a unary operator and its operand.
<li>Wherever a pointer type appears, there should be no space between the
base type and the asterisk. For pointer variable declarations, a space should
separate the type name from the variable name.
<pre style="code">
// Celestia style
char* str;
str = reinterpret_cast<char*>(p);
// Not Celestia style
char *str;
str = reinterpret_cast<char *>(p);
</pre>
<li>In function calls or definitions, there should be no space
between the parentheses and either the arguments or the function name.
When there are multiple arguments, a single space should follow each comma
separating arguments.
<pre>
// Celestia style
y = square(x);
y = atan2(x, z);
// Not Celestia style
y = square( x );
y = square (x);
y = atan2(x,z);
y = atan2(x , z);
</pre>
</ul>
</div>
<br>
<div>
<span class="sectiontitle">Naming</span>
<ul>
<li>Use capitalization not underscores to separate words in class and
variable names.
<li>Class names should start with a capital letter. The first letter of each
word within the class name should also be capitalized. Class names should
not be prefixed with a C.
<pre style="code">
// Celestia class names
class Renderer;
class UniversalCoord;
// Not Celestia class names:
class RENDERER;
class renderer;
class Universal_Coord;
class CUniversalCoord;
</pre>
<li>Method names are written using the class name conventions except with
the first letter in lower case.
<pre style="code">
// Celestia method names
void render();
int getValue();
void setAbsoluteMagnitude(float);
// Not Celestia method names:
void Render();
int get_value();
void Set_Absolute_Magnitude(float);
</pre>
<li>Functions both static and global use the class name conventions.
<li>Enum values also use the class name conventions.
<li>Macros should be all caps, with words separated by underscores.
<pre style="code">
// Celestia macros
#define INFINITE_MOUSE
#define BROKEN_SSTREAM
// Not Celestia macros
#define InfiniteMouse
#define INFINITEMOUSE
#define broken_sstream
</pre>
<li>Variable names do not contain type information, i.e. Hungarian and other
type-based naming conventions are not used. There are a few important
exceptions. Convenience typedefs for class templates in Celestia's vector
math library do contain type informations. For example,
Vector3<float> is Vec3f and Matrix4<double> is Mat4d.
</ul>
<br>
<div>
<span class="sectiontitle">Portability</span><br>
Celestia is a cross-platform project, and this requires working around the
quirks of several different compilers. Here are a few to watch out for.
<br>
<p><span class="subsectiontitle">The Scope of for</span><br>
The ANSI C++ standard states that the scope of a variable declared in
the initialization part of a for statement is just the for loop. Microsoft
Visual C 6.0 disagrees and lets the definition "leak" out of the loop. Other
compilers (like the GNU C++ compiler) conform to the C++ standard.
Avoid writing code that relies on either behavior. The simplest
rule is to never declare variables in the initialization spection of a for loop.
If you do declare a variable there, make sure that it is not referenced outside
of the for loop.
<blockquote>
<pre style="code">
// This won't compile with Visual C++ (because it's broken)
int sum = 0;
for (int i = 0; i < 5; i++)
sum += i;
for (int i = 0; i < 5; i++)
sum += i * i;
// This version won't compile with g++ (because it conforms to the standard)
int sum = 0;
for (int i = 0; i < 5; i++)
sum += i;
for (i = 0; i < 5; i++)
sum += i * i;
// This version works on any compiler
int sum = 0;
int i;
for (i = 0; i < 5; i++)
sum += i;
for (i = 0; i < 5; i++)
sum += i * i;
</pre>
</blockquote>
</div>
</body>
</html>