-
Notifications
You must be signed in to change notification settings - Fork 16
Coding Guidelines
- Preprocessor defines should be all upper case, e.g.
MY_PREPROCESSOR_DEFINE
. Avoid them though if possible (and use constants/methods/... instead). - All names use CamelCase/camelCase (instead of e.g. underscore; i.e. not: camel_case)
- Constant names start with an upper case letter, e.g.
MyConstantValue
- variable names start with a lower case letter, e.g.
myVariableValue
- Method names start with a lower case letter, e.g. myMethod
- Classes in open_iA should start with the "iA" prefix.
- Place the opening brace on the line after the thing you're starting; example:
class Test
{
// ...
}
void foo()
{
if (bar)
{
// ...
}
}
There should be as few includes as possible in a header file (ideally none). You only need to include a header file here if you:
- Derive from a class/struct
- Use a class/struct as member (but not if you are only using a pointer, reference or smart pointer to that class!)
In all other cases (e.g. when declaring a pointer to a class member), forward-declare any referenced classes!
Example header file:
#include "BaseClass.h"
#include "Member.h"
#include "MySmartPointer.h"
// forward-declarations
class Type1;
class Type2;
class Type3;
class Type4;
class TestIncludes: public BaseClass // BaseClass.h needs to be included
{
Type1* a; // fwd-declaration of PointerType is enough!
MySmartPointer<Type2> b; // MySmartPointer needs to be included, but Type2 only fwd-declared!
Member c; // directly using class Member as member, so we also need to include
void testMethod(Type3 foo, Type4 & bar); // Type3 and Type4 only need to be fwd-declared
};
In the cpp file, includes should be sorted from application-specific to the most generic headers (typically STL), in order of dependency (http://stackoverflow.com/questions/2762568/c-c-include-file-order-best-practices). The ideal order for our application code therefore is:
- header file for this .cpp file
- header files from the same module
- header files from the core
- library headers:
- itk
- vtk
- Qt
- STL & system/platform-specific includes
Since all supported compilers (Visual C++, g++) support it, the simpler #pragma once
should be used.
using namespace std
, while sometimes making it a bit easier to write names from the std namespace (e.g. std::vector or std::string) should be avoided, as it pulls in all sorts of functions and might lead to weird compilation errors, e.g. on other compilers or when new standards are introduced), or even weird bugs.
See e.g. this stackoverflow question for more details.
Enable by marking openiA_USE_COTIRE in CMake. This will enable precompiled headers through the COmpile TIme REduction library for CMake. However, in our experiments, it only slightly decreases the build time, but significantly increases the binary directory size.
Whenever possible, use the QString
type within open_iA for strings. Only when calling external library code that requires std::string
or char *
, convert to these types. This avoids encoding errors, as QString works with an UTF-8 encoded string; std::string
and char *
both are encoding-agnostic, and if not carefully handled, this can lead to problems with special characters. For conversion of a QString
to a std::string
or char *
used in a system library for accessing files, use the method getLocalEncodingFileName
from core/src/io/iAFileUtils.h
.
Rule of Thumb: Use ITK images whenever possible (rationale: I/O is much faster, more processing filters available). Only when you need to show an image, convert it to vtkImageData using an iAConnector.
Use helper methods in iAITKIO.h
and iATypedCallHelper.h
to make filters applicable for multiple different image types.
- multiple constants for the same thing -> merge to use the same definition!
- code duplication! -> merge implementations!
- unused (or only assigned to and never read)
- local variables
- members
- method parameters -> remove!
- unused methods (not called from anywhere) -> remove!
- passing references to methods, which are never used in the place calling the method
- intended as optimization when the method is called multiple times
- "optimization" of not declaring variable multiple times in method not worth the added unreadability!) -> declare variable inside the method
- very early declared variables (without initialization or with meaningless, empty initialization) -> declare variables as late as possible (ideally where you can usefully initialize them) -> also prefer declaring variable inside of loop! performance gain of declaring outside is negligible (https://stackoverflow.com/questions/7959573/declaring-variables-inside-loops-good-practice-or-bad-practice)
- methods that are called only once (and are short)
- If they are
- Action: Maybe they can be embedded where they are called.
- methods that have one or more boolean parameter that switches between large parts of execution flows in the methods -> maybe they can be split up into multiple methods
- somewhere in code, for a pointer/smart pointer member: if (null) initialize -> just initialize in constructor -> or use a member variable instead of pointer
open_iA Documentation, licensed under CC BY-NC-SA 4.0