We follow the MongoDB Server Code Style except:
- We use GUID include-guards rather than
#pragma once
- File names match class names e.g.
class FooBar
will be found inFooBar.hpp
andFooBar.cpp
rather thanfoo_bar.hpp
.
We have not yet officially brought over the clang-formatter settings from the server.
Please avoid:
- Complicated macros (e.g.
__VA_ARGS__
or#ifdef
excluding include-guards) - Macros for syntax tokens (e.g.
class MyClass : PRIVATE_SUBCLASS Y
ornamespace SOME_NAMESPACE
) - Conditional-compilation (we strive to only use widely-supported standard C++ features)
- Compiler-specific features
std::experimental
- Code-generation (e.g. generating C++ from another language, including CMake)
Many editors and IDEs have a hard time if code hides lots of things behind macros or code-generation or otherwise uses cleverness. While there is a lot of power in macros and code-generation, for the time-being we are valuing wide editor support and simplicity of conventional methods.
If a pull-request addresses a JIRA ticket, for a single-commit PR, prefix the subject line with the ticket ID. (For a multi-commit PR, we will add the ID later when we squash or merge it.)
ABC-883 Add commit message conventions to CONTRIBUTING.md
Capitalize subject lines, and don't use a trailing period. Keep the subject at most 70 characters long. Use active voice! Imagine this preamble to get your phrasing right:
If applied, this commit will... %%your subject line%%
See Chris Beams' How to write a git commit message for more good guidelines to follow.
Naming and bureaucracy:
- Public (exposed) header files belong in
include
directories. - Public headers must have a
.hpp
suffix. - Private headers must have a
.hh
suffix. - Header file names are in
snake_case
, but headers defining a single class arePascalCase
. - Class names are in
PascalCase
, and local/member variables arelowerCamelCase
. - Member variables (class properties) have leading underscores.
- Method parameters do not have leading or trailing underscores.
General header file structure:
- Include Guard (
#ifndef HEADER_{uuid}_INCLUDED
#define HEADER_{uuid}_INCLUDED
). Useuuidgen | sed s/-/_/g
to generate{uuid}
for new files. - System Headers
<vector>
(alphabetical order) - Blank line
- Local headers
<genny/foo.hpp>
(alphabetical order) - Open Namespace
genny
- Code
- Close Namespace
genny
(Helpful tip: make a shell alias for the include string:
alias huuid="echo \"HEADER_\$(uuidgen | sed s/-/_/g)_INCLUDED\""
)
Example header file:
#ifndef HEADER_9854B7E9_CAFF_4CD3_8A48_BD5E6A368C96_INCLUDED
#define HEADER_9854B7E9_CAFF_4CD3_8A48_BD5E6A368C96_INCLUDED
#include <string>
#include <vector>
#include <genny/bar.hpp>
#include <genny/foo.hpp>
namespace genny {
// Declarations
// Inline Implementations
} // namespace genny
#endif // HEADER_9854B7E9_CAFF_4CD3_8A48_BD5E6A368C96_INCLUDED
Guideline and ordering:
-
Blank line at beginning and end of class declaration
-
Class names in
PascalCase
-
Public section up top:
-
default-or-argument-bearing 'user' constructors
-
declaration-or-deletion-of-move-constructor
-
declaration-or-deletion-of-move-assignment-operator
-
declaration-or-deletion-of-copy-constructor
-
declaration-or-deletion-of-copy-assignment-operator
-
declaration-of-dtor
-
Public methods
-
-
Passkey/pseudo-private methods within public section
-
Private section on bottom:
- Friendships
- Private Constructors
- Private Methods
- Private Variables (leading underscore and
lowerCamelCase
)
-
Blank line at end of class declaration.
Example:
#ifndef HEADER_82C204F5_26C2_4B39_9469_9FE242037891_INCLUDED
#define HEADER_82C204F5_26C2_4B39_9469_9FE242037891_INCLUDED
#include <string>
#include <vector>
#include <gennylib/Foo.hpp>
namespace genny {
class Foo {
public:
Foo();
Foo(Foo&& other) noexcept;
Foo& operator=(Foo&& other) noexcept;
~Foo();
std::vector<int> explode(const std::string& y);
private:
friend class Baz;
class impl;
std::unique_ptr<impl> _impl;
};
} // namespace genny
#endif // HEADER_82C204F5_26C2_4B39_9469_9FE242037891_INCLUDED
- Define outside of class declaration
- Specify inline keyword in declaration and definition (for clarity)
- Prefer to use free functions
- Use scoped enums (
enum class
) wherever possible - Use
k
prefixes for enum values e.g.enum class Color { kRed, kBlue };
Genny uses Catch2 as its test framework. If you'd like to make changes to the vendored copy of Catch2 (e.g. to upgrade to a newer copy) Please make sure you read the README in the Catch2 directory before making changes.