Skip to content

Style Guide

General

Comments

Use code comments sparingly. Comments should explain why a decision was made, not what the code is doing.

Comments should be complete English sentences including the necessary articles ("a", "an", and "the") and punctuation, and should follow Microsoft's Writing Style Guide.

Inequality operators

Prefer using the < <=> or operators over <=, >, and >=.

C++

Follow Google's C++ Style Guide.

Function declarations

Exception: Use trailing return types for all function, method, and labmda declarations. Functions and methods may not use automatic return type inference.

// ✅ Do this
auto Add(const int64 a, const int64 b) -> int64;

// ❌ Not this
int64 Add(const int64 a, const int64 b);

Header guard

Exception: Use #pragma once instead of #define guard for header files. This project's tooling does not support automatically enforcing the header guard convention where the #define guard's identifier mirrors the file's path to guarantee uniqueness. Despite being non-standard, #pragma once carries advantages such as reducing the maintenance burden when renaming and moving files improves compilation speed in some cases.

// ✅ Do this
#pragma once

// ❌ Not this
#ifndef SPOOR_PATH_TO_HEADER_H_
#define SPOOR_PATH_TO_HEADER_H_
...
#endif

Initialization

Prefer list (curly brace) initialization over other forms. List initialization does not allow type narrowing making it safer than its alternatives.

MyClass::MyClass(const int64 value) : value_{value} {...}

const int64 x{42};
const MyClass my_class{x};

Error handling

Do not use C++ exceptions for error handling. In fact, Spoor disables exceptions by compiling with -fno-exceptions.

Instead, handle errors with Spoor's Result<Value, Error> type used to return either a value on success or an error otherwise.

Numeric values

Use numeric types with a defined size. For convenience, integer types without the _t postifx are defined in util/numeric.h. Prefer using these typedefs over the values defined in <cstdint>.

// ✅ Do this
#include "util/numerics.h"

int64 x{42};

// ❌ Not this
#include <cstdint>

int x{42};
int64_t y{7};

Tools

Use Clang Format and Clang Tidy to style and lint code.

Ignore lint warnings

In special circumstances it might make sense to ignore lint warnings, for example, when using an external library macro where the lint warning is unavoidable. Explicitly list the lint rules to ignore instead of using a blanket NOLINT or NOLINTNEXTLINE.

// ✅ Do this
int64 a[] = {1, 2, 3};  // NOLINT(modernize-avoid-c-arrays)

// ❌ Not this
int64 a[] = {1, 2, 3};  // NOLINT

Exception: Google Test and Abseil flags library macros.

// ✅ Okay
TEST(Foo, Bar) { // NOLINT
  ...
}

// ✅ Okay
ABSL_FLAG(  // NOLINT
    std::string, my_flag, {}, "Description...");

Objective-C

Follow Google's Objective-C Style Guide.

Nil checks

Exception: Do not use implicit nil checks

// ✅ Do this
if (a != nil)

// ❌ Not this
if (a)

Python

Follow Google's Python Style Guide.

Indentation

Exception: Indent code with two spaces.

Starlark (Bazel)

Follow Starlark's Style Guide.

Use Buildifier to style and lint Starlark files.

Shell

Follow Google's Shell Style Guide.

Shebang

Exception: Use the shebang #!/usr/bin/env bash which is more portable.

# ✅ Do this
#!/usr/bin/env bash

# ❌ Not this
#!/bin/bash

Markdown

Follow Google's Markdown Style Guide.

Character line limit

Each line should be at most 80 characters long.

Exception: URLs and tables which cannot be wrapped.

Use reference-style links for long URLs. Use kebab-case for reference names, place references at the end of the file, and alphabetize the list.

✅ Do this
Follow [Google's Markdown Style Guide][google-markdown-style-guide].

[google-markdown-style-guide]: https://google.github.io/styleguide/docguide/style.html#document-layout

❌ Not this
Follow
[Google's Markdown Style Guide](https://google.github.io/styleguide/docguide/style.html#document-layout).