Why?

The ratio of time spent reading code vs. writing code is well over 10 to 1.

We’re not teaching you to be a code monkey. We’re teaching you to be a software developer: someone who writes good code and appreciates the importance of doing so.

That’s why we’re asking you to follow this style guide. Now, to be fair, there is no such thing as a perfect style guide: there will always be exceptions. But by and large, this guide has been designed to encourage good style with reasonable restriction.

Keep in mind that with the exception of the “General Guidelines” section, this guide has been developed with C++ in mind, so many rules are not portable (even to C/Java/C#, which are in the same syntax family!).

General Guidelines

In general (no matter what programming language), your code must be

Remember: the purpose of these rules is to enhance your code, never to make it worse. We have designed these guidelines to be broadly applicable, but there are no rules without exceptions - there will always be judgment calls to make, and we expect you to be able to make the correct ones.

C++ Pitfalls

In addition, you should keep the following pieces of advice in mind:

Conventions

There are a lot of coding conventions out there, ranging from the absurd to the controversial. For the purposes of this course, we will be using a mix of conventions that can be enforced with the clang-format linter and in-house rules (where ambiguous, ask, but it is safe to assume that in-house rules take precedence).

Using clang-format

You are expected to use clang-format -style=webkit to lint your code, which will automatically format your code according to the WebKit coding standard, which can be found here.

Alternatively, you may maintain your own clang-format specification.

Note that

In-house Rules

Structure

Classes must be split between two files: a .h containing only their declaration (the specification of the class’s interface, fields, etc.) and a .cpp containing only their definition (i.e. implementation of methods, etc.).

Header and Code Files

The use of both .h and .cpp files for the same bodies of code means that there are a number of stylistic concerns that must be managed:

Include guards

To prevent the preprocessor from including dependencies multiple times, #include guards (a.k.a. #define guards) must always be used where appropriate.

The WebKit standard specifies that #pragma once should be used, which works for their purposes, but since it is simply a common compiler extension and not actually in the C++ standard, you are not allowed to use it.

In a .h file, they must be named as NAMESPACE_CLASS_H (if in a .cpp, use _CPP as the suffix), c.f.

#ifndef NAME_FOO_H
#define NAME_FOO_H

namespace Name {
class Foo {
    ...
}; // class Foo
} // namespace Name

#endif // ifndef NAME_FOO_H

If no namespace is used, do not prepend an underscore, c.f.

#ifndef FOO_H
#define FOO_H

class Foo {
    ...
}; // class Foo

#endif // ifndef FOO_H

Declaration Order

When defining a class or struct, you should use access modifiers as the primary order, the following list as the secondary order, and grouping by functionality as the ternary order:

Comments should also be used to distinguish logical groups of fields and/or functions.

Within functions, etc., variable declarations should be placed either at the start of a block (after the {) or at the beginning of the group of lines of code that use the variables, and in the case of the latter, should be preceded by a blank line.

Access Modifiers

Never expose more of a class than should be exposed - in other words, if a member variable or function is not private, then there should be a good reason for it to be public or protected.

Syntax and Semantics

C++ has been around for a long time, and also is a very powerful language. As a result, there are a number of things that you can do which - for the most part - you should generally be unable to do, or at the very least you should avoid doing. These rules are as follows:

Naming Fields and Functions

We expect SCREAMING_SNAKE_CASE on constants and camelCase on everything else; specifically, UpperCamelCase for classes and namespaces and lowerCamelCase for class fields, locals, and functions.

Names should also generally correspond to what a variable represents and to what a function does or returns. To that end, variable names should generally be nouns and function names should generally be adjectives and/or verbs (generally, “is” should prefix boolean accessors, “get” for other accessors, and “set” for mutators), e.g.

uint32_t size
std::string errorMessage
bool isEmpty()
Property getProperty()
void setProperty()

Avoid names which might be ambiguous, e.g. void setRelativeZero() and void setCounterToZero() are preferable to void zeroCounter().

Spacing

The usage of whitespace is really important and is absolutely huge for readability. Use blank lines liberally (but not excessively) to improve readability; it is far more useful to be able to distinguish logical groups of member functions at a glance than to have to scroll for them.

There are also a number of issues that you should be aware of: