Skip to content

Classes vs functions

troussil edited this page Sep 26, 2012 · 1 revision

Design problem

When one wants transform some input data X to some output data Y, two alternatives are possible:

  • using an object A that offers a new view on X, ie. A(X) is Y.
  • using a procedure/function F that computes Y from X, ie. F(X,Y) or Y = F(X).

Use case

  • polygonal representation of contours (eg. FP) or estimators (eg. curvature estimator)
  • images (eg. distance transform) This list is not exhaustive.

Pros and cons

Designing classes (or struct) is useful for template specialization. Moreover, classes are well-defined entities, documented as such, which can gather many pieces of code in public and private methods in order to implement complex algorithms.

On the other hand, functions are well suited for users:

  • they can be overloaded to provide a customized signature
  • when they are called, there template parameters may be deduced from their arguments.

Proposal

Therefore, we propose to design a class (looking like an adapter) as well as one or several associated functions for each transformation mechanism.

For a class called Something (upper-case), the associated functions are called something (lower-case). Functions are gathered in the namespace Functions (DGtal::Functions::something), but written in the same files as the class (.h and .ih).

If some types must be provided, a traits class called SomethingTraits must be available, with one or more inner types.

Examples: Polygonalisation of a contour

  • A digital contour and its FP are both range of points. However FP keeps only a subset of the input set of points:

       ...
       FP<ConstIterator> polygon(itb, ite); 
       ASSERT( (polygon.end() - polygon.begin()) <= (ite - itb) ); 
    
  • The associated function would be:

       ...
       Functions::fp(itb, ite, std::back_inserter(polygon)); 
       ASSERT( (polygon.end() - polygon.begin()) <= (ite - itb) ); 
    
  • The FP can be parametrized by the integer type used for the computations and by the adjacency of the digital contour:

       ...
       FP<ConstIterator, int, 4> polygon(itb, ite); 
       ASSERT( (polygon.end() - polygon.begin()) <= (ite - itb) ); 
    
  • In that case, the associated function would be:

       ...
       Functions::fp4(itb, ite, std::back_inserter(polygon), int()); 
       ASSERT( (polygon.end() - polygon.begin()) <= (ite - itb) );  
    

or

     ...
     Functions::fp4(itb, ite, std::back_inserter(polygon), FPTraits<ConstIterator>::Integer()); 
     ASSERT( (polygon.end() - polygon.begin()) <= (ite - itb) );