Coding Standards: Difference between revisions
m only style changes |
No edit summary |
||
| (5 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
<span class=warning> | <span class=warning> | ||
This document is not yet finished. Please add new points whenever they occur to you. | This document is not yet finished.<br> | ||
Please add new points whenever they occur to you. | |||
</span> | </span> | ||
| Line 18: | Line 19: | ||
This implies that you should not use tabs in any other place then indentation. E.g. in the following sample use SPACE to align the constants. | This implies that you should not use tabs in any other place then indentation. E.g. in the following sample use SPACE to align the constants. | ||
{{code| | |||
#define LOS_INLOS 1 | #define LOS_INLOS 1 | ||
#define LOS_INRADAR 2 | #define LOS_INRADAR 2 | ||
}} | |||
Do not attempt to align method parameters in a function call when breaking it over multiple lines. Just indent them using two tabs. Trying to align parameters with the opening parenthesis is unmaintainable: next time someone refactors the code and changes the function name, he has to go through all places it is used this way and waste his time inserting/removing spaces. Of course this applies to similar cases too; in general aligning stuff in such a way that an identifier rename requires realignment of all code using that identifier is bad practice. | Do not attempt to align method parameters in a function call when breaking it over multiple lines. Just indent them using two tabs. Trying to align parameters with the opening parenthesis is unmaintainable: next time someone refactors the code and changes the function name, he has to go through all places it is used this way and waste his time inserting/removing spaces. Of course this applies to similar cases too; in general aligning stuff in such a way that an identifier rename requires realignment of all code using that identifier is bad practice. | ||
| Line 28: | Line 29: | ||
For top-level types (struct/class/union/enum), braces go on the next line and for function definitions they may go on the same line: | For top-level types (struct/class/union/enum), braces go on the next line and for function definitions they may go on the same line: | ||
<pre> | |||
class CMyClass | class CMyClass | ||
{ | { | ||
| Line 55: | Line 56: | ||
} while (condition1); | } while (condition1); | ||
} | } | ||
</pre | </pre> | ||
For if-else statements (and similar), the following is also fine: | For if-else statements (and similar), the following is also fine: | ||
<pre> | |||
if (condition) { | if (condition) { | ||
} | } | ||
else { | else { | ||
} | } | ||
</pre | </pre> | ||
For if's with a single line statement, it is preferred to omit the braces | For if's with a single line statement, it is preferred to omit the braces if no braces belonging to another control block follow immediately after the statement: | ||
<pre> | |||
if (condition) | function() { // recommended | ||
if (condition) | |||
statement; | statement; | ||
if (condition) { | |||
if (condition) { | |||
statement; | statement; | ||
} | } | ||
</pre | } | ||
function() { // okay | |||
if (condition) { | |||
statement; | |||
} | |||
if (condition) | |||
statement; | |||
} | |||
</pre> | |||
==Naming== | ==Naming== | ||
In Spring engine code, concrete classes are prefixed with C, interfaces with I, structs with S. Both use CamelCase. Functions and methods use CamelCase too. Parameters, fields, variables use pascalCase. | In Spring engine code, concrete classes are prefixed with C, interfaces with I, structs with S. Both use CamelCase. Functions and methods use CamelCase too. Parameters, fields, variables use pascalCase. | ||
<pre> | |||
// interface | // interface | ||
class ISkirmishAI | class ISkirmishAI | ||
| Line 91: | Line 100: | ||
char* myStr; | char* myStr; | ||
}; | }; | ||
</pre | </pre> | ||
There are two exception to this however: | There are two exception to this however: | ||
| Line 104: | Line 113: | ||
Keep classes dedicated to a single function, do not create big monolithic classes which no one understands. | Keep classes dedicated to a single function, do not create big monolithic classes which no one understands. | ||
Insert a blank line to separate two parts of a function that have very distinct functionality. Otherwise try to keep the code compact with as few lines as possible, but avoid putting multiple statements on a single line and do not write lines more than 120 characters long. | |||
We use comment tags (TODO, FIXME, ..) as described [http://en.wikipedia.org/wiki/Comment_%28computer_programming%29#Tags here]. | We use comment tags (TODO, FIXME, ..) as described [http://en.wikipedia.org/wiki/Comment_%28computer_programming%29#Tags here]. | ||
On pointer or reference types, try to keep the respective symbol adjacent to the type: | On pointer or reference types, try to keep the respective symbol adjacent to the type: | ||
<pre> | |||
// better | // better | ||
char* myStr; | char* myStr; | ||
| Line 124: | Line 135: | ||
int * MyVar = (int *)OtherVar; | int * MyVar = (int *)OtherVar; | ||
void MyMethod(const std::string & myParam); | void MyMethod(const std::string & myParam); | ||
</pre | </pre> | ||
If there is no type, keep the symbol adjacent to the variable name: | If there is no type, keep the symbol adjacent to the variable name: | ||
<pre> | |||
// better | // better | ||
char myChar, *myCharPointer, **myCharDoublePointer; | char myChar, *myCharPointer, **myCharDoublePointer; | ||
| Line 134: | Line 145: | ||
// bad | // bad | ||
char myChar, * myCharPointer, * * myCharDoublePointer; | char myChar, * myCharPointer, * * myCharDoublePointer; | ||
</pre | </pre> | ||
For items separated by commas, e.g. function parameters and enums, keep one space after each comma: | For items separated by commas, e.g. function parameters and enums, keep one space after each comma: | ||
<pre> | |||
// good | // good | ||
void MyFun(int a, int b, int c); | void MyFun(int a, int b, int c); | ||
| Line 144: | Line 155: | ||
void MyFun(int a,int b,int c); | void MyFun(int a,int b,int c); | ||
int MyArr[3] = {1,2,3}; | int MyArr[3] = {1,2,3}; | ||
</pre | </pre> | ||
For operators, e.g. =, + and -, keep one space on each side. Avoid using extra spaces around parentheses: | For operators, e.g. =, + and -, keep one space on each side. Avoid using extra spaces around parentheses: | ||
<pre> | |||
// good | // good | ||
void i = (1 - b); | void i = (1 - b); | ||
| Line 154: | Line 165: | ||
void i=( 1-b ); | void i=( 1-b ); | ||
void j=((1/b)+5)*c; | void j=((1/b)+5)*c; | ||
</pre | </pre> | ||
==External dependencies== | ==External dependencies== | ||
| Line 169: | Line 180: | ||
* [http://www.tiobe.com/content/paperinfo/gemrcsharpcs.pdf Philips Medical Systems - Coding Standard: C#] (free online book) | * [http://www.tiobe.com/content/paperinfo/gemrcsharpcs.pdf Philips Medical Systems - Coding Standard: C#] (free online book) | ||
[[Category: | [[Category:Engine Dev]] | ||
Latest revision as of 01:25, 23 November 2018
This document is not yet finished.
Please add new points whenever they occur to you.
Compiler
Keep in mind that we use gcc (g++) as the main compiler, likewise for linux and windows builds. So be sure your code compiles and works with gcc.
Directory structure
http://github.com/spring/spring/blob/master/directories.txt
Style
Indentation
Use tabs, not spaces. This allows anyone to choose their favorite indentation size.
This implies that you should not use tabs in any other place then indentation. E.g. in the following sample use SPACE to align the constants. <syntaxhighlight lang="bash">
#define LOS_INLOS 1 #define LOS_INRADAR 2
</syntaxhighlight>
Do not attempt to align method parameters in a function call when breaking it over multiple lines. Just indent them using two tabs. Trying to align parameters with the opening parenthesis is unmaintainable: next time someone refactors the code and changes the function name, he has to go through all places it is used this way and waste his time inserting/removing spaces. Of course this applies to similar cases too; in general aligning stuff in such a way that an identifier rename requires realignment of all code using that identifier is bad practice.
Curly braces
For top-level types (struct/class/union/enum), braces go on the next line and for function definitions they may go on the same line:
class CMyClass
{
};
void MyFunction()
{
}
// fine too
void MyFunction2() {
}
Non-top-level types may use the same style as control flow braces.
For control flow, braces go on the same line:
if (condition) {
} else {
}
for (int i = 0; i < 10; ++i) {
do {
while (condition2) {
}
} while (condition1);
}
For if-else statements (and similar), the following is also fine:
if (condition) {
}
else {
}
For if's with a single line statement, it is preferred to omit the braces if no braces belonging to another control block follow immediately after the statement:
function() { // recommended
if (condition)
statement;
if (condition) {
statement;
}
}
function() { // okay
if (condition) {
statement;
}
if (condition)
statement;
}
Naming
In Spring engine code, concrete classes are prefixed with C, interfaces with I, structs with S. Both use CamelCase. Functions and methods use CamelCase too. Parameters, fields, variables use pascalCase.
// interface
class ISkirmishAI
{
};
// concrete class implementing interface
class CMySkirmishAI : public ISkirmishAI
{
void MyMethod(bool myParam);
int myField;
char* myStr;
};
There are two exception to this however:
- helper subclasses do not have any prefix, and
- value types neither (it is "
float3", not "Cfloat3").
File-names are usually identical to the name of the main class that is inside, with the prefix stripped off. For example, MySkirmishAI.cpp for class CMySkirmishAI.
General
Try to keep code as readable as possible. This means, do not write very long functions, but split the problem in multiple functions. Use identifier names with an actual meaning as opposed to a,b,c, etc. The point is to allow other devs to "read" the code, as opposed to "figure it out".
Keep classes dedicated to a single function, do not create big monolithic classes which no one understands.
Insert a blank line to separate two parts of a function that have very distinct functionality. Otherwise try to keep the code compact with as few lines as possible, but avoid putting multiple statements on a single line and do not write lines more than 120 characters long.
We use comment tags (TODO, FIXME, ..) as described here.
On pointer or reference types, try to keep the respective symbol adjacent to the type:
// better char* myStr; float* MyMethod(const char& myParam); int* MyVar = (int*)OtherVar; void MyMethod(const std::string& myParam); // okay char *myStr; float *MyMethod(const char &myParam); int *MyVar = (int *)OtherVar; void MyMethod(const std::string &myParam); // bad char * myStr; float * MyMethod(const char & myParam); int * MyVar = (int *)OtherVar; void MyMethod(const std::string & myParam);
If there is no type, keep the symbol adjacent to the variable name:
// better char myChar, *myCharPointer, **myCharDoublePointer; // okay char myChar, * myCharPointer, ** myCharDoublePointer; // bad char myChar, * myCharPointer, * * myCharDoublePointer;
For items separated by commas, e.g. function parameters and enums, keep one space after each comma:
// good
void MyFun(int a, int b, int c);
int MyArr[3] = {1, 2, 3};
// bad
void MyFun(int a,int b,int c);
int MyArr[3] = {1,2,3};
For operators, e.g. =, + and -, keep one space on each side. Avoid using extra spaces around parentheses:
// good void i = (1 - b); void j = ((1 / b) + 5) * c; // bad void i=( 1-b ); void j=((1/b)+5)*c;
External dependencies
Do not introduce new external dependencies without good motivation. The past has proven there are quite some libraries which just suck, do not build on some platform, are too buggy, make code unreadable, etc. If you really need to add a new dependency, be sure it is cross platform, and favor dependencies that are already packages in the major distributions like Debian or Ubuntu.
When working on Linux, remember to (get someone to) compile the dependency on Windows, both for MinGW and MSVC.
Sources
(This is good material to at least skim through; the first one is a must have for every serious programmer.)
- Code complete 2 (commercial book)
- Philips Medical Systems - Coding Standard: C# (free online book)