Style Guidelines: Difference between revisions
Doxygen not in favor. ;) |
m Change ordering, removed Doxygen requirement |
||
Line 3: | Line 3: | ||
inside the examples. | inside the examples. | ||
=== All-encompassing Guidelines === | |||
==== Indentation ==== | |||
Indent your code with tabs (ASCII 9). Use space (ASCII 32) for all other | |||
formatting. | |||
==== Braces ==== | |||
Braces are on their own line, on the same level of indentation as the | |||
structure they belong to. Braces around <tt>else</tt> may stand on the same | |||
line as the <tt>else</tt>. You may add braces around single statements in | |||
<tt>if</tt> statements if the first block or an <tt>else</tt> block has them. | |||
if (count < 10) | |||
{ | |||
printf("Too few thingies!"); | |||
AddMore(); | |||
} else { | |||
printf("We have enough"); | |||
} | |||
==== Spaces ==== | |||
Function names are not followed by space. Commas are. No space follows opening | |||
brackets ("[") or parentheses ("("). Also no space preceeds closing brackets | |||
("]") or parentheses (")"). Unary operators do not require spaces. Binary | |||
operators do. | |||
Keywords (<tt>while</tt>, <tt>for</tt> etc.) are followed by a space. | |||
==== Parentheses ==== | |||
Do not use parentheses unless they are required for precedence or the code | |||
gets confusing without them. Remember other people may have confusion | |||
thresholds different from you. | |||
==== Control Structures ==== | |||
Control structures with a single statements are written without braces. If the | |||
statement spans multiple lines, you may add braces for readability. Structures | |||
without a statement contain a comment denoting this. | |||
while (*dest++ = *src++) | |||
/* empty */; | |||
Cascades in a <tt>switch</tt> statement are marked by a FALLTHROUGH | |||
comment. Code that cannot be reached has an assertion. <tt>case</tt> elements | |||
are not indented. | |||
switch (foo) | |||
{ | |||
case FOO_HEX: | |||
accept_hex = true; | |||
// FALLTHROUGH | |||
case FOO_DEC: | |||
accept_num = true; | |||
break; | |||
default: | |||
assert(!"Invalid foo value"); | |||
// Do something meaningful here anyway, if possible; | |||
// try to not leave the program in an ill-defined state. | |||
} | |||
==== Comments ==== | |||
// Single-line comments look like this | // Single-line comments look like this | ||
/* | /* | ||
Line 14: | Line 69: | ||
*/ | */ | ||
==== Type Casting ==== | |||
Do not use C-style or function style casts. Use a template cast instead. | |||
=== Source File Layout === | |||
==== Copyright Header ==== | |||
Every source file begins with a copyright header. If you make significant | Every source file begins with a copyright header. If you make significant | ||
changes to the code, you may (but are not required to) add your name to the | changes to the code, you may (but are not required to) add your name to the | ||
Line 37: | Line 97: | ||
the purpose of the file next, and leave another blank line after this. | the purpose of the file next, and leave another blank line after this. | ||
==== Inclusion Guards ==== | |||
If you are writing a header file, use #include guards. If your file is called | If you are writing a header file, use #include guards. If your file is called | ||
''C4Foo.h'', your guard should be <tt>INC_''C4Foo''</tt>. | ''C4Foo.h'', your guard should be <tt>INC_''C4Foo''</tt>. | ||
Line 47: | Line 108: | ||
''TODO: Precompiled headers.'' | ''TODO: Precompiled headers.'' | ||
Include | ==== #include Directives ==== | ||
Include local headers first. Put the filename in double quotes, and use | |||
forward slashes as directory separators. | forward slashes as directory separators. | ||
#include | #include "Standard.h" | ||
#include "StdBuf.h" | |||
Leave a blank line before | Leave a blank line before system headers. Use angle brackets to include these, | ||
and sort them alphabetically. | and sort them alphabetically. | ||
#include | #include <map> | ||
#include | #include <vector> | ||
=== Declarations === | |||
==== Preprocessor Macros ==== | |||
Do not <tt>#define</tt> values in headers. Use <tt>const</tt> instead, or | Do not <tt>#define</tt> values in headers. Use <tt>const</tt> instead, or | ||
<tt>enum</tt> if you are declaring an enumeration. | <tt>enum</tt> if you are declaring an enumeration. | ||
Line 77: | Line 142: | ||
} while(0) | } while(0) | ||
==== Data Types ==== | |||
Do not use the Win32 style integer declarations <tt>DWORD</tt> and | Do not use the Win32 style integer declarations <tt>DWORD</tt> and | ||
<tt>BOOL</tt>. If you need a guarantee about the size of your variables, use | <tt>BOOL</tt>. If you need a guarantee about the size of your variables, use | ||
Line 94: | Line 160: | ||
char *Qux(const char *quux); | char *Qux(const char *quux); | ||
==== Functions ==== | |||
Functions that are not used outside of the containing file are placed inside | Functions that are not used outside of the containing file are placed inside | ||
of an anonymous namespace. | of an anonymous namespace. | ||
namespace { | namespace | ||
{ | |||
int Frobnicate(const char *foo); | int Frobnicate(const char *foo); | ||
} | } | ||
Line 111: | Line 179: | ||
XmlDocument *ParseXmlFile(const char *file); | XmlDocument *ParseXmlFile(const char *file); | ||
When passing arguments that may be changed by the called function, pass them | When passing arguments that may be changed by the called function, pass them | ||
as pointers. This makes it obvious that they may be changed. Use constant | as pointers. This makes it obvious that they may be changed. Use constant | ||
references for all other parameters, unless they are a primitive type. | references for all other parameters, unless they are a primitive type. | ||
==== Class Members ==== | |||
No class member variable should be declared <tt>public</tt> unless necessary. | |||
Consider using <tt>GetFoo</tt> and <tt>SetFoo</tt> accessors. If you want to | |||
declare a compound data type that allows direct access to its members, use | |||
<tt>struct</tt>. Do not add more functions than constructors, destructors, and | |||
assignment operators to <tt>struct</tt>s. | |||
Mark all class members that do not change the visible state of the object | Mark all class members that do not change the visible state of the object | ||
<tt>const</tt>. If you need to modify internal state that is not visible from | <tt>const</tt>. If you need to modify internal state that is not visible from | ||
outside of the class, mark the state variable <tt>mutable</tt>. | outside of the class, mark the state variable <tt>mutable</tt>. | ||
Revision as of 09:21, 5 August 2009
This document specifies the preferred source code style of files inside the OpenClonk source tree. Some of the style rules are also stated implicitly inside the examples.
All-encompassing Guidelines
Indentation
Indent your code with tabs (ASCII 9). Use space (ASCII 32) for all other formatting.
Braces
Braces are on their own line, on the same level of indentation as the structure they belong to. Braces around else may stand on the same line as the else. You may add braces around single statements in if statements if the first block or an else block has them.
if (count < 10) { printf("Too few thingies!"); AddMore(); } else { printf("We have enough"); }
Spaces
Function names are not followed by space. Commas are. No space follows opening brackets ("[") or parentheses ("("). Also no space preceeds closing brackets ("]") or parentheses (")"). Unary operators do not require spaces. Binary operators do.
Keywords (while, for etc.) are followed by a space.
Parentheses
Do not use parentheses unless they are required for precedence or the code gets confusing without them. Remember other people may have confusion thresholds different from you.
Control Structures
Control structures with a single statements are written without braces. If the statement spans multiple lines, you may add braces for readability. Structures without a statement contain a comment denoting this.
while (*dest++ = *src++) /* empty */;
Cascades in a switch statement are marked by a FALLTHROUGH comment. Code that cannot be reached has an assertion. case elements are not indented.
switch (foo) { case FOO_HEX: accept_hex = true; // FALLTHROUGH case FOO_DEC: accept_num = true; break; default: assert(!"Invalid foo value"); // Do something meaningful here anyway, if possible; // try to not leave the program in an ill-defined state. }
Comments
// Single-line comments look like this
/* * Multi-line comments look like this. Make sure you write enough text to * warrant a multi-line comment. Also be sure to write in full sentences. */
Type Casting
Do not use C-style or function style casts. Use a template cast instead.
Source File Layout
Copyright Header
Every source file begins with a copyright header. If you make significant changes to the code, you may (but are not required to) add your name to the list of copyright holders. If you choose to add yourself, use your real name, not a nickname. Legally recognized pseudonyms are accepted, as are names of legal entities. If you don't want to add yourself, you may add the catch-all copyright attribution phrase, if it does not already exist.
/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 2000-2009 John Doe * Copyright (c) 2005 Jane Q. Public * * Portions might be copyrighted by other authors who have contributed * to OpenClonk. * * Other legalese goes here, but has been omitted for brevity. See an * existing file for a template. */
The copyright header is followed by an empty line. Put a comment explaining the purpose of the file next, and leave another blank line after this.
Inclusion Guards
If you are writing a header file, use #include guards. If your file is called C4Foo.h, your guard should be INC_C4Foo.
#ifndef INC_C4Foo #define INC_C4Foo class C4Foo; #endif
TODO: Precompiled headers.
#include Directives
Include local headers first. Put the filename in double quotes, and use forward slashes as directory separators.
#include "Standard.h" #include "StdBuf.h"
Leave a blank line before system headers. Use angle brackets to include these, and sort them alphabetically.
#include <map> #include <vector>
Declarations
Preprocessor Macros
Do not #define values in headers. Use const instead, or enum if you are declaring an enumeration.
Do not #define inline functions either, use inline. If your functions need to work on multiple data types, overload the function or write a template.
If, despite of the above, still need to write a macro, use an all-uppercase name. If your macro contains a compound statement, enclose it in a do loop to allow its use in if statements. A terminating semicolon should be provided at the place of invocation. This makes parsing the source easier for pretty-printers and editors. If your macro spans multiple lines, align the backslashes.
#define FOO(a, b) do { \ bar += (a); \ bar /= (b); \ } while(0)
Data Types
Do not use the Win32 style integer declarations DWORD and BOOL. If you need a guarantee about the size of your variables, use the C99 types intXX_t and uintXX_t. If you don't need that guarantee, use int. If you need a variable that is large enough to store a pointer on your current platform, use intptr_t.
If you come across code that still uses Win32 types, consider changing it if you are working on code in the vicinity. Don't commit changes that only consist of replacing DWORD by uint32_t.
When declaring a pointer, put a space in front of the asterisk, and none after. This saves some confusion when declaring multiple variables at once. The same goes for references.
int *foo, *bar; char *Qux(const char *quux);
Functions
Functions that are not used outside of the containing file are placed inside of an anonymous namespace.
namespace { int Frobnicate(const char *foo); }
Functions that are used across multiple files are prototyped inside a common header. The prototypes should be grouped where appropriate, and ordered logically or, failing that, alphabetically.
Function and class names begin with a capital letter, and use camel casing. If you need to embed acronyms inside the name, pretend the acronym was all lower case. Member variables use the same convention, but begin with a lower case letter. Do not use hungarian prefixes.
XmlDocument *ParseXmlFile(const char *file);
When passing arguments that may be changed by the called function, pass them as pointers. This makes it obvious that they may be changed. Use constant references for all other parameters, unless they are a primitive type.
Class Members
No class member variable should be declared public unless necessary. Consider using GetFoo and SetFoo accessors. If you want to declare a compound data type that allows direct access to its members, use struct. Do not add more functions than constructors, destructors, and assignment operators to structs.
Mark all class members that do not change the visible state of the object const. If you need to modify internal state that is not visible from outside of the class, mark the state variable mutable.