Coding Guidelines

From Mumble Wiki
Revision as of 23:53, 21 August 2014 by DD0T (talk | contribs) (Mention QT_VERSION_CHECK)
Jump to: navigation, search

General

Much of the Mumble codebase does not yet follow these new code guidelines. However if your write new code or adjust existing code make sure to follow them so we can reach a consistent style as soon as possible.

  • The Qt coding conventions mostly apply
  • Every source file should contain a license header
  • Lines should generally be no longer than 100 characters
  • Use newlines for logical grouping
  • Try to be standards (C++03) compliant and const correct
  • When interfacing with system code feel free to locally use the coding style recommended for that system
  • Consistency is important but these are no laws. Use your own judgement.

Indentation

  • Use tabs for indenting and space for lining up code.
    • This means using tabs only at the beginning of lines. Otherwise users cannot set their own tabstop without breaking formatting
  • Never indent preprocessor commands controlling control flow (e.g. #ifdef, #endif,...)

Headers

  • Include guards should use MUMBLE_PATH_FILENAME_H_ to prevent ambiguity. E.g. for the file MainWindow.h in src/mumble:
#ifndef MUMBLE_MUMBLE_MAINWINDOW_H_
#define MUMBLE_MUMBLE_MAINWINDOW_H_
...
#endif
  • Don't use non-standard #pragma once
  • Try to use forward declarations where possible to reduce coupling

Naming

  • Don't abbreviate names.
  • Good naming is essential for code maintainability. Treat it accordingly.

Classes

  • Use CamelCase names.

Member functions

  • Arguments as well as function names should be camelCase
Type camelCase(Type camelCase);
  • Getters should be prefixed with get/is/has, be constant and name the variable they return
Type getVariable() const;
/// Or for boolean
bool isVariable() const;
/// or
bool hasVariable() const;
  • Setters should be prefixed with set and efficiently handle their argument
void setVariable(const Type& variable);

Qt Slots

  • Use an "on" prefix onSomethingHappening() for manually wired slots
  • Feel free to use Qt auto-wire where possible (e.g. on_qpbRemove_clicked())

Member variables

m_ and s_ prefix

  • m_camelCase for member variables
  • s_camelCase for static member variables

Constants

  • Use ALL_CAPS with underscore as a seperator for global, file global, static const member variables and static const local variables.
  • Non-static but const local variables are not capitalized, but formatted just like normal variables.
static const int GLOBAL_SVAR;

void fu() {
    static const int LOCAL_SVAR = 4;
    const int localVar = 5 + bla();
}

class bar {
    static const int MEMBER_SVAR;
    const int memberVar;
};

Types

  • Use CamelCase for type names
class MyClass {};
typedef MyClass AlternativeClassName;
enum MyEnum {};

Enums

  • Use CamelCase for enumeration types
  • For disambiguation and improved auto-completion use a unique prefix for the enum variables. Prefer the capital letters in the CamelCase name if possible.
enum CamelCase {CC_FIRST, CC_SECOND, CC_THIRD};
  • If you need an end marker for an enumeration prefer COUNT_PREFIX
  • If the enumeration values need explanation use multiple lines
enum CamelCaseToo {
    /// First camel in the case
    CCT_FIRST,
    COUNT_CCT
};

Code style

if statements

if (a > b
    || b > c
    || c > d) {
    doSomething();
} else {
    doSomethingElse();
}
  • Split up long if statements at operators. Place the operators at the beginning of the new line instead of at the end.
  • Try to keep the logic in if statements understandable. E.g. use additional named variables or split one if statement into multiple statements if it makes the code more readable.
  • Always use { } unless there is no chance of misinterpreting the statement (e.g. returns)
if (thingy)
    return stuff;

Classes (e.g. a QObject based class)

  • Access specifiers should always be ordered public, public slots, signals, protected, private
  • QObject derived classes must have a Q_OBJECT statement to ensure signal/slot is working
  • Constructors with only one argument must be marked explicit
/// Class for managing things by foo.
class MyClass : public QObject {
        Q_OBJECT
    public:
        /// Constructs MyClass without initializing foo management
        explicit MyClass(QObject *parent = NULL);
        /// Constructs MyClass for managing initialFooCount of foos
        MyClass(int initialFooCount, QObject *parent = NULL);
        ...
    public slots:
        ...
    signals:
        ...
    protected:
        ...
    private:
        /// Stores the number of foos since the last reset
        int m_fooCount;
};
  • Constructor implementations
MyClass::MyClass(int initialFooCount, QObject *parent)
    : QObject(parent)
    , m_fooCount(initialFooCount) {

    doStuff();
};

Switch

  • Each case/default must have a break or a return. Fall throughs must be explicitly commented.
switch (foo) {
    case A:
         ...
         break;
    case B:
    case C:
         ...
         // Fall through
    default:
         break;
}

Comments

Try to use comments in a sensible way. Don't comment the obvious (e.g. no setBla() "Sets bla") and don't feel obligated to comment every single parameter and function if the variable naming and types already make the behavior obvious.

  • Comment intent over behavior
  • When in doubt err on the side of to much comments
  • Make sure you always keep related comments up to date when changing code

Classes / Functions

  • Comment in header / at point of declaration
  • Use doxygen style comments
    • We use auto-brief style so your first sentence will be used like it was prefixed with @brief. Be sure to finish the first sentence with a '.'.
/// Use this for single line comments
int foo;

/// Use this also for big comments.
///
/// @param parameter Takes param in meters
/// @return parameter in feet on success. A value < 0 on failure.
int bar(int param);
  • Place comments directly above the code they are referring to. Don't place them in the same line.

Specifics

Special guidelines for specific situations one should be aware of.

Qt backwards compatibility

Mumble has to be compatible with Qt 4 as well as Qt 5. For that reason there will be situations where you'll want to have different code based on version.

#if QT_VERSION > 0x500000
    // Qt 5 code goes here
#else
    // Qt 4 code
#endif

Avoid using the QT_VERSION_CHECK macro and always specify the wanted version explicitely. It cannot be expanded by Qt4's moc and hence can lead to invalid code.