-
Notifications
You must be signed in to change notification settings - Fork 4
Coding Guidelines
The Integra svn contains software written in a variety of languages including C, Python, SClang and Max/MSP. Below are a set of guidelines for each language. These guidelines are not strict rules (unless otherwise stated), and are intended to enhance collaboration between contributors.
- All code should be documented
- Inline documentation is favoured over 'external' documentation
- Each 'trunk' directory should contain a brief README explaining what is in the trunk
- All code should be clean and readable
- Never commit broken code
- Even if you're not writing Python follow this
These conventions apply to Integra module names, not to code itself.
- Integra module class names should be in CamelCase
- Integra module instance names should be in CamelCase with a numeric suffix indicating the instance number: TapDelay1
- Integra module attribute names should be in lowerCamelCase giving us: TapDelay1.delayTime
- Use four spaces instead of Tabs for indentation (i.e. expand tabs to spaces)
- Use Unix line breaks (i.e.
not Windows: )
- A single line should fit in an 80 character terminal and therefore extend no further than 78 characters, if it does - please insert a line break or line continuation character (e.g. '\')
- function_and_variable_names_should_be_all_lowercase_with_underscores_and_be_explicit_and_meaningful
- As far as possible, function names should take the form ntg_<category>_<action>. E.g ntg_definition_add(), ntg_attribute_new() and NOT ntg_add_attribute()
- MACROS and CONSTANTS should be in capitals
- When writing platform-specific code, the compiler-defined macro should be used as a condition in an ifdef statement , that wraps the code e.g. #ifdef _WIN32. Do not use the user land macros like 'WIN32'
- All code should conform to the ANSI C89 standard.
- Pointers should be initialised to NULL (not 0)
- Pointer comparisons to 0x000000 should be made against NULL (not 0)
- The 'include' directive should be used in the following order: <config.h>, standard system headers (<..>), non-standard system headers (<…>), libIntegra public headers (”…”), libIntegra private headers (”…”).
- Function definitions should be formatted as follows:
return_type *function_name(params...)
{
...
}
- Otherwise, should always be on the same line as the preceding expression, with no space:
if(foo == 3){
do_something();
}
* The macro NDEBUG should be used to determine whether a 'debug' or 'release' configuration is being used for build
- Use the debug and error handling API: integra_debug.h integra_error.h
- error.h/errno may (and should) be used internally inside the library (e.g. for comparisons or printing serious errors to stderror), but integra_error.h should be used for ALL return codes
- Never add your own debug statements using printf or whatever, ALWAYS use the macro in integra_debug.h
- Use the memory allocation API: integra_memory.h
- If using an external library use their memory allocation functions
- NEVER directly call malloc, free, calloc or realloc
file structure
standard gnu license agreement at top of every file
functions within a class should always be ordered as follows: Constructor public functions protected functions private functions
virtual and override functions should be grouped together wherever this is sensible functions relating to similar areas of functionality should be grouped together wherever this is sensible
all variables should be declared private, with public getters/setters as needed all variables should be initialised where they are declared
The ActionScript 3 typed Vector class should be used in preference to the untyped Array class where possible
naming conventions
Classes should be named in upper camel case Functions, variables and constants should be named in lower camel case Member variables should be preceded with an underscore
enumerations
There is no native 'enumeration' type in Actionscript. A common Actionscript convention, also used in the Integra Live GUI, is to define enumerations as classes whose only content is a set of public static const Strings, one for each enumeration value.
indentation style: Allman style ( http://en.wikipedia.org/wiki/Indent_style )
Code flow style: minimise indentation. EG instead of
function doSomething
{
if( condition1 )
{
if( condition2 )
{
if( condition3 )
{
doSomethingElse();
}
}
}
}
it's better to write
function doSomething
{
if( !condition1 )
{
return;
}
if( !condition2 )
{
return;
}
if( !condition3 )
{
return;
}
doSomethingElse();
}
switch statements
Switch statements should always contain a 'default case'. If the default is not expected to be used (eg when there's a case for each value of an enumeration), the default case should fail an assertion, to alert developers to a possible error.
defensive programming - assertions and failsafe mechanisms
There is no native 'Assert' functionality in Actionscript. The Integra Live Gui uses a 3rd party component called 'FlexUnit' (http://opensource.adobe.com/wiki/display/flexunit/FlexUnit), which provides an 'Assert' class. Assertions should be used as liberally as possible. Furthermore, in any situation where an assertion failure is likely to cause a significant software malfunction, and where a simple failsafe mechanism is possible, one should be implemented.
Example of assertion without failsafe mechanism:
Assert.assertNotNull( referenceToSomething )
//subsequent code which relies on referenceToSomething
Example of assertion with failsafe mechanism:
if( referenceToSomething == null )
{
Assert.assertTrue( false );
return;
}
//subsequent code which relies on referenceToSomething
- Patches should be left aligned
- Crossing patch cords should be avoided
- Segmented patch cords should be avoided unless they really do make the patch easier to read
- Pd and Max module implementations should be saved as files with lowercase filenames using a - character to separate words, e.g. tap-delay.pd
All code should be documented. Even simple algorithms should include comments to help contributors learn and understand how the system is built and provide for easy access to the inner workings of the Integra system. A distinction should be made between API documentation and documenting algorithms.
The libIntegra code base is documented using Doxygen source code documentation generator tool. Depending on the language, if support is supplied we encourage the use of Doxygen (currently supports C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#, and to some extent D), in order to have a coherent and easily accessed API documentation. Following is a shortlist of useful Doxygen markup and guidelines for documenting a function in C.
All functions, public as well as private, should have a documentation block preceeding the function definition in the header file in the ggeneral form:
- brief description of the function
- detailed description of the function
- a list of the parameters the function takes as well as a description of each of the parameters
- a description of the return value (omitted if the functiion returns null)
We follow the principles of the Git branching model proposed by Vincent Driessen. On Mac OS X this can easily be accomplished with the Git Tower client, which supports Git Flow actions through the Git-Flow toolbar button.
Workflow:
- All new feature development should take place in the "develop" branch
- Once an upcoming release in the development branch is considered feature complete, a new (temporary) "release" branch should be created with the major / minor version number of the release, e.g. "release-1.6"
- When the "release" branch code is ready for release it should be merged into the "master" branch with the commit tagged with the full version number e.g. 1.6.2.1543
- If hotfixes are required for the currently released version, they should be made in the "release" branch and then merged into both the "master" and "develop" branches. The merge commit in the "master" branch should be tagged with the new version and an update release should be deployed
- Once a new release is due to be made from the development branch the old "release" branch can be deleted and replaced with a new one, e.g. "release-1.7"
- Each commit should relate to a self-contained piece of work, normally this should be tied to an issue on the project tracker
- Commit messages should be written in the imperative mood, if possible referencing the issue they relate to. The general form for the message summary should be:
<action taken>. <closes | fixes> #<issue number>
Additional lines can be used if you want to give more detail about <action taken>
For example:
Change malloc() to calloc() for allocating audio buffers. Fixes #23
We need to zero out the buffers in case they are accessed before they have been filled by the input callback
In order to maintain a clean working tree we use the following rule:
- When getting changes from the "remote" respository to your "local" repository always rebase your changes. This can be achieved with either
git pull --rebase
orgit fetch && git rebase
It is very straightforward to make a source code release.
From svn: integralive/library/trunk
- Check that version information is correct in configure.in
- sh ./autogen.sh && ./configure –enable-swig && make && make dist
This will give a source tarball like:
libIntegra-0.3.0.tar.gz
To deploy on the integra server, upload the latest source tarball (or make one then upload) to your home directory
- tar zxf libIntegra-0.3.0.tar.gz
- cd libIntegra-0.3.0
- ./configure –enable-serialization –enable-swig
- make
- sudo make install
Then change directory to the working svn copy:
- cd /var/svn/integra
- sudo svn update
Test, test, test!
Thats it! Writing help