NCCA Coding Standard Code Layout
Indentation, Braces, and Spacing
Tabs size should be set to 2. The indentation standard is designed for ease of reading. Braces should be on an otherwise empty line. Any section bracketed by { and } should be indented as follows
if( blah )
{
//
// some code here
//
}
The only exception to this rule is when functions are defined inside class definitions, such as the get and set function examples below
class TempClass
{
protected:
int m_number;
public:
int number() const { return m_number; }
void setNumber( int const _number ) { m_number = _number; }
};
Terms within a conditional expression should be separated by spaces, and, where necessary, split across multiple lines to improve readability.
We don’t want:
if(blk->size+rover->size-size>=sizeof(FreeBlock)||((char*)blk+blk->size==(char*)rover&&blk->size+rover->size>=size))))
We do want:
if( blk->size + rover->size - size >= sizeof( FreeBlock ) ||
( (char*)blk + blk->size == (char*)rover && blk->size + rover->size >= size )
)
Conditional Code
Conditional code within a function block should be indented in the same way as a normal if block, with ‘{}’ scoping brackets used to enclose the internals. Where the conditional block is more than a few lines long, the #else and #endif directives should be commented with the corresponding #if condition.
For Example:
m_dataSize = _nbrColours * sizeof(ftColour);
#if DARWIN
{
m_dataSize = ((_nbrColours + 31) & ~31) * sizeof(ftColour);
m_dataSize = ((m_dataSize + 63)& ~63);
...more code...
}
#endif // DARWIN
m_dataSize += m_platformHeaderSize;
Outside of a function block, the #if should be indented to be consistent with the surrounding code, with the internals indented by a single 2-space tab.
Get and Set functions
It is common for a class to have functions to access and adjust an object’s members. These use the Qt convention for naming where the accessor is the same name as the attribute and the mutator is prefixed with set…
class TempClass
{
protected:
int m_number;
public:
int number() const { return m_number; }
void setNumber( int const _number ) { m_number = _number; }
};
Accessors and other read-only functions should always be defined using the const modifier.
In general a class should not have exposed member variables. Hide them and provide accessor and mutator methods instead, exceptions are for example attributes in math elements such as Vec3 and Mat4.
Conditionals
- Use the { and } whether they are needed or not. It stops the possibilities of program flow bugs being introduced by adding an extra line of code into what you think is an ‘if’, where in fact it isn’t.
- Brackets should be placed on a line by themselves, and indented in line with their if or else statement, unless the readability of the code can be increased by arranging consecutive conditionals in columns. In this case, the brackets may be placed on the same line as the if statement.
Example:
We don’t want this :
if ( condition )
do something;
else {
do something line one;
do something line two;
}
We do want :
if ( condition )
{
do something;
}
else
{
do something line one;
do something line two;
}
and this
if( condition1 ) { do something1 }
if( condition2 ) { do something2 }
if( condition3 ) { do something3 }
In the final case, the code must be arranged into columns to aid readability.
Switch statements
- Switch statements should be formatted with the brackets indented underneath the switch statement, and the case statements indented underneath.
- Each case statement should use { }, indented in line with their case statement.
- Where used, break statements should be placed inside the scoping brackets.
- Always use a default case that at least asserts, unless you’re expecting values that should not be caught by the switch.
As with conditionals, the switch statement may also be arranged in columns where this will improve the readability of the code.
Examples:
We don’t want this :
switch( var )
{
case condition1:
do something1
break;
case condition2:
do something2
break;
case condition3:
do something3
}
We do want this:
switch( var )
{
case condition1:
{
do something1
break;
}
case condition2:
{
do something2
break;
}
case condition3:
{
do something3
break;
}
default:
{
.. Some debug assert
break;
}
}
or this :
switch( var )
{
case condition1: { do something1; break; }
case condition2: { do something2; break; }
case condition3: { do something3; break; }
default: { DebugAssert; break; }
}
For loops
All modern compilers should correctly implement standard scoping for variables declared in the for() statement. This means that any iterator not used outside the scope of the loop should be declared within it.
Use :
for(int i=0; i<10; ++i)
{
doStuff(i);
}
for(int i=0; i<10; ++i)
{
doMoreStuff(i);
}
Rather than :
int i;
for(i=0; i<10; i++)
{
doStuff(i);
}
for(i=0; i<10; i++)
{
doMoreStuff(i);
}