+$ FORMATTER='my-clang-format-15 -i' ./tools/format-cpp.sh
+----
+
+==== Naming
+
+* Use camel case with a lowercase first letter for:
+** Variable names: `size`, `objSize`.
+** Function/method names: `size()`, `formatAndPrint()`.
+
+* Use camel case with an uppercase first letter for:
+** Types: `Pistachio`, `NutManager`.
+** Template parameters: `PlanetT`, `TotalSize`.
+
+* Use snake case with uppercase letters for:
+** Definition/macro names: `MARK_AS_UNUSED()`, `SOME_FEATURE_EXISTS`.
+** Enumerators: `Type::SIGNED_INT`, `Scope::FUNCTION`.
+
+* Use only lowercase letters and digits for namespaces: `mylib`, `bt2`.
+
+* Use the `T` suffix for type template parameters and the `V` suffix for
+ non-type template parameters:
++
+[source,cpp]
+----
+template <typename NameT, typename ItemT, unsigned int SizeV = 0>
+----
+
+* Name a template parameter pack `ArgTs`.
++
+[source,cpp]
+----
+template <typename NameT, typename... ArgTs>
+----
+
+* Use an underscore prefix for private and protected methods and member
+ type names: `_tryConnect()`, `_NodeType`.
+
+* Use the prefix `_m` for private and protected member variable names:
+ `_mLogger`, `_mSize`, `_mFieldClass`.
++
+This is to avoid name clashes with private/protected getters/setters.
+
+* Name setters and getters like the property name, without the `set` and
+ `get` prefixes.
+
+* Use the `is` or `has` prefix, if possible, to name the functions which
+ return `bool`.
++
+However, try to keep the name readable. For example, prefer
+`colorIsBlue()` over `isColorBlue()`.
+
+=== Coding convention
+
+In general, the project's contributors make an effort to follow,
+for {cpp11} code:
+
+* The
+ https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md[{cpp} Core Guidelines].
+
+* Scott Meyers's
+ "`https://www.oreilly.com/library/view/effective-modern-c/9781491908419/[Effective Modern {cpp}]`".
+
+Here are a few important reminders:
+
+* Namespace your code.
+
+* Create one header/source file pair per class when possible.
++
+For a class named `MyClass`, name the corresponding files `my-class.hpp`
+and `my-class.cpp`.
+
+* Use the `inline` keyword, not `static inline`, for header-only
+ functions that are not templates.
+
+* When defining a class, use this order:
++
+--
+. Friends (without any preceding access specifier).
+
+. Public types and type aliases.
++
+Private/protected types may be here too if they can't be lower.
+
+. Constructors, whatever their access.
+
+. Destructor (always public).
+
+. Copy-assignment and move-assignment operators.
+
+. Public methods.
+
+. Protected types and type aliases.
+
+. Protected methods.
+
+. Private types and type aliases.
+
+. Private methods.
+
+. Protected data members.
+
+. Private data members.
+--
+
+* Declare variables as close to where they're used as possible.
+
+* In general, try to avoid variables if it doesn't lead to more lines.
++
+For example, given:
++
+[source,cpp]
+----
+const auto size = getSize(myObj, 23);
+auto& obj = this->_objForSize(size);
+
+abc::sendObj(obj, SendOpts::WAIT);
+----
++
+Prefer this:
++
+[source,cpp]
+----
+abc::sendObj(this->_objForSize(getSize(myObj, 23)), SendOpts::WAIT);
+----
+
+* If you really need variables, then scope them to avoid "`leaking`"
+ them:
++
+[source,cpp]
+----
+doSomeStuff(123, &obj);
+
+{
+ const auto status = tryChange(obj);
+
+ BT_CPPLOGD("New status: {}.", status);
+ BT_ASSERT(status == Status::CONTINUE);
+}
+
+doMoreStuff(&obj);
+----
++
+This also means to either use a dedicated, named method/function or to
+use `bt2c::call()` with an immediately invoked function expression
+(lambda) to perform complex initialization of an ideally `const`
+variable:
++
+[source,cpp]
+----
+const auto size = bt2c::call([this] {
+ auto& sender = this->_curSender();
+
+ if (sender.strategy() == Strategy::ACK) {
+ return sender.strategySize();
+ } else if (sender.strategy() == Strategy::NACK) {
+ return 0;
+ }
+
+ return _mDefSize;
+});
+----
+
+* Always use `bt2c::call()` to call an immediately invoked function
+ expression (see the previous point).
+
+* If possible, initialize object members without a default value with
+ the initializer list of a constructor, not in the constructor body.
++
+If the initialization is complex, either use a dedicated, named
+method/function or `bt2c::call()` with an immediately invoked function
+expression (lambda):
++
+[source,cpp]
+----
+MyObj::MyObj(const std::size_t size) :
+ _mSize {size},
+ _mOtherObj {bt2c::call([size] {
+ /* Complex initialization here */
+ })}
+{
+}
+----
+
+* Use `auto` when possible.
++
+Use `auto&` instead of `const auto&` when you know that the type is
+`const` anyway.
++
+Don't use `auto *`.
+
+* Use `const` as much as possible, even for pointers
+ (`+const char * const+`) and numeric values (`const unsigned int`)
+ which never need to change.
+
+* Prefer the `pass:[MyObj myObj {...}]` initialization form over
+ `pass:[auto myObj = MyObj {...}]`.
+
+* Implement simple setters, getters, and one-liners in header files and
+ everything else that's not a template in source files, including
+ constructors.
+
+* Make methods `const noexcept` or `const` as much as possible.
+
+* Make constructors `explicit` unless you really need an implicit
+ constructor (which is rare), including default constructors:
++
+[source,cpp]
+----
+explicit Meow();
+----
+
+* Use `std::unique_ptr` to manage memory when possible.
++
+However, use references (`+*my_unique_ptr+`) and raw pointers
+(`+my_unique_ptr.get()+`) when not transferring ownership.
+
+* Use `nullptr`, not `NULL` nor 0.
+
+* Return by value (rvalue) instead of by output parameter (non-const
+ lvalue reference), even complex objects, unless you can prove that the
+ performance is improved when returning by parameter.
+
+* For a function parameter or a return value of which the type needs to
+ be a reference or pointer, use:
++
+If the value is mandatory:::
+ A reference.
+If the value is optional:::
+ A raw pointer.
+
+* Don't use `+std::move()+` when you already have an rvalue, which
+ means:
+** Don't write `+return std::move(...);+` as this can interfere with
+ RVO.
+** Don't use `+std::move()+` with a function call
+ (`+std::move(func())+`).
+
+* For each possible move/copy constructor or assignment operator, do one
+ of:
+** Write a custom one.
+** Mark it as defaulted (`default`)
+** Mark it as deleted (`delete`).
+
+* Use scoped enumerations (`+enum class+`).
+
+* Mark classes known to be final with the `final` keyword.
+
+* Use type aliases (`using`), not type definitions (`typedef`).
+
+* In a `.cpp` file, use anonymous namespaces for local symbols instead
+ of `static` or `inline`.
+
+* Prefer a function in an anonymous namespace in a `.cpp` file over a
+ private static method if it doesn't need private access to an object.
+
+* Don't pollute the global namespace:
+** Don't use `using namespace xyz` anywhere.
+** Use only namespace aliases in source files (`.cpp`), trying to
+ use them in the smallest possible scope (function, or even smaller).
+
+* Return a structure with named members instead of a generic container
+ such as `std::pair` or `std::tuple`.
+
+* When a class inherits a base class with virtual methods, use the
+ `override` keyword to mark overridden virtual methods, and do not use
+ the `virtual` keyword again.
+
+* Define overloaded operators only if their meaning is obvious,
+ unsurprising, and consistent with the corresponding built-in
+ operators.
++
+For example, use `+|+` as a bitwise- or logical-or, not as a shell-style
+pipe.
+
+* Use RAII wrappers when managing system resources or interacting with
+ C{nbsp}libraries.
++
+In other words, don't rely on ``goto``s and error labels to clean up as
+you would do in{nbsp}C.
++
+Use the RAII, Luke.
+
+* Throw an exception when there's an unexpected, exceptional condition,
+ https://isocpp.org/wiki/faq/exceptions#ctors-can-throw[including from
+ a constructor], instead of returning a status code.
+
+* Accept a by-value parameter and move it (when it's moveable) when you
+ intend to copy it anyway.
++
+You can do this with most STL containers.
++
+Example:
++
+[source,cpp]
+----
+void Obj::doSomething(std::string str)
+{
+ _mName = std::move(str);
+ /* ... */
+}
+----
+
+.`baby.hpp`
+====
+This example shows a {cpp} header which follows the {bt2} {cpp} coding
+convention.
+
+[source,cpp]
+----
+/*
+ * SPDX-FileCopyrightText: 2020 Harry Burnett <hburnett@reese.choco>
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef BABELTRACE_BABY_HPP
+#define BABELTRACE_BABY_HPP
+
+#include <string>
+#include <unordered_set>
+#include <utility>
+
+namespace life {
+
+class Toy;
+
+/*
+ * A baby is a little human.
+ */
+class Baby : public Human
+{
+ friend class Parent;
+
+public:
+ using Toys = std::unordered_set<Toy>;
+
+ enum class Gender
+ {
+ MALE,
+ FEMALE,
+ OTHER,
+ };
+
+ explicit Baby() = default;
+ explicit Baby(const Toys& toys);
+ Baby(const Baby&) = delete;
+ Baby(Baby&&) = delete;
+
+protected:
+ explicit Baby(Gender initialGender = Gender::OTHER);
+
+public:
+ ~Baby();
+ Baby& operator=(const Baby&) = delete;
+ Baby& operator=(Baby&&) = delete;
+
+ /*
+ * Eats `weight` grams of food.
+ */
+ void eat(unsigned long weight);
+
+ /*
+ * Sleeps for `duration` seconds.
+ */
+ void sleep(double duration);
+
+ /*
+ * Sets this baby's name to `name`.
+ */
+ void name(std::string name)
+ {
+ _mName = std::move(name);
+ }
+
+ /*
+ * This baby's name.
+ */
+ const std::string& name() const noexcept
+ {
+ return _mName;
+ }
+
+protected:
+ void _addTeeth(unsigned long index);
+ void _grow(double size) override;
+
+private:
+ std::string _mName {"Paul"};
+ Toys _mToys;
+};
+
+} /* namespace life */
+
+#endif /* BABELTRACE_BABY_HPP */
+----
+====
+
+== Python Usage
+
+=== Formatting
+
+All Python code must be formatted using the version of
+https://github.com/psf/black[Black] specified in `dev-requirements.txt`.
+
+All Python imports must be sorted using the version of
+https://pycqa.github.io/isort/[isort] indicated in `dev-requirements.txt`.