Coding standards

More information about the coding standard github.svg 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++

Notepad_1.png

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();