dtk coding style

Introduction

This document describes the recommended coding style for dtk. This style is not mandatory, but to have consistent formatting of the source code files it is recommended to make use of it.

dtk coding style follows the Qt coding style, with few differences desribed here after.

Rules

Indentation

  • 4 spaces
  • no tab

Variable declaration

  • Declare each variable on a separate line
  • Avoid abbreviations and meaningless names (e.g. "a", "rabarr", "toto")
  • Take useful names. No short names, except:
    • single character variable names can denote counters and
    • temporary variables whose purpose is obvious.
  • Variable name are lower case and each part of the name is separated with underscore.
  • Functions, methods and classes start with lower-case letter. Each consecutive word in their names start with an upper-case letter.
  • typedef and acronyms are camel-cased (e.g. dtkMesherCgal rather than dtkMesherCGAL)

Examples:

// wrong
dtkSparseSolver *ss;
dtkSparseMatrix *mtx;

// correct
dtkSparseSolver *sparse_solver;
dtkSparseMatrix *sparse_matrix;

Member variables

  • When using a d-pointer, the member variable declaration follows the above rules.
  • When variables are declared directly as member of a class, their name is asked to start with the prefix m_

Examples:

// wrong
class dtkConcreteDummy
{
private:
    int    _counter;
    double value_;
};

// correct
class dtkConcreteDummy
{
private:
    int    m_counter;
    double m_value;
};

Member methods

  • Setter methods start with the prefix ‘set’ in lower case.
  • The getter methods do not start with ‘get’.
  • When argument list is empty, the keyword void is used.
  • Users are asked to group setter and getter methods in a consistent way by using public keyword as separator.

Examples:

// wrong
class dtkConcreteDummy
{
public:
    void SetCounter(int counter);
    double getValue();
};

// correct
class dtkConcreteDummy
{
public:
    void setCounter(int counter);

public:
    double value(void);
};

Whitespaces

  • Use blank lines to group statements together
  • Always use only one blank line
  • Always use a single space after a keyword and before a curly brace:
// wrong
if(foo){
}

// correct
if (foo) {
}
  • For pointers always use a single space between the type and the pointer symbol * but no space between * and the variable name
  • For references, use no space between the type and the reference symbol & but always a single space between & and the variable name
// wrong
char* my_char;
const QString &my_string;

// correct
char *my_char;
const QString& my_string;
  • Surround binary operators with spaces
// wrong
for (int i=0;i<N;++i) {
    dtkDebug() << i;
}

// correct
for (int i = 0; i < N; ++i) {
    dtkDebug() << i;
}
  • No space after a cast
  • Avoid C-style casts when possible
// wrong
char *block_of_memory = (char*) malloc(data.size());

// correct
char *block_of_memory = reinterpret_cast<char *>(malloc(data.size()));
  • Do not put multiple statements on one line
  • By extension, use a new line for the body of a control flow statement:
// wrong
if (foo) bar();

// correct
if (foo) {
    bar();
}

Braces

  • As a base rule, the left curly brace goes on the same line as the start of the statement.
// wrong
if (true)
{
}
else
{
}

// correct
if (true) {
} else {
}
  • The rule differs for function implementations, class, struct and namespace declarations. In this case, the opening brace always starts on a line.
static void foo(int g)
{
    dtkDebug() << "foo: " << g;
}

class dtkAbstractConcept
{
};
  • Use curly braces even when the body of a conditional statement contains only one line.

Example:

// wrong
if (true)
    return true;

for (int i = 0; i < 10; ++i)
    dtkDebug() << i;

// correct
if (true) {
    return true;
}

for (int i = 0; i < 10; ++i) {
    dtkDebug() << i;
}

Parenthesis

  • Use parentheses to group expressions:
// wrong
if (a && b || c)

// correct
if ((a && b) || c)

// wrong
a + b & c

// correct
(a + b) & c

Switch statements

  • The case labels are in the same column as the switch
  • Every case must have a break (or return) statement at the end or a comment to indicate that there’s intentionally no break, unless another case follows immediately.
switch (myEnum) {
case Value1:
    doSomething();
    break;
case Value2:
case Value3:
    doSomethingElse();
    // fall through
default:
    defaultHandling();
    break;
}

Jump statements

  • Do not put else after jump statements
// Wrong
if (this_or_that) {
    return;
} else {
    somethingElse();
}

// Correct
if (this_or_that) {
    return;
}
somethingElse();

Line breaks

  • Line size is not limited provided the code is readable.
  • When breaking a line, commas go at the end of wrapped lines; operators start at the beginning of the new lines. An operator at the end of the line is easy to miss if the editor is too narrow.
// Wrong
if (long_expression +
    other_long_expression +
    another_long_expression) {
}

// Correct
if (long_expression
    + other_long_expression
    + anothero_ther_long_expression) {
}

Qt includes

  • When including Qt classes, prefer the inclusion of the full module rather than the corresponding header alone.
// wrong
#include <QString>

// preferable
#include <QtCore>

About Thibaud Kloczko

Graduated in CFD, Thibaud Kloczko is a software engineer at Inria. He is involved in the development of the meta platform dtk that aims at speeding up life cycle of business codes into research teams and at sharing software components between teams from different scientific fields (such as medical and biological imaging, numerical simulation, geometry, linear algebra, computational neurology).

Leave a Reply

Your email address will not be published. Required fields are marked *