Difference between revisions of "Documentation/4.1/Developers/Style Guide"

From Slicer Wiki
Jump to: navigation, search
(4.0 -> 4.1)
 
(→‎Code style: Add Levels of Abstractions)
Line 18: Line 18:
 
* do not leave blocks of commented out code in the source file -- if needed insert links to prior svn versions as comments
 
* do not leave blocks of commented out code in the source file -- if needed insert links to prior svn versions as comments
  
 +
== Functions ==
 +
* Don't mix different levels of abstraction
 +
** Examples
 +
*** When dealing with files names and path, use [http://vtk.org/gitweb?p=VTK.git;a=blob;f=Utilities/KWSys/vtksys/SystemTools.hxx.in;h=04f197842695c5914d1a49d4738159d3bccb08e8;hb=HEAD kwsys::SystemTools] in VTK classes, [http://doc.qt.nokia.com/4.7.4/qfileinfo.html QFileInfo]/[http://doc.qt.nokia.com/4.7.4/qdir.html QDir] in Qt classes or [http://docs.python.org/library/os.path.html os.path] in python. Instead of doing string manipulation manually:
 +
****<code>QString filePath = directoryPath + "/" + fileName + ".exe"</code>)
 +
*** prefer instead:
 +
****<code>SystemTools::JoinPath(), SystemTools::GetFilenameName()...</code>
 +
****<code>QFileInfo(QDir directory, QString fileName), QFileInfo::suffix(), QFileInfo::absoluteFilePath()...</code>
 +
****<code>os.path.join(), os.path.splitext(), os.path.abspath()...</code>
 +
** References
 +
*** [http://www.amazon.com/gp/product/0132350882?ie=UTF8&tag=solisyntprog-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0132350882 Clean Code] from ''Robert C. Martin'': ''Mixing levels of abstraction within a function is always confusing. Readers may not be able to tell whether a particular expression is an essential concept or a detail. Worse, like broken windows, once details are mixed with essential concepts, more and more details tend to accrete within the functions.''
 +
*** http://zuskin.com/coding_habits__functions.htm#Abstraction_levels
 +
* Use STL where you can, but follow the VTK [http://www.vtk.org/Wiki/VTK_FAQ#Can_I_use_STL_with_VTK.3F guidelines]
 +
** However, prefer [http://doc.qt.nokia.com/4.7-snapshot/containers.html Qt Container classes] to STL classes in Qt files
 +
** Note that a [http://www.vtk.org/doc/nightly/html/classvtkCollection.html vtkCollection] is somewhat equivalent to <code>std::list<vtkSmartPointer<vtkObject*> ></code>
 
== Language Specific ==
 
== Language Specific ==
  
Line 40: Line 55:
  
 
== Misc. ==
 
== Misc. ==
 
* Use STL where you can, but follow the VTK [http://www.vtk.org/Wiki/VTK_FAQ#Can_I_use_STL_with_VTK.3F guidelines]
 
  
 
= Commits =
 
= Commits =

Revision as of 21:08, 16 May 2012

Home < Documentation < 4.1 < Developers < Style Guide

Code style

Code that inherits from VTK classes should follow VTK coding conventions for naming, indentation, etc. See http://www.vtk.org/Wiki/VTK_Coding_Standards for details.

Naming

  • Acronyms should be written in all CAPS.
    • RASToSlice not RasToSlice
    • vtkMRML not vtkMrml
  • Words should be spelled out and not abreviated
    • GetWindow not GetWin

Comments

  • include extensive comments in the header files
  • keep the comments up to date as the code changes
  • use the keyword TODO to flag spots in the code that need to be revisited
  • do not leave blocks of commented out code in the source file -- if needed insert links to prior svn versions as comments

Functions

  • Don't mix different levels of abstraction
    • Examples
      • When dealing with files names and path, use kwsys::SystemTools in VTK classes, QFileInfo/QDir in Qt classes or os.path in python. Instead of doing string manipulation manually:
        • QString filePath = directoryPath + "/" + fileName + ".exe")
      • prefer instead:
        • SystemTools::JoinPath(), SystemTools::GetFilenameName()...
        • QFileInfo(QDir directory, QString fileName), QFileInfo::suffix(), QFileInfo::absoluteFilePath()...
        • os.path.join(), os.path.splitext(), os.path.abspath()...
    • References
      • Clean Code from Robert C. Martin: Mixing levels of abstraction within a function is always confusing. Readers may not be able to tell whether a particular expression is an essential concept or a detail. Worse, like broken windows, once details are mixed with essential concepts, more and more details tend to accrete within the functions.
      • http://zuskin.com/coding_habits__functions.htm#Abstraction_levels
  • Use STL where you can, but follow the VTK guidelines

Language Specific

Library Dependencies

  • MRML classes should only depend on vtk and itk (not Slicer Logic or Qt)
  • Logic classes depend on MRML to store state
  • Logic classes should encapsulate vtk and itk pipelines to accomplish specific slicer tasks (such as resampling volumes for display)
  • GUI classes can depend on MRML and Logic and Qt

Development Practices

  • While developing code, enable VTK_DEBUG_LEAKS (ON by default) in your vtk build and be sure to clean up any leaks that arise from your contributions.

Coordinate Systems

  • World space for 3D Views is in RAS (Right Anterior Superior) space. See Coordinate systems.
  • All units are expressed in Millimeters (mm)

Misc.

Commits

Commit message prefix

Subversion Commits to Slicer require commit type in the comment. Valid commit types are:

  BUG:   - a change made to fix a runtime issue
           (crash, segmentation fault, exception, or incorrect result,
  COMP:  - a fix for a compilation issue, error or warning,
  ENH:   - new functionality added to the project,
  PERF:  - a performance improvement,
  STYLE: - a change that does not impact the logic or execution of the code.
           (improve coding style, comments, documentation).

The Subversion command to commit the change is:

 svn commit -m "BUG: fixed core dump when passed float data" filename1[, filename2, ...]

By using the -m command line option, it's not possible to submit a message having multiple line. Submitting a mutli-line message can be achieved using the -f option:

 svn commit -f /path/to/message filename1[, filename2, ...]

It's also possible to set the environment variable SVN_EDITOR

Message content

A good commit message title (first line) should explain what the commit does for the user, not how it is done. How can be explained in the body of the commit message (if looking at the code of the commit is not self explanatory enough).

Examples

  • Bad: BUG: Check pointer validity before dereferencing -> implementation detail, self-explanatory (by looking at the code)
  • Good: BUG: Fix crash in Module X when clicking Apply button
  • Bad: ENH: More work in qSlicerXModuleWidget -> more work is too vague, qSlicerXModuleWidget is too low level
  • Good: ENH: Add float image outputs in module X
  • Bad: COMP: Typo in cmake variable -> implementation detail, self-explanatory
  • Good: COMP: Fix compilation error with Numpy on Visual Studio

If the commit is related to a mantis issue (bug or feature request), you can mention it in the commit message body:

BUG: Fix crash in Volume Rendering module when switching view layout

vtkSetAndObserveMRMLNodeEventsMacro can't be used for observing all types of vtkObjects,
only vtkMRMLNode is expected by vtkMRMLAbstractLogic::OnMRMLNodeModified(...) 
Closes #1641

Where 1641 refers to the issue number in mantis

Importing changes from external project/repository

When you update the git tag or svn revision of any external project, explicit in the commit message what the update does instead of just mentioning that an update in made.

This will avoid having a Slicer commit history made of ineligible messages:

r19180 - ENH: Update git tag
r19181 - BUG: Update svn revision
r19182 - ENH: revision updated
...

Ideally it should be the same message than the commit(s) in the external repository.

Example: ENH: Add feature A in module X instead of ENH: Update git tag

Resources

http://www.na-mic.org/Wiki/index.php/Engineering:Subversion_Repository

http://www.slicer.org/slicerWiki/index.php/Slicer:git-svn

UI Design Guidelines

General guidelines

Panels

Section

Volume Rendering sections

A section is used in a panel to categorize parameters by visually grouping them. In the Volume Rendering module, there are 3 sections: 'Inputs', 'Display', and 'Advanced...'. By default, the 'Inputs' and 'Advanced...' sections are collapsed. This reduces visual cluttering by hiding advanced and rarely used parameters. Sections should be organized in such a way that the workflow takes the user from top to bottom:

  1. The 'Inputs' section is first as it controls the inputs of the volume rendering.
  2. then the 'Display' section controls important display properties
  3. finally, if the previous parameters are not enough to obtain the desired result, the Advanced.. section offers fine tuning of the volume rendering.

Please note that the Advanced-ness of a section doesn't necessarily impacts its position in the section ordering. To create a section you must use a ctkCollapsibleButton [1] with no panel frame. Typically, the main node selector (Volume: in Volume Rendering) is the first GUI element and is outside any section.

Parameters

Justify elements in panel

Elements in panels should be justified (use of a QFormLayout can simplify the task)

Text

  • Capitalize the first letter in any text specified for a label or button
  • Try to use brief phrases when specifying text for a label or button rather than using sentences or sentence fragments ( use "Load volumes" instead of "Choose a volume to load")
  • Provide fully descriptive tool tips with each widget defined
  • Don't use colon after each parameter labels: Load volumes instead of Load volumes:

Layouts

  • Use the default values for the margins or 0. Default margins are automatically controlled by the Slicer custom style (see QStyle::PM_LayoutLeftMargin)
  • The minimum size hint of the top level module widget is used to determine the minimum width of the module. The minimum width of a module must not be larger than 500px (subject to change). This is enforced by the automatic test qSlicerMY_MODULE_NAMEModuleGenericTest. If the width is too large, you have multiple ways of narrowing the module panel:
    • In Qt Designer, you can ensure the sizing is correct by changing the QLayout::SizeConstraint to QLayout::SetMinimumSize. When you preview the module (Ctrl-R), it appears with the same size as it would in Slicer.
    • Ideally the minimum size hint of each wide GUI element should be fixed, it is unlikely that a large size hint is "ideal". **Alternatively, you might want to investigate the following:

Links