Workspace  6.13.4
Coding Standard

Introduction

This document describes the coding standard used by the Workspace developers. It reflects the desired style and conventions to be used throughout the Workspace code base. Older code may not yet adhere to the advice given here, so such cases should be brought into compliance as developers encounter them where practical. For the most part, this standard addresses C and C++ code, but some items are applicable more broadly to other languages, tools or formats used or supported by the build system.

We welcome other groups adopting these coding standards for their own work. In particular, we encourage Workspace plugin developers to consider following these conventions so that others using their work will have a certain level of familiarity with the overall style.

General
Names
Headers
Comments
Formatting
Implementation

References


General

Spelling conventions


Names

Namespaces and classes

Correct Incorrect
SomeProgClass Some_Prog_Class
someProgClass
Someprogclass
VtkWriter VTKWriter
Application APPLICATION
Correct Incorrect
rectangle_ rectangle
executionMode_ executionMode
ExecutionMode
execution_mode

Functions and macros

Note
It is meaningless as far as the function signature is concerned to have a const specifier on a function parameter passed by value. The compiler silently ignores it when matching calls to the function.
Correct Incorrect
getBigThings() GetBigThings()
get_big_things()
getbigthings()
GETBIGTHINGS()
getBigThings(int key, QString value) getBigThings(int, QString)
getBigThings(int numItems) getBigThings(int n)
getBigThings(double* ptr) getBigThings(double *ptr)
getBigThings(int numItems) getBigThings(const int numItems)

Variables

Note
For an explanation of the differences between the various const pointer types, see the C++ FAQ at http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.5

Enums

The rules for enums are the same as for class names. This applies to both the enum name (ie its type identifier) and to the names of its values (ie its enumerators).

Typedefs and other types

The rules for typedefs are the same as those of the entity they are typedef'ing. For example, a typdef for a class should conform to class name rules.

XML tags

The rules for XML tags are the same as for class names, except that all characters should be in lowercase.

File system

This section covers naming items in the file system within the source tree. It is not necessarily meant to be applied to files created or used by the software at run-time, although the rules specified here would often be a useful guideline.

Directories

Files

Correct Incorrect
somesourcefile.cpp some_source_file.cpp
someSourceFile.cpp
file1.cpp 1file.cpp
file_1.cpp
test_foobar.cpp testfoobar.cpp
foobar_test.cpp
foobartest.cpp
foobar_win32.cpp
foobar_mac.cpp
foobar_linux.cpp
foobarwin32.cpp
mac_foobar.cpp
foobar-linux.cpp
File Type Extension
C source .c
C++ source .cpp
C/C++ header .h
C/C++ source with doxygen comments only .dox
Qt Designer UI file .ui
Qt resource file .qrc
HTML source .html
JPEG image .jpg

Tests

Correct Incorrect
test_foobar.cpp testfoobar.cpp
foobar_test.cpp
foobartest.cpp

Pre-processor defines


Headers

Header guards

The standard form of a header guard is as follows:

// Copyright header would be included first....

#ifndef CSIRO_GUMBY_FOOBAR_H
#define CSIRO_GUMBY_FOOBAR_H

namespace CSIRO
{
namespace Gumby
{
    class FooBar
    {
        // ...
    };
}}

#endif

Forward declarations

In header files, use forward declarations rather than a full #include if:

Header ordering and placement

Using directives

Do not put a using directive in a header file other than for one of the following cases:

Self-sufficiency


Comments

Copyright notices

The standard notice used for all Workspace code is the following:

============================================================================


  Copyright 2022 by:

    Commonwealth Scientific and Industrial Research Organisation (CSIRO)

    This file is licensed by CSIRO under the copy of the CSIRO Binary
    License Agreement included with the file when downloaded or obtained
    from CSIRO (including any Supplementary License).  If no copy was
    included, you must obtain a new copy of the Software from CSIRO before
    any use is permitted.

    For further information, contact: workspace@csiro.au

  This copyright notice must be included with all copies of the source code.

============================================================================

Doxygen comments

Classes

/**
 * \brief Implements a specific magic trick
 *
 * This class does all sorts of interesting things.
 * Most of it is magic, some is just pure genius.
 *
 * \relates PerformMagic
 */
class MagicTrick
{
    // Contents of the public class
};


/**
 * \brief Example of a template class
 *
 * \tparam TrickT Specifies the type of trick the class defines
 */
template<typename TrickT>
class PerformTrick
{
    // Contents of the public class
};


/**
 * \internal
 */
class HiddenSecret
{
    // Move along, nothing to see here...
};

Functions

    // ... end of previous function
}


/**
 * \param xFactor  Some value that does extra special things.
 * \param required Switch specifying whether we want to use the \a xFactor.
 *
 * This function does some magical computation. It uses \a xFactor
 * only when \a required is \c true. Otherwise, it uses some other value.
 *
 * \return The magic factor, or pi if you are hungry.
 *
 * \sa foolGeneralPublic()
 */
double  computeMagic(double xFactor, bool required)
{
    // ....
}

Enums

/**
 * Specifies what sort of magic tricks can be requested.
 */
enum SupportedMagicTricks
{
    SleightOfHand,    //!< Standard magician's trick
    Misdirection,     /*!< This can be a bit more involved which
                           is why its description is longer */
    GrandIllusion     //!< Not going to spoil the surprise!
};

Variables

Note
Variables are not normally made accessible directly in public classes and global variables are to be avoided, so most variables will be private implementation details. As such, variables do not generally need to be documented unless the developer wants to make some non-obvious detail clear. A common example would be to document some assumption about how the variable is used.

Formatting

Defining variables

Correct Incorrect
int varOne;
int varTwo;
int varOne, varTwo;
int* varOne;
int& varTwo = ...;
int *varOne;
int &varTwo = ...;

Virtual, Final and Override qualifiers

#include <iostream>

class BaseClass
{
public:
    virtual bool virtualMethod() const = 0;
};

class DerivedClassOne : public BaseClass
{
public:
    void virtualMethod() const override
    {
        std::cout << "This implementation is a non-final override." << std::endl;
    }

    virtual newVirtualMethod() const
    {
        std::cout << "This implementation is a new virtual method." << std::endl;
    }
};

class DerivedClassTwo : public BaseClass
{
public:
    void virtualMethod() const final
    {
        std::cout << "This implementation is a final override." << std::endl;
    }
};

Placement of curly braces

Correct Incorrect
if (someExpression == true)
{
    // Do something
}
if (someExpression == true) {
    // Do something
}
Within a class definition only...
int getFoobar() const { return foobar_; }

if (someExpression == true) { doSomething(); }

Constructors

Correct Incorrect
Foo::Foo(int a, int b) : a_(a), b_(b) {} Foo::Foo(int a, int b) : // Something really long... ;)
Foo::Foo(int a, int b) :
    a_(a),
    b_(b)
{
}
Foo::Foo(int a, int b)
    :
    a_(a),
    b_(b)
{
}

Foo::Foo(int a, int b) :
      a_(a)
    , b_(b)
{
}

Indentation

The indentation guidelines are best shown by example:

/**
 * \brief Main outer namespace
 */
namespace A
{

/**
 * \brief Inner namespace for fun toys
 *
 * To avoid excessive indenting, don't indent inner namespaces ....
 */
namespace B
{
    // .... unless it is an anonymous or private namespace, in which
    // case you can indent it or not depending on your own preference
    namespace
    {
        // ...
    }

    /**
     * \brief Does nothing interesting
     */
    class Foo : public JustOneBase
    {
        // ...
    };


    /**
     * \brief Does some more interesting things
     */
    class Bar :
        public BaseOne,    // Indent multi-line base classes
        public BaseTwo
    {
        double  var1_;

    // Access specifiers have same indentation as the class keyword
    public:
        Bar();

        int getCrazyValue(int b);

        /**
         * \brief Inner class for interesting stuff
         */
        class Nested
        {
            // ... Same rules as for regular non-nested classes
        }

        /**
         * Toys for the adrenalin junky
         */
        enum CoolThings
        {
            Snowboards,   //!< For cold weather only
            DrumKits      //!< Use when neighbours are away
        };
    };


    /**
     * \param b Mystery switch
     *
     * \return A crazy value of little use.
     */
    int Bar::getCrazyValue(int b)
    {
        int a = 1;
        for (int i = 0; i != 20; ++i)
        {              // Don't indent curly braces....
            a += i;    // ... only indent the stuff within the braces
        }

        switch (b)
        {
        case 7:        // Don't indent the case keywords ...
            a += 42;   // ... but do indent the case body
            break;
        case 2:
            a -= 27;
            break;
        default:
            a += b;
        }

        return a;
    }
}}

Implementation

The following are a set of implementation guidelines not already covered by preceding sections. They are designed to provide some consistency in coding style and to avoid common programming pitfalls or suboptimal code. Many of these are discussed in more detail in the excellent book "C++ Coding Standards", by Herb Sutter.

Interfaces

Note
The reason for excluding STL in the public API or headers is to allow clients to switch to a different STL implementation (eg STLPort). It may also be necessary on some platforms to ensure binary compatibility.

Signals and slots

The following are in addition to the rules for ordinary member functions:

Exceptions

See Scott Meyers' book "More Effective C++" for further good advice on exceptions.

Logging

Auto

Loops

C++ language


References

The following are some references that have had a strong influence on the Workspace source code, both in terms of style and implementation. They are highly recommended for anyone interested in C++ development in general.