For developers‎ > ‎

Coding guidelines

Collaboration

Welcome to the TuttleOFX project!
We recommand you to use the github fork and "pull request" mechanism. This is the most effective way to work with us.

Submit your "pull request" to our "develop" branch.

Versioning system

  • Git usage
Keep your commits as small as possible.

  • Commit message
As the project is composed of multiple parts, we recommand to put in one word the concerned module or kind of modules.
Module: short description

Detailed description of the modifications
* specific list of modifications
* another modification

Depending on the kind of modification, the detailled description and the list of modifications are optionals.

Don't forget to keep an empty line after the short (one line) description. Think about the "short description" as an email title.
Example:
tuttleHost: time propagation

* move getFramesNeeded() to OfxhImageEffectNode
* don't use connect on GraphAtTime but the low level function addEdge (to keep valid names, in/out, inAttr)
* update tuttle-time unittest


Code Formatting

  • Naming rules
    • File extensions
      • .cpp / .hpp for C++ files
      • .c / .h for C files
    • Files and class names should be the same.
    • Keep one class by file as much as possible.
    • UpperCamelCase for types.
    • localCamelCase for variables.
    • So lowelCamelCase files means that there is no class declaration inside and only contains a set of functions.
    • Class members are prefixed by "_", like "_memberVariable"

  • Struct vs Class
As defined in the Google C++ style guide, we only use Struct for POD.
For this kind of types, we allow to remove the variable prefix "_" because all the content of the struct is member variables.

  • Space, alignments, etc.
Please refer to the project style rules defined in the uncrustify configuration file: "tools/uncrustify.cfg".
TuttleOFX use the Uncrustify source code beautifier (GPL), available on linux, OSX and Windows platforms.


Coding Style Guide

We recommand you to read the following project style guides to learn good practices: Google C++ Style Guide and LLVM coding standards.


We follow the Google C++ Style Guide practices (not formatting) with the following additions and modifications:
  • Explicit names is strongly recommanded
As far as reasonable, we recommand excplicit names even if it creates long names. If you think it's a problem, you may need to change your IDE ;).

  • RAII
We use RAII as much as possible.
It's not possible in the OpenFX low level C interface, but we encapsulate this on both side: plugin and host.

  • C++ Exception
We use C++ exceptions with boost exception which is more flexible.
It allows to add arbitrary data to the active exception. If you don't have all information into the low level function, you could catch the exception at a higher level and add information, like this:

...
catch( boost::exception & e )
{
    e << boost::errinfo_file_name(file_name);
    throw;
}
  • BOOST_THROW_EXCEPTION
Use BOOST_THROW_EXCEPTION macro to throw exception as it adds file and line information into the exception.
BOOST_THROW_EXCEPTION( exception::Logic() );
  • C++ Exception messages
We recommand to put the maximum information into exception. To achieve that, it should be easy to add formatted messages into exception.
For this reason, we add stringstream objects that you can put into exceptions. The "operator<<" is used by boost exception to add new object information, so we define the "operator+" to easily manipulate those stringstream objects.

We use 2 kind of formatted messages into exceptions: "user" and "dev".
    • user message: The user message should be understandable for library users or external plugin developpers without looking through the code.
    • dev message: This message add some debugging information and is really technical.

An error example when loading an OpenFX plugin fails:
BOOST_THROW_EXCEPTION( exception::File()
    << exception::user() + "Error while loading plugin."
    << exception::dev() + "Can't search for symbol " + quotes( symbol ) + " (invalid:" + _invalid + ", dlHandle:" + _dlHandle + ")."
    << exception::filename( _binaryPath ) );

  • How to choose between ASSERT and BUG exception?
We use ASSERT when it's something that the library itself should garantee OR when it's really performance critical.
When it's a non-sense case, but the function could be called from external usages (external plugins or library users) possibly with wrong values, we use the particular exception called Bug.
This indicates that there is a bug somewhere. It could be a bug in the library itself, a bug in the library usage or a bug into a plugin.
BOOST_THROW_EXCEPTION( exception::Bug()
    << exception::dev( "fetchRegionOfDefinition unsupported on " + mapNodeTypeEnumToString(getNode().getNodeType()) + " node." ) );

  • Include order
Use local to global order for readability and to avoid hidden dependencies: your file header, your module headers, your project headers, other libraries, BOOST libraries, C++ standard library, C standard library.
    • Relative includes use "", like this: #include "local/path/to/header.hpp". Relative path should be used only to point into a subdirectory of the current file. Avoid usage of UNIX directory shortcuts . (the current directory) or .. (the parent directory).
    • Non relative includes use <>, like this: #include <another/module/of/my/project/header.hpp>.

An exemple from "tuttle/host/INode.cpp":

#include "INode.hpp" // Corresponding header first

#include "ImageEffectNode.hpp" // Current module headers
#include "InputBufferNode.hpp"

#include <tuttle/host/graph/ProcessVertexData.hpp> // Project headers
#include <tuttle/host/graph/ProcessVertexAtTimeData.hpp>

#include <boost/foreach.hpp> // Boost headers
#include <boost/algorithm/string/join.hpp>
#include <boost/lexical_cast.hpp>

#include <iostream> // C++ headers

#include <cstring> // C headers