Coding guidelines¶
Table of contents:
Language and libraries¶
- The codebase is mostly written in “C with classes”, a simple and unsophisticated subset of C++.
- We use C++98.
- We don’t use exceptions.
- We mostly avoid templates.
- We avoid inheritance, except “interface” inheritance.
- We avoid operators, overloading, and default arguments.
- We avoid using the preprocessor.
- We don’t use STL (the algorithms-and-containers part of the C++ standard library).
- We don’t use third-party utility libraries like Boost.
- We maintain our own minimal utility library (roc_core) designed to be very lightweight and allowing fine-grained memory management.
Portability¶
- The code should run on a variety of operating systems, compilers, and hardware architectures, including rather old compilers and distributions. See supported platforms page.
- The code specific to platform, compiler, or optional features and dependencies, should be isolated inside corresponding target directories. All other code should be portable across all supported configurations.
Best practices¶
- The code should compile without warnings (use
--enable-werror
SCons option).
- Cover every component with class-level unit tests if possible. Additionally, cover high-level features with pipeline-level integration tests. We use CppUTest.
- Prefer RAII and smart pointers for resource management.
- Prefer either non-copyable or trivial-copy objects. Avoid making “heavy” operations implicit, in particular, operations involving memory management.
- Use const when it is useful.
- Use anonymous namespaces instead of static globals, functions, and constants.
- Use enums instead of defines, when possible.
- Use allocators and pools for memory management.
- Log (using
roc_log
) important events and information needed to understand why an error occurred.
- Panic (using
roc_panic
) when a contract or an invariant is broken. A panic is always preferred over a crash. However, remember that panics are only for bugs in Roc itself. Never panic on invalid or unexpected data from the outside world.
Coding style¶
- The code should be formatted using
scons fmt
, which invokesclang-format
. If it goes awry, you can prevent a file from being formatted by adding it to.fmtignore
.
- Header and source files should contain the “Roc Streaming authors” copyright and license header. Running
scons fmt
will automatically insert them.
- Headers, classes, public members, and free functions should be documented using Doxygen. If Doxygen is installed, it is invoked during build and warns about undocumented items.
- Prefer creating individual .h and .cpp files for every class. Use snake_case for file names and old-style header guards, which are automatically inserted by
scons fmt
.
- Use upper case SNAKE_CASE for macros, CamelCase for class names, and lower case snake_case for methods, functions, fields, and variables. Add trailing underscore_ for private methods and fields.
- The code should be formatted according to our 1TBS-like indentation style defined in
.clang-format
config:- use 4 spaces for indentation;
- place opening braces on the same line as the control statement;
- use braces even for single-statement blocks;
- don’t place condition or loop bodies at the same line as the control statement.
#endif
and#else
statements should have trailing// <NAME>
and// !<NAME>
comments. Namespace closing brace should have trailing// namespace <name>
comment.