Coding guidelines¶
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 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.