Code Style Guide

From Arx Libertatis Wiki
Jump to navigation Jump to search

This page describes the style used for Arx Libertatis source code. New contributions should try to follow this guide, even if much of the existing code doesn't. However, nothing described here are is a strict rule and

Example

(WIP!)

src/somedir/SomeClass.h:

>/*
 * Copyright notice(s) ...
 */

#ifndef ARX_SOMEDIR_SOMECLASS_H
#define ARX_SOMEDIR_SOMECLASS_H

namespace somens {

//! Short documentation comment
void someFunction();

class SomeClass {
	
public:
 	
	/*!
	 * Longer documentation comment
	 *
	 * @param functionParameter Some parameter...
	 *
	 * @return some value.
	 */
	int memberFunction(int functionParameter);
	
	int m_memberVariable;
	
	static int s_staticMemberVariable;
	
};

extern int g_globalVariable;

} // namespace somens

#endif // ARX_SOMEDIR_SOMECLASS_H

src/somedir/SomeClass.cpp:

#include "somedir/SomeClass.h"

namespace somens {

int g_globalVariable = 0;

int SomeClass::s_staticMemberVariable = 0;

int SomeClass::memberFunction(int functionParameter) {
	
	int localVariable = functionParameter;
	
	someFunction();
	
	return localVariable + m_memberVariable;
}

} // namespace somens


if(foo) {
	a = Template:Text;
	i++;
} else if(bar) {
	a = Template:Text;
	j++;
} else {
	a = Template:Text;
	k++;
}
if(foo)
	bar = 1;
if(   x >= min.x
   && x <= max.x
   && z >= min.z
   && z <= max.z
   && !(type & (FLAG_A | FLAG_B | FLAG_C))
   && foo
) {
	bar = 1;
}
switch(bar) {
	case 0: {
		++bar;
		break;
	}
	case 1: {
		--bar;
		break;
	}
	default: {
		bar += bar;
		break;
	}
}
switch(bar) {
	case 0:  ++bar;      break;
	case 1:  --bar;      break;
	default: bar += bar; break;
}
for(int i = 0; i < 10; i++) {
	// do stuff
}
while(condition) {
	// ...
}
do {
	// ...
} while(condition);
try {
	number = boost::lexical_cast<long>(string);
} catch(...) {
	number = -1;
}

Note: C++-style static_cast etc. are usually preferred.

char * s = (char *)object;
class Point {
 	
public:
 	
	Point(Template:Real x, Template:Real y)
		: x(x)
		, y(y)
	{
		// ...
	}
 	
private:
 	
	Template:Real x;
	Template:Real y;
 	
};

Symbol Names

Symbol names use variants of Template:Wp.

Classes

Classes and structs use camel case names and start with an upper case letter:

struct SomeType;

TODO: what about typedefs?

Functions

Function names are also camel case, but start with a lowercase letter:

void someFunction();

Member functions

Member functions are also just functions - there is no need for a different visual style.

Variables

TODO: note on no hungarian notation

Local variables

Local (function-scope) variables use camel case names with a lower-case start:

int localVariable = 0;

Function parameters

Function parameters are local variables, so they should follow the same naming scheme.

Member variables

Member variables should be named just like local variables, but with an added m_ prefix:

class SomeClass {
	int m_someVariable;
};

The prefix makes it easy to distinguish local variables from those with a longer lifetime.

Static member variables

Static member variables should be named just like local variables, but with an added s_ prefix:

class SomeClass {
	static int s_someVariable;
};

The prefix makes it easy to distinguish local variables from those with a longer lifetime.

Static function-scope variables

No special formatting rules are necessary.

Global variables

... should be avoided if possible! But for the cases where they are needed, they should be named just like local variables, but with an added g_ prefix:

int g_someVariable = 0;

The prefix makes it easy to distinguish local variables from those with a longer lifetime.

Namespaces

Namespace names should be lowercase and as short as possible.

If the namespace block contains more than a few lines, consider repeating the namespace keyword and name at the end:

namespace ns {

// ...

} // namespace ns

Low-level symbols

Low-level classes and their member functions and variables (container, path, ...) use C++-stdlib-style lowercase names with underscores. This is so that they visually fit in with other lower-level symbols from the C++ stdlib and Boost.

Formatting

Line length

Indentation

Use a single tab character for each indentation level. This allows everyone to choose their own indentation with by configuring their editor.

Also indent "empty" lines according to the indentation of adjacent lines.

if(...) {
	
	// ...
	
}

Alignment

Always uses spaces for alignment, never tabs:

if(...) {
	
	function(arg, arg, arg,
	         arg, arg);
	
}

Line breaks

Other whitespace

#includes

Syntax

For system and library includes, use angle brackets:

#include <header>

For our own includes use quotes and include the full path below the src directory:

#include "subsystem/File.h"

Order

  1. First include should be the header corresponding to the current source file
  2. Then come standard C/C++ includes
  3. After that, other system includes (<unistd>, etc.)
  4. Next, library includes
  5. Finally, includes for our own header files

There should be an empty line between each of these groups of includes. More empty lines may be added to aid readability (but if that is needed, consider splitting the source file to reduce the number of includes).

Within each group, #includes should be sorted semi-lexicographically: Within each path hierarchy, entries are sorted lexicographically, except that all files always come before subdirectories.

Example (subsystem/File.cpp):

#include "subsystem/File.h"

#include <string>
#include <vector>

#include <boost/foreach.hpp>

#include "a/Header.h"
#include "a/another/Header.h"
#include "b/Header.h"

Documentation

Other notes

using namespace statements

... should be avoided. Use namespace aliases instead:

namespace a = b::c::d;

However, try to use a meaningful alias. If possible, consistent aliases should be used in different files for the same source namespace.

other using statements

... are also usually best avoided. There are of course exceptions (for example to invoke ADR with std::swap), but leaving the namespace prefix where the symbol is used makes it easier to tell where the symbol comes from.

#include guards