B. Code conventions

Every programmer team has a number of conventions to be used while writing code. Whatever the conventions (several exist, which provides a convenient casus belli for countless wars) adhering to them helps all developers working on the same project,38 as they make it easier to understand the code; a reader familiar with their use can distinguish at a glance between a macro and a function, or between a variable and a type name.

The following listing briefly illustrates the conventions used throughout the QuantLib library. Following the advice in Sutter and Alexandrescu, 2004, we tried to reduce their number at a minimum, enforcing only those conventions which enhance readability.

Illustration of QuantLib code conventions.
#define SOME_MACRO

typedef double SomeType;

class SomeClass {
  public:
    typedef Real* iterator;
    typedef const Real* const_iterator;
};

class AnotherClass {
  public:
    void method();
    Real anotherMethod(Real x, Real y) const;
    Real member() const;   // getter, no "get"
    void setMember(Real);  // setter
  private:
    Real member_;
    Integer anotherMember_;
};

struct SomeStruct {
    Real foo;
    Integer bar;
};

Size someFunction(Real parameter,
                  Real anotherParameter) {
    Real localVariable = 0.0;
    if (condition) {
        localVariable += 3.14159;
    } else {
        localVariable -= 2.71828;
    }
    return 42;
}

Macros are in all uppercase, with words separated by underscores. Type names start with a capital and are in the so-called camel case; words are joined together and the first letter of each word is capitalized. This applies to both type declarations such as SomeType and class names such as SomeClass and AnotherClass. However, an exception is made for type declarations that mimic those found in the C++ standard library; this can be seen in the declaration of the two iterator types in SomeClass. The same exception might be made for inner classes.

About everything else (variables, function and method names, and parameters) are in camel case and start with a lowercase character. Data members of a class follow the same convention, but are given a trailing underscore; this makes it easier to distinguish them from local variables in the body of a method (an exception is often made for public data members, especially in structs or struct-like classes). Among methods, a further convention is used for getters and setters. Setter names are created by adding a leading set to the member name and removing the trailing underscore. Getter names equal the name of the returned data member without the trailing underscore; no leading get is added. These conventions are exemplified in AnotherClass and SomeStruct.

A much less strict convention is that the opening brace after a function declaration or after an if, else, for, while, or do keyword are on the same line as the preceding declaration or keyword; this is shown in someFunction. Moreover, else keywords are on the same line as the preceding closing brace; the same applies to the while ending a do statement. However, this is more a matter of taste than of readability; therefore, developers are free to use their own conventions if they cannot stand this one. The shown function exemplifies another convention aimed at improving readability, namely, that function and method arguments should be aligned vertically if they do not fit a single line.