Skip to content

Instantly share code, notes, and snippets.

@baconpaul
Last active December 8, 2023 13:58
Show Gist options
  • Save baconpaul/0852ef1e6628779cdc10c63ea210c53d to your computer and use it in GitHub Desktop.
Save baconpaul/0852ef1e6628779cdc10c63ea210c53d to your computer and use it in GitHub Desktop.
Some Coding Standards for Surge Things Maybe?

Prologue

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

  1. 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
  2. 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
  3. 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.
  4. Writing bad code which follows these standards is less good than writing good code which bends them with a comment!

So here goes

Names

  • namespaces are sst::lower_case::names
  • structs are CamelCaseWithUpper and are struct not class
  • struct members follow
    • mFooBar for members
    • sThisThat for static members
  • constants are generally
    • static constexpr either in a namespace or in a struct as appropriate
    • prefixed with a k for constants which are values. static constexpr float kDefaultCutoff{440.f};
    • prefixed with an n or num for unsigned integral constants which are set sizes. static constexpr uint32_t numParts{8}; or static constexpr size_t nPatches{148} or (somewhat controversially) static constexpr uint16_t nMaxVoices{256};
  • enums
    • enums are either commonly prefixed ft_this, ft_that or all upper case.
    • prefer class enums to non-class enums, especially in the prefixed form, using the class rules.
    • enums can optionally have a numBlah final member if ordered.
  • template class arguments are T etc or UpperCase
  • template int arguments follow the int constants member rules
  • local variables do whatever you want, but try to not conflict with the rules above. Like a local variable named kCutoff is pretty anti-social.

Coding Styles

C++ Standard

  • 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::filesystem for all filesystem apis, through the various import aliases provided.

Types

  • Try to use explicit types from <cstdint> like int16_t or uint32_t over int. Unsigned matters! Give it some thought.
  • initialize class members inline with {} whenever possible. That is, prefer a declaration like int mBlockCount{0}; in a class to : mBlockCount(0) in the constructor initialization list.
  • whenever possible, use auto. But be careful of auto f{0}; makes an int not a float!
  • Prefer c-style (int)std::round(f) casts for fundamental types (int, float, uint8_t etc...) but use static_cast<> reinterpret_cast<> or dynamic_cast<> as appropriate in other cases.
  • Initalize literal constants with the correct type using prefixes. 1.2f is a float; 0U is an unsigned 0.
  • prefer const std::string & to const char *

Memory

  • Prefer std::unique_ptr and std::make_unique to any other mechanism.
  • If you use std::shared_ptr write a comment explaining why. Sometimes you need it.
  • If you use new, you have probably made a mistake.

Pointers, References, etc

  • If you can code to const & rather than *, do so. Generally use references.
  • Having an object keep a const &Foo mFoo initialized in the constructor and set by using Struct(*mUniqueThing) is idiomatic.

Threads

  • use std::thread for all apis
  • threads == bugs. If you are adding a thread, chat with some other devs to make sure.

Miscellany

  • Use lambdas and std::function as 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.

The Audio Thread

  • Dont allocate
  • Use lock free data structures
  • Stuck? Ask!

Vibes

  • const matters. 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment