Guidelines for Developers

First and foremost: the best code is no code at all.

All Vitrall elements are located in global Vitrall namespace. Each module or utility library has its own Vitrall::name namespace. All classes and other definitions are located inside (e.g. class Renderer in Graphics module: Vitrall::Graphics::Renderer).

The only exception from this rule is a global variable stdlog of type Vitrall::Logging::Log, that is located in namespace Vitrall, and the log levels. It is strongly discouraged to create more exceptions.

Vitrall Specific Conventions

  • Do not split components of vectors in setters or getters - use just float3 (or other vector types) for both internal storage and access methods.
  • moduleName/ModuleName.hpp files are intended as entry library headers, do not include any other headers from the given library. Include only entry headers of other modules.
  • Use overloaded operators for printing, reading and arithmetic operations, this especially relates to classes from Math: Math::Matrix, Math::float3, Math::int2. If there the suitable operator is not implemented, then write one (or issue a ticket for psniegowski). For example instead of writing:
void printComponentWiseProduct(Math::float3 a, Math::float3 b)
{
  Math::float3 c;
  c.x = a.x * b.x;
  c.y = a.y * b.y;
  c.z = a.z * b.z;
  stream << "component wise product of " 
    << a.x << " " << a.y << " " << a.z << " and " 
    << b.x << " " << b.y << " " << b.z << " is "
    << c.x << " " << c.y << " " << c.z;
}

write just:

void printProduct(const Math::float3 &a, const Math::float3 &b)
{
  stream << "component wise product of " 
    << a << " and " << b << " is " << a * b;
}
  • However, remember about not using operators where ever possible, for example, don't use binary plus operator for scalar product because binary asterisk operator is used for the vector product - just make method named 'dot' for first one and 'cross' for the second one.

Code Formatting Conventions

  • Use tab characters instead of spaces.
  • Place opening { bracket in the following line.
  • Enclose even single-statement blocks in { } braces.
  • Place spaces between operators and operands.
  • Do not place spaces between () braces and their content.

Naming

  • Take advantage of C++ namespaces: instead of SomeModule::SomeModuleClassName write SomeModule::ClassName.

Boost

Vitrall uses some of the boost libraries heavily:

  •  Asio for networking,
  •  Thread for threading and synchronization (mutexes and conditional variables),
  •  Smart Ptr for smart pointers like boost::shared_ptr,
  •  Function and  Bind for creating handlers and other passing function calls to other threads,
  •  Lambda to increase code readability.

Includes

Includes should be sorted alphabetically and organized in the following sections:

// First include the corresponding header file (only applicable to .cpp files)
#include "SomeClass.hpp"

// Then all the other headers from the same module
#include "Alpha.hpp"
#include "Beta.hpp"

// Then headers from other vitrall modules
#include <vitrall/alpha/Alpha.hpp>
#include <vitrall/beta/Beta.hpp>

// External headers, grouped wherever possible
#include <boost/alpha.hpp>
#include <boost/beta.hpp>

#include <osg/Geode>
#include <osg/Node>

// System headers go at the end
#include <cstdio>
#include <cstdlib>

Please separate sections with an empty line even when the group contains only a single element.

We need to write down guidelines for the general headers, e.g. Vitrall.hpp and where does the developer have to use it and where she can ommit it. What should be put in module's main header file? Can other files in the module simply depend on that?

Logging

Vitrall uses a sophisticated logging utility based on conctept of  syslog, implemented in Vitrall::Logging::Log class. The main log is available as Vitrall::stdlog global object. If needed, additional log object can be created.

Vitrall's Log supports following levels:

  • Fatal
  • Error
  • Warning
  • Notice
  • Info - something a regular user should see
  • Debug - for developers
  • Trace - for developers, produces a lot of messages

Is is strongly recommended to provide log messages wherever this is suitable.

Here is a basic log usage:

#include <vitrall/logging/Message.hpp>

VITRALL_INFO("http request for ", Quote(request->GetResource()), " has been parsed");

To allow custom type to be used by logging utilities, one should provide specialization of template Logging::LogTraits.

Notes Regarding C++

Do not use using or using namespace in global namespace in header file ( reason).

Use statement using namespace in cpp files like this:

using namespace Vitrall;
using namespace Vitrall::Graphics;

when you are in files inside Graphics module.

Do not pass parameters to functions of types other than built-in standard types (int, float and so on) as a value. Use pointer or a reference instead. Remember of the const type modificator.

Always mark methods that do not change state of the object with const keyword (see  here).