So kmolcard hopped on board and asked if we have any coding standards. And we kinda dont beyond "it works" and "clang-format it" so maybe its finally time to write some things down, some of which we are kinda defacto doing and some of which we are not.
A few pre-comments
- This is a draft baconpaul wrote and is not yet something we agree on. Comments, ideas, concensus working. And maybe the best thing is to delete some sections and stay silent
- This document implies some changes but I explicitly think we should not do a massive retrofit of the code base. Use these guides for new stuff and for changes, but don't retrofit the whole code bsase
- This is a guide not a set of rules. Sometimes they won't work. Then skip them! Or skip them and add a comment. And some things are marked "prefer", so use judgement of course.
- Writing bad code which follows these standards is less good than writing good code which bends them with a comment!
So here goes
- namespaces are
sst::lower_case::names - structs are
CamelCaseWithUpperand arestructnotclass - struct members follow
mFooBarfor memberssThisThatfor static members
- constants are generally
static constexpreither in a namespace or in a struct as appropriate- prefixed with a
kfor constants which are values.static constexpr float kDefaultCutoff{440.f}; - prefixed with an
nornumfor unsigned integral constants which are set sizes.static constexpr uint32_t numParts{8};orstatic constexpr size_t nPatches{148}or (somewhat controversially)static constexpr uint16_t nMaxVoices{256};
- enums
- enums are either commonly prefixed
ft_this, ft_thator all upper case. - prefer class enums to non-class enums, especially in the prefixed form, using the class rules.
- enums can optionally have a
numBlahfinal member if ordered.
- enums are either commonly prefixed
- template class arguments are
Tetc orUpperCase - template int arguments follow the
intconstants member rules - local variables do whatever you want, but try to not conflict with the rules above. Like a local variable named
kCutoffis pretty anti-social.
- We code to c++17 standard.
- Some of our builds still compile back to macos 10.9 so we have some light constraints on
<variant>and<optional>which CI will catch if you get them wrong. - use
std::filesystemfor all filesystem apis, through the various import aliases provided.
- Try to use explicit types from
<cstdint>likeint16_toruint32_toverint. Unsigned matters! Give it some thought. - initialize class members inline with
{}whenever possible. That is, prefer a declaration likeint mBlockCount{0};in a class to: mBlockCount(0)in the constructor initialization list. - whenever possible, use
auto. But be careful ofauto f{0};makes anintnot afloat! - Prefer c-style
(int)std::round(f)casts for fundamental types (int,float,uint8_tetc...) but usestatic_cast<>reinterpret_cast<>ordynamic_cast<>as appropriate in other cases. - Initalize literal constants with the correct type using prefixes.
1.2fis a float;0Uis an unsigned 0. - prefer
const std::string &toconst char *
- Prefer
std::unique_ptrandstd::make_uniqueto any other mechanism. - If you use
std::shared_ptrwrite a comment explaining why. Sometimes you need it. - If you use
new, you have probably made a mistake.
- If you can code to
const &rather than*, do so. Generally use references. - Having an object keep a
const &Foo mFooinitialized in the constructor and set by usingStruct(*mUniqueThing)is idiomatic.
- use
std::threadfor all apis - threads == bugs. If you are adding a thread, chat with some other devs to make sure.
- Use lambdas and
std::functionas a way to pass functions over prior c++ approaches if possible - Never use
[&] - Be cautions if using
[=] - All blocks have braces even one liners after an if.
- Dont allocate
- Use lock free data structures
- Stuck? Ask!
constmatters. Think about it and use it as much as you can.- Templates and specializations are better than virtual functions and inheritances especialy in the audio thread.
- The UI object model is the one place we use virtual a lot. That's fine.
- We end up using CRTP a lot. Dont know why but it works well