Last modified 8 months ago Last modified on 10/05/11 13:27:17

Coding Style

Preamble

We are trying to follow the coding style that is predominant in the old Warzone code. Please use this style in your patches.

This means your code should look like this (note spaces, braces and line endings):

void functionName(const char *variableName, int *anotherVar, STRUCTURE *psStruct)
{
        if (variableName == NULL)
        {
                *anotherVar = 1 + 2 * (5 / 2);
        }
        else
        {
                *anotherVar = 1 + 2 * (atoi(variableName) / 2);
        }
}

Indentation for scope should use tabs, while indentation for lining up wrapped lines should use tabs to align with the start of previous line, then spaces. This way the code will look readable with any tab size. For example, when a line with a two-line printf begins, use tab to indent it, then use tab then spaces to indent the following line, like this (\t for tabs):

\t\tprintf("some text on this line that got long, "
\t\t       "some more text on the next line");

We follow the C++ standard since we want the code to be compilable with C++ compilers:

  #define VARIADIC_PRINT(...) do { printf(__VA_ARGS__); } while(0)
  // I'm a C99 comment! I'm lucky to be in Warzone 2100!
  /* I'm an old fashioned C89 comment, still pretty useful.. */

More things to do:

  • Avoid some reserved C++ keywords:
    • try, catch, throw
    • typeid
    • and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq
  • Comment always why you do something if this is not obvious.
  • Comment how you do it if it may be difficult to follow.
  • Do not comment out code you want to remove (just remove it, Subversion can always get it back).
  • Always add braces following conditionals (if).
  • Put curly braces on lines of their own
  • Use C99 fixed size types (uint32_t etc.) only where necessary. Otherwise use usual C types (int etc.).
  • Don't use Pumpkin's legacy types (UDWORD etc.) in new code!

Make sure your patch does not add any new compiler warnings.

Commenting and doxygen documentation

We are implementing a doxygen documentation on the code, which can be accessed here. To the documentation be congruent, the following style is being used:

  • use the following header after the license:
    /**
     *
     * @file
     * File description
     *
     */
    
  • Use javaDoc style:
    /** I'm a single line comment, commenting something.*/
    
    /**< I'm an inline comment, commenting something like struct/class members.*/
    
    /**
     *  I'm a multi line comment, commenting some struct/class or some function.
     */
    
  • if documenting a header file (.h), the following style is used (order.h example)
/** Retreat positions for the players. This is a global instance of RUN_DATA.*/
extern RUN_DATA asRunData[MAX_PLAYERS];

/** \brief Gives the droid an order.*/
extern void orderDroidBase(DROID *psDroid, DROID_ORDER_DATA *psOrder);

/** \brief Initializes the global instance of RUN_DATA.*/
extern void initRunData(void);
  • use \brief on the functions to tell that this is a small description of the function (is describing its interface).
  • don't make too long descriptions, as they are meant only to be brief.
  • only describe parameters that are not obvious, or aren't obvious when the function is called (bools are some important examples).
  • use one line to separate the comment from the previous declaration.
  • If documenting a source (.cpp) file, the following style should used (order.cpp example):
/** This function compares the current droid's order to the order.
 * Returns true if they are the same, false else.
 */
bool orderState(DROID *psDroid, DROID_ORDER order)
{...}

/** This function returns true if the order is an acceptable order to give for a given location on the map.*/
bool validOrderForLoc(DROID_ORDER order)
{...}
  • the documentation on the source is meant to the reader understands what the function does on the implementation point of view.
  • you don't need to strictly tell what the function's arguments mean.
  • use two lines separation between the comment and the previous function implementation.
  • don't doxygen document comments about specific code inside the implementation, as they are to be read along with code.

You can find documentation examples on order.h, order.cpp and orderdef.h.

GNU Indent

For gnu indent, you can use the following switches:

indent --dont-break-procedure-type --no-space-after-function-call-names --use-tabs --tab-size4 -i4 --brace-indent0 --line-length120 <files>

Artistic Style

For astyle, save the following as "astyle":

suffix=none
indent=tab
brackets=break
indent-switches
pad=oper
unpad=paren
min-conditional-indent=0
mode=c
indent-preprocessor
one-line=keep-statements
max-instatement-indent=8

and call astyle like:

astyle --options=astyle <files>

C++

For C++ code, keep the following in mind:

  • Try to follow http://doc.trolltech.com/qq/qq13-apis.html when designing interfaces
  • Try to avoid changing a ton of code when porting something to c++
  • Do not rewrite code to C++ just to rewrite stuff to C++
  • Avoid templates like the plague. Unless to avoid a worse plague.
  • Avoid exceptions at all costs. No exceptions.
  • Avoid redundant inheritance redundancy. Abstract classes and pure virtuals are best abstracted away.
  • Debugging code is harder than writing code. So if you are writing code as cleverly as possible, you are by definition too stupid to debug it. Avoid this. (This is easier with C++ code, but also holds for C.)

Discussion points:

  • Read http://qt.gitorious.org/qt/pages/CodingConventions as most of this applies to us as well
  • Once Qt branch is merged: Use Qt classes instead of std:: classes whenever possible.
  • Use smart pointers smart. That means do not overuse them. They are no substitute for thinking.