Coding standards
More information about the coding standard Link to Github
Braces
function definitions
Function definitions should have each brace on its own line.
Right:
int main()
{
...
}
Wrong:
int main() {
...
}
class definitions
Class definitions should have each brace on its own line and the final brace should be followed by a semicolon.
Right:
class CDocumentation
{
...
};
Wrong:
class CDocumentation {
...
}
namespaces
Namespaces should have each brace on its own line and the final brace should be followed by a semicolon.
Right:
Namespace Whiptail
{
...
};
Wrong:
Namespace Whiptail {
...
}
one-line control
One-line control clauses can use braces. For a better overview use braces.
Optimal:
if (condition)
{
DoSomething();
}
Disadvantageous:
if (condition)
DoSomething();
bodyless clauses
Control clauses without a body should be avoided but when used should use an empty set of braces and not a trailing semicolon.
Right:
for (; current; current = current->next) { }
Wrong:
for (; current; current = current->next);
Comments
Seperator
The standard seperator is 90 slash characters.
Right:
//////////////////////////////////////////////////////////////////////////////////////////
Wrong:
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//----------------------------
//***********************************************************
Functions should be separated by ONE empty lines.
Right:
//////////////////////////////////////////////////////////////////////////////////////////
bool ReturnTrue()
{
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////
/// Next function description
Wrong:
///////////////////////////////////////////////////////////////////////////////////////////////////////////
bool ReturnTrue()
{
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Next function description
Comment single line
The standard is a tripple slash with one space “/// “
Mark the code
Use the following style to describe.
///\todo Mark a todo like this
///- Mark a point like this
File Naming
There will be NO spaces in any filenames or directories.
Right:
/AIAHealSupport/AIAHealSupport.cpp
Wrong:
/HealSupport Template/AI AHeal Support.cpp
Formatting
Tabs/Spaces
Use spaces, not tabs. Tabs should only appear in files that require them for semantic meaning, like Make files.
The indent size is 4 spaces.
Notepad++
Right:
int main()
{
return 0;
}
Wrong:
int main()
{
return 0;
}
indent
In a header, code inside a class should be indented.
keywords
public, private, protected and friend should be indented.
Put single blank line after those keywords!
Any friend keywords should appear at the bottom of a class definition below any other code.
Right:
class CDocumention
{
public:
Document();
...
friend class CEffectList;
Document2()
};
Wrong:
class CDocumention
{
friend class CEffectList;
public:
Document();
...
};
namespace
In a header (.hpp, .h) file, code inside a namespace should be indented.
Right:
namespace Whiptail
{
class CDocumention
{
public:
Document();
};
};
Wrong:
namespace Whiptail
{
class CDocumention
{
public:
Document();
};
};
case
A case label should be indented from its switch statement.
A case statement’s contents are indented from the case.
The colon after a case statement should have no spaces before or after it.
Right:
switch (condition)
{
case mostLikelyCondition:
case leastLikelyCondition:
i++;
break;
default:
i--;
}
Wrong:
switch (condition) {
case leastLikelyCondition:
case mostLikelyCondition:
i++;
break;
default:
i--;
}
parenthesis
Use parenthesis in complex mathmatical formulae and expressions.
It is important to make it easy for future readers of this code to visualize and modify order of operations.
Right:
pfloat32 myValue = (pV0->vx * w0) + ( pV1->vx * w1) + (pV2->vx * w2) + (pV3->vx * w3);
Wrong:
pfloat32 myValue = pV0->vx * w0 + pV1->vx * w1 + pV2->vx * w2 + pV3->vx * w3;
Use parenthesis in complex logic and conditional expressions.
It is important to make it easy for future readers of this code to visualize and modify order of operations.
Right:
if ((pAudio->pBuffer[0] == 'R') && (pAudio->pBuffer[1] == 'I') && (pAudio->pBuffer[2] == 'F') && (pAudio->pBuffer[3] == 'F'))
Wrong:
if (pAudio->pBuffer[0] == 'R' && pAudio->pBuffer[1] == 'I' && pAudio->pBuffer[2] == 'F' && pAudio->pBuffer[3] == 'F')
Line breaking
statements
Each statement should get its own line.
Right:
x++;
y++;
if (condition)
{
DoSomething();
}
Wrong:
x++; y++;
if (condition) DoSomething();
else
An else statement should go on it’s own line separate from closing and opening braces.
Right:
if (condition)
{
...
}
else
{
...
}
Wrong:
if (condition) {
...
}
else {
...
}
An else if statement should be written as an if statement when the prior if concludes with a return statement.
Right:
if (condition)
{
...
return someValue;
}
if (condition)
{
...
}
Wrong:
if (condition) {
...
return someValue;
} else if (condition) {
...
}
Names
Do not use underscores unless specified by another guideline
variable/data members
Use lowerCamelCase for public/protected variables and data members. Use an “_” before private data members.
class/struct/function/namespace
Use UpperCamelCase aka PascalCamel for a class, struct and namespace names. Use lowerCamelCase for class functions.
Right:
class Gameobject;
GameObject::setState(true);
struct CreatureData;
size_t bufferSize;
char characterDelimiter;
Wrong:
class gameobject;
gameobject::SetState(true);
struct _creature_data;
size_t buffer_size;
char Characterdelimiter;
class-/ structure data members
Prefix class and struct data members with “m_”.
Right:
class CWString
{
...
short m_length;
};
Wrong:
class CWString
{
...
short length;
};
procede boolean
Precede boolean values with words like “is”, “has” and “did”.
Right:
bool isValid;
bool didSendData;
bool hasChildren;
Wrong:
bool valid;
bool sentData;
bool children;
use full words
Use full words, for all variables except in the rare cases where an abbreviation would be more canonical and easier to understand.
Right:
size_t charSize;
size_t length;
short tabIndex;
Wrong:
size_t characterSize;
size_t len;
short tabulationIndex;
cross meaning iterator
Avoid using cross meaning iterator variable names in loops, for example do not use i,j or k as iterator variables when working on a Quaternion or x,y and z when working with a vector as these types can contain data members of the same names causing confusion.
function names
Use descriptive verbs in function names.
Right:
bool convertToASCII(short*, size_t);
Wrong:
bool toASCII(short*, size_t);
meaningless variable names
Leave meaningless variable names out of function declarations.
Right:
void setCount(size_t);
Wrong:
void SetCount(size_t count);
unused names
Comment unused variable names out of function definitions.
Right:
void CWHeap::Free(void* /*pAddr*/)
{
}
Wrong:
void CWHeap::Free(void* pAddr)
{
}
readwrite variable
Use “Get”/”Set” for readwrite variable.
Right:
size_t getCount();
...
size_t setCount();
Wrong:
size_t Count();
mutators
Precede mutators with the word “set” and should match the name of the variable being accessed.
Right:
void setCount(size_t);
Wrong:
void count(size_t);
defined
#defined constants should use all uppercase names with words separated by underscores.
Right:
#define KEY_ALT_MASK 0x04
Wrong:
#define KeyAltMask 0x04
Macros that expand to function calls or other non-constant computation. These should be named like functions, and should have parentheses at the end, even if they take no arguments (with the exception of some special macros like STD_ASSERT). Note that usually it is preferable to use an inline function in such cases instead of a macro.
Right:
#define WBStopButtonTitle() NSLocalizedString("Stop", "Stop button title")
Wrong:
#define WB_STOP_BUTTON_TITLE NSLocalizedString("Stop", "Stop button title")
#define WBStopButtontitle NSLocalizedString("Stop", "Stop button title")
“header guards” (ifndef, define, endif, pragma once)
Right:
#pragma once
// all your myfile.hpp here
Wrong:
#ifndef _GAMEOBJECT_H
#define _GAMEOBJECT_H
#endif
#ifndef _GameObject_H_
#define _GameObject_H_
#endif
Other Punctuation
initializer
Constructors for classes should initialize all of their members using C++ initializer syntax. All superclasses should be on the same line as the class name If there are superclasses (parent classes) Starting on the next line after the class name and superclass list each member with its initialization wrapping at less than or equel to 120 characters further members should be initialized starting with an indent one level past the class name. If there are no superclasses (parent classes) Starting on the same line as the class name each member should be initialized wrapping at less than or equel to 120 characters then further lines of members are indented one level past the class name. If there are are so few members and superclasses that the initialization fits under 120 characters Starting on the same line as the class name each member should be initialized. There should be more than one member on each line making it as compact as is readable without exceeding 120 characters per line including indentation The initializer list should match the order of class data members precisely
Right:
Documentation::Documentation(Document* pDoc): XMLReader(), XMLWriter(),
m_memberAlpha(0), m_memberBeta(0), m_memberGamma(0),
m_memberDelta(0), m_memberEpsilon(0), m_memberZeta(0),
{
};
XMLReader::XMLReader() : m_memberAlpha(0), m_memberBeta(0), m_memberGamma(0),
m_memberDelta(0), m_memberEpsilon(0), m_memberZeta(0),
{
};
XMLWriter::XMLWriter() : FileIO(), m_memberAlpha(0)
{
};
Wrong:
Documentation::Documentation(Document* pDoc) : XMLReader(), XMLWriter()
{
m_memberAlpha = 0;
m_memberBeta = 0;
m_memberGamma = 0;
m_memberDelta = 0;
m_memberEpsilon = 0;
m_memberZeta = 0;
}
pointer and reference
Pointer and reference types are compound types and should be written with no space between the type name and the * or & followed by spaces and or indents then the variable name.
Right:
Image* TextureHandler::DoSomething(Color& tint)
{
Color* pElement = static_cast<Color*>(node());
const ColorArray& colors = ColorInputs();
Wrong:
Image *TextureHandler::DoSomething(Color &tint)
{
Color *element = static_cast<Color *>(node());
const ColorArray &colors = ColorInputs();
inline functions
Prefer const to #define. Prefer inline functions to macros. Inline functions should be explicitly marked as inline with the inline keyword.
Right:
inline Color* GetColor() { return m_pColor; }
Wrong:
Color *GetColor() { return m_color; }
Inline functions consisting of one call or operation should occupy no more than 1 line of code and coexist inside the class definition.
Right:
inline Color* GetColor() { return m_pColor; }
Wrong:
inline Color* GetColor()
{
return m_color;
}
Inline functions that consist of more than one call or operation should be prototyped (declared) in the class definition and implementated (defined) in the same header after the class defenition. Both the prototype (declaration) and the implementation (definition) of inline functions should have the inline keyword as some compilers use one or the other or both to determine inlining rules. Implementing intentional infinite loops should be done with a for(;;).
Right:
for (;;)
{
...
}
Wrong:
while (true)
{
...
}
while (1)
{
...
}
enums
Enumerations should always be named so they can be used as type safe parameters.
Right:
enum EWTypes
{
...
}
Wrong:
enum
{
...
}
const
not modified objects
If the object you are calling a function on, is not going to be modified durring the functions scope, the function should ALWAYS have the const modifier on the end.
Right:
unsigned int GetSize() const { return m_size; }
unsigned int SetSize(unsigned int size) { m_size = size; }
Wrong:
unsigned int GetSize() { return m_size; }
unsigned SetSize(unsigned int size) const { m_size = size; }
pointer passing
When passing pointers or references to items as function paramaters, and the item being passed should not change, you should mark the parameter as const.
Right:
void Print(const char* pString); // pString is not modified
void ModifyString(char* pString); // pString may be modified
void ScanObject(const CObject& obj); // obj is not modified
void ModifyObject(CObject& obj); // obj may be modified
Wrong:
void Print(char* pString);
void ModifyString(const char* pString);
void ScanObject(CObject& obj)
void ModifyObject(const CObject& obj);
There is some times confusion on where the const modifier goes when passing parameters, if you dont want the parameter being pointed/referenced to be modifiable do this.
Right:
const CObject* pObj
Wrong:
CObject\* const pObj
If however you do not care if the object being pointed to is modifiable, but want to verify the pointer itself never changes, you do the opposite.
Right:
CObject* const pObj
Wrong:
const CObject* pObj
structures
Structs cannot have any member functions they are reserved for data members only.
Right:
struct SWEntityData
{
unsigned int m_id; ///< Comment
unsigned int m_info; ///< Comment
}
Wrong:
struct SWEntityData
{unsigned int m_id; ///< Comment
unsigned int m_info; ///< Comment
/// Get ID
unsigned int GetID() { return m_id; }
/// Set ID
void SetID(unsigned int id) { m_id = id; }
}
Spacing
operators
binary
Do place spaces around binary operators
Right:
y = m * x + b / n;
f(a, b);
c = a | b;
Wrong:
y=m*x+b/n;
f(a,b);
c = a|b;
ternary
Do place spaces around ternary operators
Right:
return condition ? 1 : 0;
Wrong:
return condition ? 1:0;
control statements
Do Place spaces between control statements and their parentheses.
Right:
if (condition)
Wrong:
if(condition)
functions parameters
Do Place spaces between each of a functions parameters.
Right:
f(a, b, c, d);
Wrong:
f(a,b,c,d);
Do not place spaces between a function and its parentheses, or between a parenthesis and its content.
Right:
f(a, b);
Wrong:
f (a, b);
f( a, b );
Types & Values
null pointer
The null pointer value should be never written as NULL/0.
Use nullptr!
CWEntity* pEntity;
Right:
pEntity = nullptr;
Wrong:
pEntity = 0;
bool values
bool values should be written as true and false.
bool isValid;
Right:
isValid = true;
Wrong:
isValid = 1;
Do not use the Objective-C style BOOL type.
Right:
bool isValid;
Wrong:
BOOL isValid;
tests
Tests for true/false and zero/non-zero should all be done without equality comparisons.
Right:
if (bCondition)
Wrong:
if (bCondition == true)
explicit init
Do not add explicit initializations to temporary variables if you assign to them before testing their value.
Right:
bool bTest;
...
bTest = GetStatus();
Wrong:
bool bTest = true;
...
bTest = GetStatus();