]> git.pond.sub.org Git - empserver/blob - doc/coding
64cc15bc8244d568bb85e377d357cb9d282daba5
[empserver] / doc / coding
1                 Guidelines for Writing Empire Code
2
3              compiled and edited by Markus Armbruster
4
5 Preface
6 -------
7
8 Empire is an old program, and the age shows in places.  It took a lot
9 of people a lot of effort to write it.  Chances are that some of them
10 were smarter than you and me.  Treat the code with the respect it
11 deserves.
12
13 These guidelines are just that: guidelines.  Not law.  There's no
14 Empire Coding Police.  People hacked on Empire code long before I knew
15 it existed, and I hope they still will when I fade into Empire
16 history.  But there's substantial experience behind these guidelines,
17 so don't dismiss them cavalierly.
18
19 Here's our goal: algorithmic clarity.  All the rules and guidelines
20 are subservient to it.  If you'd have to obfuscate your code to
21 satisfy the letter of some guideline, don't!
22
23 Mind, I said `clarity', not `self-realization' or `expression of your
24 individuality'.  Dave Pare wrote:
25
26   Be invisible.  When you make a change, think not about marking your
27   place in history, or about showing off how much nicer your two-space
28   tabs are than those old, icky eight-space tabs that the stupid
29   empire hackers of old used, but think instead about the aesthetics
30   of the whole.  The resulting lines of code should flow smoothly from
31   the beginning of the procedure to the end.  Empire is 60,000 lines
32   of code.  If you're the general case, you're only changing fifty
33   lines, so be aware of that.
34
35 Some guidelines are more serious than others.  When I use words like
36 `is', `shall' or `must', I mean it.  When I write `should', it's a
37 recommendation.
38
39 Many guidelines concern style, i.e. they involve matters of taste.
40 That's how it has to be.  Uniformity of style is important for
41 clarity.
42
43 These guidelines don't attempt to be exhaustive.  More complete
44 guidelines that are mostly compatible with Empire can be found at
45 http://www.jetcafe.org/~jim/c-style.html
46
47 See also doc/contributing.
48
49
50 Source tree organization
51 ------------------------
52
53 FIXME
54
55
56 Code formatting
57 ---------------
58
59     In My Egotistical Opinion, most people's C programs should be
60     indented six feet downward and covered with dirt."
61         -- Blair P. Houghton
62
63 Over the years, enough Empire coders lacked the good taste to preserve
64 the style of the original Empire code in their changes, and thus
65 turned the source code into an unreadable mess.  In 2003, we fed it to
66 GNU indent.
67
68 We tried to restore things to the original style, mostly.  There is
69 one notable change: basic indentation is now four spaces.  Restoring
70 the original eight spaces would have resulted in many more long lines,
71 which would have to be broken by indent.  Since indent isn't good at
72 breaking lines tastefully, we reluctantly chose four instead.
73
74 FIXME mention src/scripts/intend-emp, even better: convert it into an
75 indent profile and mention that.
76
77 If you use Emacs, `stroustrup' indentation style produces satisfactory
78 results.  The command `c-set-style', normally bound to `C-c .', lets
79 you set the style for the current buffer.  Set variable
80 `c-default-style' to "stroustrup" to switch to this style for all
81 buffers.
82
83 Avoid gratuitous space change
84
85 Don't change whitespace gratuitiously, say just because your editor
86 screws up tabs.  Such changes make it much harder to figure out who
87 changed what and when.
88
89 TAB character use
90
91 Whether you use TAB characters or not doesn't really matter that much,
92 but TAB stops are every eight characters, period.
93
94 Indentation, placement of braces, function name
95
96 Basic indentation is four spaces.  The opening brace goes on the same
97 line as `if', `struct', etc.  Put `else' and do loops' `while' one the
98 same line as the closing brace.  You are encouraged to leave out
99 syntactically optional braces.  Don't indent case labels.
100
101 Example:
102
103         if (is_fubar())
104             despair();
105         else {
106             do {
107                 char ch = getchar();
108                 switch (ch) {
109                 case EOF:
110                     return;
111                 case '\n':
112                     break;
113                 default:
114                     grind_along(ch);
115                 }
116             } while (happy());
117         }
118
119 In a function definition, the return type, function name and the
120 braces must all start on a new line, unindented, like this:
121
122         type
123         name(arguments)
124         {
125             body
126         }
127
128 This does not apply to function declarations.
129
130 Breaking long lines
131
132 Line length should not exceed 75 characters.  Break such lines at a
133 logical place, preferably before an operator with low precedence.
134 Line up the continuation line with the innermost unclosed parenthesis,
135 if there is one, else indent it four spaces.
136
137 Example:
138
139         FIXME
140
141 Bad example:
142
143         FIXME
144
145 Blank lines
146
147 Use blank lines to separate different things.  Functions must be
148 separated by a blank line.  You are encouraged to insert a blank line
149 between a block's declarations and statements.
150
151 Spaces
152
153 There is a space after `for', `if', and `while'.  If `for' and `while'
154 are followed by `;' (empty loop body) on the same line, there is a
155 space before the `;'.  There is no space between the function name and
156 the `(', but there is a space after each `,'.  There should be no
157 space between type cast operator and operand.  There is no extra space
158 after '(' and before ')'.
159
160 Example:
161
162         for (p = s; *p; ++p) ;
163         printf("%ld\n", (long)(p-s));
164
165 Comments
166
167 The function comment describing what a function does goes directly
168 above the definition.
169
170 Comments to the right of code should start in column 32 if possible
171 (counting from zero).
172
173 Comment lines should be indented exactly like the code the belong to.
174
175 You are encouraged to format multi-line comments like this:
176
177         /*
178          * Please use complete sentences, with proper grammar,
179          * capitalization and punctuation.  Use two spaces between
180          * sentences.
181          */
182
183 But please avoid elaborate boxes like this:
184
185         /***********************************************************
186          * Such decorations are a waste of time, hard to edit, and *
187          * ugly, too.                                              *
188          ***********************************************************/
189
190 Do not use
191
192         // C++/C99 comments
193
194 because they are not portable C89.
195
196
197 Conditional compilation
198
199 Unless the conditional code is very short, please comment it like
200 this:
201
202         #ifdef FOO
203         ...
204         #endif /* FOO */
205
206         #ifdef BAR
207         ...
208         #else  /* !BAR */
209         ...
210         #endif /* !BAR */
211
212
213 Style
214 -----
215
216 Names
217
218 DoNotUseStudlyCaps!  Stick to lower_case and use underscores.  Upper
219 case is for macros and enumeration constants.
220
221 File names should not differ in case only, since not all file systems
222 distinguish case.  Best stick to lower case.  Avoid funny characters
223 in file names.  This includes space.
224
225 Preprocessor
226
227 Like many good things, the preprocessor is best used sparingly.
228 Especially conditional compilation.
229
230 Do not use the preprocessor to `improve' the syntax of C!
231
232 Macro names should be ALL_CAPS to make them stand out.  Otherwise,
233 they can be mistaken for objects or functions.  This is bad, because
234 `interesting' behavior can hide inside macros, like not evaluating
235 arguments, or changing them.  Exception: if a function-like macro
236 behaves exactly like a function, then you may use a lower case name.
237
238 Parameters that can take expression arguments must be parenthesized in
239 the expansion.  If the expansion is an expression, it should be
240 parenthesized as well.
241
242 You are encouraged to use enumeration constants instead of macros when
243 possible.  The existing code doesn't, but it makes sense all the same.
244
245 Comments
246
247 Every file should have a file comment FIXME
248
249 Every function should have a function comment that describes what it
250 does.  FIXME elaborate.  Writing such comments helps both future
251 maintainers and yourself: if it's too hard to write a concise function
252 comment, then your function is likely too complicated and could use a
253 redesign.
254
255 The existing code has very little useful comments, and it'll likely
256 take us years to fix it.  Please don't make it harder than it already
257 is.
258
259 Declarations
260
261 Do not declare system functions yourself; include the appropriate
262 system header.
263
264 Use prototypes, not old-style function declarations.
265
266 To get the best use of C's type checking, each function or variable
267 with external linkage should have exactly one declaration, in some
268 header file, and that declaration must be in scope at the definition.
269 No other declarations should exist.  In particular, please include the
270 appropriate header instead of just declaring stuff again.  The code
271 used to be full of this kind of junk, and it was quite some work to
272 clean it up.
273
274 Forward declarations of static functions should all go in one place
275 near the beginning of the file.
276
277 If you want a typedef name in addition to a structure or union tag,
278 give it the same name, like this:
279
280         typedef struct foo foo;
281
282 Yes, this is incompatible with C++.  Reducing the number of names for
283 the same thing is more useful than compatibility to a programming
284 language we don't use.
285
286 Please don't hide away pointers with typedefs, like this:
287
288        typedef struct foo *foop;
289
290 When I see `foo *', I *know* what it is.  When I see `foop', I have to
291 look it up.
292
293 Booleans
294
295 Do not use increment operators to set a variable to logical true!  It
296 obfuscates the purpose, and narrow variables could even overflow.
297 Just assign 1.  A lot of cleanup remains to be done there.
298
299 Null pointer constant
300
301 Please use NULL for clarity, not just 0.
302
303 Type casts
304
305 Casting pointers to and from `void *' clutters the code and serves no
306 purpose (repeat after me: C is not C++).  It is also unsafe, because
307 the cast suppresses type warnings.
308
309 Casting function values to void clutters the code and serves little
310 purpose (repeat after me: C is not Pascal).
311
312 Casting an argument to the type of the parameter clutters the code and
313 serves no purpose (repeat after me: ISO C is not K&R C).
314
315 Factor out common code
316
317 Do not gratuitously duplicate code!  Ken Stevens said it well, and
318 it's as relevant as ever:
319
320   Cut-and-Paste coding is by far the biggest problem that the current
321   Empire suffers from.  This is how cut-and-paste coding happens.  Joe
322   Shmuck decides that he wants to add a new function to the server.
323   So he goes hunting through the server to find some already existing
324   code which does something similar to what he wants to do.  This is
325   good.  You should always write new code to imitate old code.  What
326   is bad is when Joe Shmuck decides to simply "copy" 200 lines of code
327   from the old function into his new function, and then just change a
328   couple of little things here and there to suit his needs.  This
329   method, known as Cut-and-Paste coding is the fastest and easiest way
330   to code.  However, it results in a server that is impossible to
331   maintain.  What Joe _should_ have done, is "move" the 200 lines of
332   code into a new _third_ function which the first two both call.
333   This is called writing a "general solution" to handle both cases.
334   Most of my work in the Empire2 project consisted in cleaning up
335   after a bunch of Joe Shmucks.
336
337
338 Portability
339 -----------
340
341 FIXME C89, POSIX
342
343 FIXME sizes, printf formats
344
345 FIXME reserved names
346
347 FIXME conditional compilation is a last resort
348
349
350 Robustness
351 ----------
352
353 Error checking
354
355 Check error conditions meticulously.  The existing code is bad enough
356 at this, please don't make it worse.
357
358 FIXME what to do on error
359
360 Sanity checking
361
362 In many places, the code checks for conditions that should not happen,
363 and then tries to recover.  This is sound defensive programming.
364 Please use CANT_HAPPEN() and CANT_REACH() for this purpose, because
365 they log the error condition, and optionally abort the program, or
366 write out a core dump.  This is called an "oops".
367
368 Buffer overruns
369
370 FIXME
371
372 Thread safety
373
374 Thread stacks cannot grow.  If you use too much automatic storage, you
375 can overrun the stack with disastrous consequences.  FIXME elaborate
376
377 Empire uses non-preemptive threads: a thread runs until it yields the
378 processor.  This simplifies programming, but there are still traps to
379 avoid.  Yielding the processor is an explicit thread operation, and
380 whether a thread operation yields is documented in empthread.h.
381 However, the operation may be buried in library code.
382
383 In particular, player input may yield.  Player output may yield only
384 if it goes to the current player, and his last command doesn't have
385 the C_MOD flag.  You can use this to simplify command code: set C_MOD
386 if you don't want to worry about yield on output.  This is commonly
387 done for commands that modify game state.
388
389 Be careful with static storage.  Read-only data is fine.  More than
390 one thread writing static data is problematic, but there are safe
391 uses.  For instance, a static scratch buffer that is never used across
392 `yields' is safe.
393
394 Yielding the processor invalidates *all* the game state you copied
395 into variables.  You have to reread and possibly recheck.  See below.
396
397 Accessing game state
398
399 Game state consists of several sets of objects, e.g. sectors, ships,
400 bmaps, ...  Each set is fully held in memory and backed by a file in
401 the data directory.
402
403 There are several ways to access an object in set FOO:
404
405 * You can get a pointer to the object (not a copy!) with getFOOp().
406
407   This is inherently dangerous, because it allows you to update the
408   object in memory without updating the disk file.  It's used mostly
409   in update code, where it pays major performance dividends, but there
410   are uses in other places.  Whether they are wise is debatable.
411
412   Obviously, the object can change when you let another thread run.
413   This is not an issue in update code, because it never yields.
414
415 * You can get a copy with getFOO() and write it back with putFOO().
416
417   Putting updates both the object in memory and the disk file.
418
419   Any change to the object invalidates the copy.  Putting such an
420   invalid copy will clobber the change(s) that invalidated it,
421   possibly resulting in corrupted game state.  The code oopses on such
422   puts, but it can't repair the damage.
423
424   There are two common ways to invalidate a copy: calling a function
425   that updates the object you copied (unless it does that through your
426   copy), and yielding the processor, which lets other threads update
427   the object you copied.
428
429   Therefore, you have to re-get after a possible invalidation, and
430   deal with changes.  In particular, if you checked whether the object
431   is suitable for a task, you need to check again after re-getting it.
432   If you can afford to bail out when something changed, use
433   check_FOO_ok().
434
435   Function comments should state what objects the function can update.
436   Unfortunately, they generally don't.
437
438   It's best to keep puts close to gets, both at runtime and in the
439   source code.
440
441 * Bmaps have special access functions.
442
443   Each country has two bmaps: the working bmap and the true bmap.
444   Unfortunately, the bmap code calls the former `bmap' and the latter
445   `map'.
446
447   You update bmaps with map_set().  This doesn't write through to the
448   file; instead, it returns non-zero when the update changed anything.
449   In that case, you must write bmaps to disk with writemap() before
450   you yield.  If you only updated the working bmap, then you can call
451   writebmap() instead.
452
453 Reading player input
454
455 Reading player input can fail, and you must check for that.
456 Neglecting it can break the interrupt feature for players (normally
457 Ctrl-C), and produce extra prompts that could confuse clients.  Even
458 worse is neglecting it in a loop that terminates only when input is
459 read successfully.
460
461 When reading input fails, you should normally abort the command with
462 status RET_SYN.  There are exceptions, e.g. when aborting a pinpoint
463 bombing run over the target.
464
465 Some functions to read player input return a special error value you
466 can check, e.g. recvclient(), prmptrd() and uprmptrd() return a
467 negative value, getstring() and getstarg() return NULL.
468
469 Others return the same error value for failed read and for successful
470 read of input that is invalid.  Then you need to check
471 player->aborted; if it is set after a read, the read failed.
472
473 \f
474 Historical guidelines, superseded by the above
475
476
477 Remarks from Dave Pare:
478
479 And now, a few editorial remarks on my views on Good Techniques for
480 Modifying Existing Software:
481
482 My safari through the hot and bug-ridden jungle that Empire has become
483 has given me some new insights on the modification of large software
484 packages.  My adventure has prompted me to propose some simple coding
485 guidelines for those dreaming of hacking on the code:
486
487 1) Be invisible.  When you make a change, think not about marking your
488 place in history, or about showing off how much nicer your two-space
489 tabs are than those old, icky eight-space tabs that the stupid empire
490 hackers of old used, but think instead about the asethetics of the whole.
491 The resulting lines of code should flow smoothly from the beginning of the
492 procedure to the end.  Empire is 60,000 lines of code.  If you're the
493 general case, you're only changing fifty lines, so be aware of that.
494
495 2) Procedurize.  If you find yourself in a triple-nested loop, or a five
496 hundred line procedure, perhaps it's because you need to split some of
497 that code off into a procedure.  In general, if you've got more than two
498 levels of tabs (or indentations), or more than one or two major loops in
499 a procedure, something may well be amiss.
500
501
502 Sasha Mikheev on indentation:
503
504 The empire indentation style can be achived by using
505 indent -orig -i8 foo.c
506
507 or in old c-mode emacs (versions before 19.29):
508 ;add this to .emacs
509 (setq c-indent-level 8)
510 (setq c-continued-statement-offset 8)
511 (setq c-argdecl-indent 8)
512 (setq c-brace-offset -8)
513 (setq c-label-offset -8)
514
515
516 Further comments by Ken Stevens:
517
518 1) Global variables
519 The only variables which should be global are constants.  If you write
520 a routine which changes a global variable, then you will corrupt the
521 data when two different players run that routine at the same time.
522
523 2) Portability.
524 The following code:
525                 char    a;
526         #ifdef FOO
527                 unsigned char b;
528         #endif FOO
529 Should be rewritten as:
530                 s_char  a;
531         #ifdef FOO
532                 u_char  b;
533         #endif /* FOO */
534
535 AIX has different conventions for signed chars, and IRIX requires the
536 /* comments */ after #endif.
537
538 3) Cut-and-Paste
539 Cut-and-Paste coding is by far the biggest problem that the current
540 Empire suffers from.  This is how cut-and-paste coding happens.  Joe
541 Shmuck decides that he wants to add a new function to the server.  So
542 he goes hunting through the server to find some already existing code
543 which does something similar to what he wants to do.  This is good.
544 You should always write new code to imitate old code.  What is bad is
545 when Joe Shmuck decides to simply "copy" 200 lines of code from the old
546 function into his new function, and then just change a couple of
547 little things here and there to suit his needs.  This method, known as
548 Cut-and-Paste coding is the fastest and easiest way to code.  However,
549 it results in a server that is impossible to maintain.  What Joe
550 _should_ have done, is "move" the 200 lines of code into a new _third_
551 function which the first two both call.  This is called writing a
552 "general solution" to handle both cases.  Most of my work in the
553 Empire2 project consisted in cleaning up after a bonch of Joe Shmucks.
554 I took repeated code and "consolidated" it into general function
555 libraries.
556
557 4) Good style.
558 Just to add to Dave's "Be Invisible" motto, I'd like to give a little
559 example to illustrate some basic do's and don'ts for coding style:
560
561 The following function has bad style:
562
563 double att_combat_eff(com,own)
564 struct combat *com;
565 natid own;{
566   double str;
567   double eff=1.0;
568   if(com->type==EF_SECTOR)
569   {
570     eff=com->eff/100.0;
571     if(com->own==own){
572       str=com->sct_dcp->d_ostr;
573     }else{
574 str=com->sct_dcp->d_dstr;eff=2.0+(str-2.0)*eff;
575     }else if(com->type==EF_SHIP&&com->own!=own)
576       eff=(1.0+com->shp_mcp->m_armor/100.0);
577   return eff;}
578
579 Here is the same function written with "good" style:
580
581 double
582 att_combat_eff(com, own)
583         struct  combat *com;
584         natid   own;
585 {
586         double  eff = 1.0;
587         double  str;
588
589         if (com->type == EF_SECTOR) {
590                 eff = com->eff / 100.0;
591                 if (com->own == own)
592                         str = com->sct_dcp->d_ostr;
593                 else
594                         str = com->sct_dcp->d_dstr;
595                 eff = 2.0 + (str - 2.0) * eff;
596         } else if (com->type == EF_SHIP && com->own != own)
597                 eff = (1.0 + com->shp_mcp->m_armor / 100.0);
598
599         return eff;
600 }
601
602 These are all the things I fixed when changing the bad to the good:
603 - Function names should always start a new line (so you can search for them)
604 - There should always be a space after a ","
605 - Function arguments should be indented 8 spaces
606 - There should always be a tab after a type declaration
607 - Opening function bracket should be on a line by itself
608 - Indentation should be 8 spaces
609 - There should always be a space on both sides of every operator
610 - There should always be a space after if, for, while, switch
611 - The opening bracket should be on the same line as the if
612 - There should always be a space on either side of a {
613 - There should always be a new line after a ;
614 - The closing function bracket should be on a line by itself