The following document is a description of the accepted coding style for the Medical Imaging Interaction Toolkit (MITK). Developers who wish to contribute code to MITK should read and adhere to the standards described here.
Naming Conventions
- Using case change to indicate separate words
ImageFilter
PixelType
DataStorage
NodePredicateProperty
- Underscores are not used e.g. Image_Filer, _Node
- Variable names should convey the meaning behind the code
BoundingBox::Pointer boundingBox = BoundingBox::New();
- Names are generally spelled out
- Abbreviation are allowable when in common use e.g. ROI for Region of Interest
Naming Classes
- Classes are named beginning with a capital letter
- Classes are named according to the following general rule:
class name = <algorithm><input><concept>
- Examples of concepts
Accessor: Access and convert between types e.g. NullScalarAccessor
Container: A container of objects such as points or images e.g. VectorContainer
Filter: A class that participates in the data processing pipeline e.g. AddImageFilter
Mapper: Transform data from one form into another e.g. ContourMapper2D
Reader/Writer: A class that reads/writes a single data object e.g. VtkSurfaceReader
Naming Files
- MITK classes like ExampleClass should be in namespace mitk and their corresponding files should be named mitkExampleClass.h/.cpp.
- Qt specific MITK classes like QmitkListView should have the prefix Qmitk in their class names and their corresponding files should be named QmitkListView.h/.cpp.
- Header Files ends with an .h and
- Implementation Files with an .cpp or .txx for a template class
Naming Methods and Functions
- Functions and methods are named beginning with a capital letter
- Referring to class methods in code, an explicit this-> pointer should be used
mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetAll();
Naming Signal/Slots Methods and Functions
- Slots are named according to the following general rule
On[variable name who send the signal][signal]();
- Example
connect( loadImagePushButton, SIGNAL( clicked(bool ) ),
SLOT( OnLoadImagePushButtonClicked( bool ) ) );
void mitk::Image::OnLoadImagePushButtonClicked( bool )
{
... Do something ...
}
- Signals are named according to the following general rule
- Example
emit SignalFinishedSegmentation();
Naming Class Data Members
- Class data members are prefixed with m_
m_Volumes
m_OffsetTable
m_ImageMask
- An exception to this rule, Qt class Data members are not prefixed and begin with a lower-case letter
loadImageButton
closeImageAction
Naming Local Variables
- Local variables first letter is lower-case
Naming Qt Variables
- GUI variables ends with name of used QT tool.
QPushButton* loadImagePushButton;
QAction* closeImageAction;
QCheckBox* hideImageCheckBox;
QRadioButton* binaryImageRadioButton;
Naming Typedefs
- Typedefs must end in the word Type
typedef TPixel PixelType;
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef std::list<mitk::Image::Pointer> ImageListType;
Pointer
Declaration of Pointers
- Position of * pointers are connected with the variable
SmartPointer
- SmartPointers must be used for classes that have itk::Object as a base class.
- Assignment of a just created instance to a normal pointer results in a crash, since the reference count is decreased immediately to zero and the object is destroyed.
itk::Object::Pointer object = itk::Object::New();
- Static declarations are also forbidden and result into an exception when the scope of the variable is left, because the destructor is called while the reference count is still greater than zero.
- Note that using smart pointers requires using real (normal) pointers when setting input. If you want to return a newly created smart pointer that is not also kept within the class (e.g., if you write a Clone method), you have to return a smart pointer on output (compare itkMacro.h). If the smart pointer is kept within the class, returning a real (normal) pointer is sufficient.
- Testing a SmartPointer against NULL is done with the IsNull() and Is- NotNull() methods. A simple ==NULL issues a warning.
Namespace
- MITK classes should be in namespace mitk
{
ImageDecorator::Pointer decorator = mitk::ImageDecorator::New();
d->Decorate( image );
return image;
}
- Constants in MITK for mitk::Operation and mitk::Action are set in namespace, so don't forget to add prefix mitk::
switch (actionId)
{
....Do something ...
break;
default:
break;
}
Code Layout and Indentation
General Layout
- Each line of code should take no more than 120 characters.
- Use lots of whitespace to separate logical blocks of code, intermixed with comments
- DO NOT USE TABS. The standard indention is 2 spaces (see ITK Style Guide). Configure your editor accordingly.
- DO NOT USE trailing whitespaces
- Declaration of variables should be one declaration per line
int sliceNumber;
char* stringName;
ImageType::Pointer image;
Class Layout
- Namespace DO NOT litter your header with "using namespace;"!
- Class (Template)
template <class TType>
class ClassName : public ImageBase<VImageDimension>
{
- Methods
public:
....methods....
protected:
....methods....
private:
....methods....
- QT Slots
public slots:
On...();
protected slots:
On...();
- Data Member
private/protected:
....class data members....
};
}
#endif
Use of Braces
- Used to delimit the scope of an if, for, while, switch.
- Braces are placed on a line by themselves:
for ( unsigned int i = 0; i < 3; ++i )
{
... do something ...
}
or if ( condition )
{
... do something ...
}
else if ( other condition )
{
... do something ...
}
else
{
... do something ...
}
- You can choose to use braces on a line with a code block when the block consists of a single line:
if ( condition ) { foo = 1; }
else if ( condition2 ) { foo = 3; }
else { return; }
or for ( unsigned int i = 0; i < 3; ++i) { x[i] = 0.0; }
Include Guards
- #include guard is a particular construct used to avoid the problem of double inclusion when dealing with the #include directive.
- Naming convention for #include guards is: ClassName_h
- Following example demonstrates a problem that can arise if #include guards are missing: Here, the file child.cpp has indirectly included two copies of the text in the header file grandfather.h. This causes a compilation error, since the structure type foo is apparently defined twice.
grandfather.h struct foo
{
int m Member;
};
father.h #include "grandfather.h"
child.h #include "grandfather.h"
#include "father.h"
Use of #include guards
- Here, the first inclusion of grandfather.h causes the macro grandfather h to be defined. Then, when child.cpp includes grandfather.h the second time, the #ifndef test fails, and the preprocessor skips down to the #endif, thus avoiding the second definition of struct foo. The program compiles correctly.
grandfather.h #ifndef grandfather h
#define grandfather h
struct foo
{
int m Member;
};
father.h #include "grandfather.h"
child.h #include "grandfather.h"
#include "father.h"
Some Technical Notes
- Use forward declarations in header files wherever possible. Only include those header files in a header file that are really necessary. Include the rest in the implementation file.
- For classes inheriting directly or indirectly from itk::LightObject (most of the MITK-classes do so), the class definition should include the mitkClassMacro. Additionally, if the class can be instantiated (normally the case, if the class is not abstract) and has only a constructor without parameters, the constructor should be declared protected and the itkFactorylessNewMacro should be used to create a New() method for instantiation. Here is an example:
class ExampleClass : public SuperClassOfTheExampleClass
{
public:
itkFactorylessNewMacro(Self)
[...]
protected:
ExampleClass();
virtual ~ExampleClass();
}
- Set- and Get-methods can be created with the macros itkSetObjectMacro(name,type) and itkGetObjectMacro(name,type), respectively, if the type is derived from itk::LightObject or itk::Object.
- When using inner classes of a parent class which is templated, you have to use the keyword typename for gcc 3.x and standard compliance. For example, TreeChangeListener is an inner class of Tree, therefore use:
class LinkedTree : public Tree<T>
{
public:
typedef typename LinkedTree<T>::TreeChangeListener TreeChangeListener;
[...]
}
Another example: typename std::vector<TreeChangeListener*>::iterator pos = treeChangeListenerList.begin();
iterator is an inner class of vector.
- Constants in MITK for mitk::Operation and mitk::Action are set in namespace, so don't forget to add prefix mitk:: Prefixes for the constants are to be used like corresponding others. See file Interactions\mitkBaseInteraction\mitkInteractionConst.h for further details.
Automatic Code Formatting
We offer a .clang-format file, which can be used to automatically format code acceptably.
For an explanation of the different options check out https://clang.llvm.org/docs/ClangFormatStyleOptions.html