Skip to content

Coding Guidelines

Simon Leistikow edited this page Oct 29, 2024 · 1 revision

Naming Conventions

Variables

  • Variable names begin with lowercase, uppercase after each word (e.g., numSamples).
  • Class names are in CamelCase (e.g., class RenderProcessor;).
  • Names of member variables end with an underscore (i.e. class foo { int bar_; }).
  • Access to member variables is done without a preceding 'this->'.

Preprocessor Defines

  • Defines are written in all caps.
  • Do not use defines where a constant variable would suffice.
  • Voreen-specific constants begin with VRN_ (tgt analogous with TGT_)
  • Defines for header files: VRN_FILENAME_H

Miscellaneous

  • File names are lower case only.
  • Use english names and comments.

Data Types

  • unsigned types should be used only if absolutely necessary (i.e. to use the full value domain) and not just to prevent negative values.
  • short should also be used only if there is a convincing reason for it (i.e. save memory). int is almost always faster and it prevents problems with casting.
  • The size() method of STL containers (i.e. std::vector) returns a size_t and not int or unsigned int, so size_t should be used to prevent problems on 64-bit architectures.
  • The size() method of Qt containers however returns int.
  • In tgt/types.h some platform-independent types are defined (e.g. int8_t or uint32_t). If you want to assume something about the size of a type that goes beyond the C++ spec, use these types instead. An example are volumes with a bit depth of 16 bits. These should use uint16_t and not short or int.

Includes

  • Use quotations marks for voreen and tgt stuff.
  • Use angle brackets for everything else.
      #include "voreen/core/vis/identifier.h" 
      #include <string>
    
  • Includes should be placed in .cpp files preferably. Header files should contain forward declarations if the full declaration isn't neccessary.
  • A header file must never ever contain using namespace.
  • The include file for OpenGL is tgt/tgt_gl.h.

(Debug-)Output

  • Always use tgt loggers for debug output (tgt/logmanager.h). Example: LERROR("crash.");
  • Exception: "just testing" (can use std::cout, but remove as soon as possible).
  • Every base class declares a std::string loggerCat_ for logging, containing a string voreen... This should be overwritten in derived classes.

Version Control

  • Do not commit code that breaks stuff!
  • Use descriptive commit comments (in English), but not too elaborate.
    • "compile fix" is okay if there was a compile error.
    • "bug fix" is way too concise, it should name the specific bug (and the Trac bug number if applicable).
  • No large binaries in the repository: No volumes, large textures, large pre-compiled libraries, etc.
  • Pre-compiled binaries:
    • Go into modules/<your_module>/ext/
    • ext/ is only for core-dependancies (no new deps. unless authorized by the core dev team)
    • No linux/mac binaries (compilation is easy enough, compatibility across distributions/versions could be problematic)

Documentation

Formatting

Files

  • Preferably one class per file. Exception: simple specialization of an abstract base class.
  • File end with a line break (otherwise the gcc throws warnings).

Separation of Header and Source Files

  • Header files should contain only declarations. Definitions (method stumps) go into the cpp file.

  • Exceptions:

    • Methods like getClassName or getCodeState of processors can be seen as documentation and should be defined in the header file.
    • Templated classes make a clean separation difficult. The header part of the file is layouted as if the class was not templated and the corresponding method definitions come at the end of the header file.
  • If possible, try to put helper functions or classes just in the source file in an anonymous namespace, without even mentioning it in the header file.

  • Use inner classes and move enums into classes whereever possible, to prevent filling up the namespace.

Indentions

  • Line width should be limited to ~100 characters.
  • Indention: 4 blanks.
  • Use whitespaces only, not tabs. Default setting with Visual Studio is tabs; to change, visit: Tools (Extras) -> Options... (Optionen...) -> Text Editor -> C/C++ -> Tabs (Tab stops).
  • No indentions for namespace.

Miscellaneous

  • Opening bracket of a code block is placed at the end of a line. Exceptions are methods or if-statements with a multi-line parameter list and stack-based variable definition in case constructs.
  • Even a single instruction after an if should be written indented in a new line (makes debugging easier, because it's visually distinguishable if the if line or the instruction is being excecuted.
  • Insert empty lines where necessary, but usually one should be enough.
  • The asterisks and ampersands belong to the type and should be written as such: Type* ptr; Type& ref;.
  • For multi-line strings use automatic concatenation of strings instead of the preprocessor or the +-operator:
  // good:
  const std::string foo = "This is a very long string that takes up "
  "multiple lines.";
  // bad:
  const std::string foo = "This is a very long string that takes up
  multiple lines.";
  // not as bad, but unnecessary:
  const std::string foo = "This is a very long string that takes up " +
  "multiple lines.";

Other

  • Avoid compiler warnings at all costs.
  • Bugs and hacks should be marked by a FIXME: or TODO: in the code.
  • QString literals should be enclosed in tr("...") for the use of internationalization.
  • Variable initialization is done in the constructor: Class::Class() : member_(0), member2(0).
  • If you can, do not include complete namespaces (i.e. no using namespace std;), exception is voreen. Only include parts of the namespaces (e.g. using tgt::vec3), and only in source files of course.
  • Use namespace voreen { ... } instead of voreen:: for each method.
  • Order in classes: public, protected and private. First methods, followed by an empty line, followed by member variables.
  • Avoid the C-style cast (int)foo. Instead use C++-style casts static_cast(foo), dynamic_cast(foo) and reinterpret_cast(foo) (but know when to use which).
  • Target platforms are Windows, Linux and MacOS X
    • Particularities to be noted:
      • Mac OS: glew.h not in GL/
  • Use STL containers where possible and reasonable.
  • Write const-correct code (see http://www.parashift.com/c++-faq/const-correctness.html)
  • External libraries must be optional. If the library is not included, the project must still compile without errors. If conditional compilation if necessary to achieve that, do not use this in too many places.

Examples

Include File

  /* Copyright header */

  #ifndef VRN_FILENAME_H
  #define VRN_FILENAME_H

  #include <...>
  ...
 
  #include "..." 
  ...

  namespace voreen {

  class Class {
  public:
      methods

  protected:
      methods

      member variables

  private:
      methods

      member variables 
  };

  } // namespace

  #endif // VRN_FILENAME_H
  <empty line>

switch-case

  switch (...) {
  case 1:
      ...
      break;
  case 2:
      ...
      break;
  case 3:
      {
          int temporary = 0;
          ...
          break;
      }
  default:
      ...
  }

if-then-else

  // Even for single line instructions!
  if (...) {
      ...
      ...
  }
  else if (...) {
      ...
  }
  else {
      ...
  }
Clone this wiki locally