Skip to content

Architecture

VasiliBaranov edited this page Feb 23, 2015 · 3 revisions

This document describes high-level architecture of the PorousMediaAnalysis project.

Table of Contents:

  1. General points
  2. Points specific to the project

1. General points

  1. Object-oriented programming (OOP) is used, test-driven development (TDD) is used (or at least the program is designed to support TDD), interface-driven development is used. Domain-driven design is used. Service-layered architecture is used.

  2. Google C++ style guidelines are used, with amendments:

  3. C#-similar naming conventions are followed, see 1. http://msdn.microsoft.com/en-us/library/xzf533w0(v=vs.71).aspx or 2. http://msdn.microsoft.com/en-us/library/vstudio/ms229002(v=vs.100).aspx:

    • local function variables, private variables of classes are in camel case,
    • methods, classes, typedefs, structures, public structure variables are in pascal case,
    • define macroses and global constants are in caps.
    • no hungarian notations is used, no Type postfix is used.
  4. Structured exception-handling is introduced in the project; for exception types see Exceptions.h.

  5. C# and Java-similar inheritance is used: no multiple inheritance of classes. If a class contains just abstract methods (no fields, no implementations), it's called an interface, and its name is prefixed with "I" (ex. IPackingGenerator). Multiple interface inheritance is allowed.

  6. Default copy constructors and assignment operators are used for simple structures (data containers, Data Transfer Objects).

  7. (From Google C++ style guide). Every object has a single owner, therefore we don't need copy constructors and assignment operators. They are explicilty disallowed for most objects (except DTO).

  8. How object ownership is transfered:

  9. If an object A is passed (by pointer/reference) to the function B or constructor of an object C, this function B or object C do not own A and should never delete it.

  10. If an object A creates an object B in the constructor, it owns it (obvious).

  11. If a function creates an object, it owns it (obvious).

  12. If an object's A method returns an object B by pointer to an object C, ownership depends on semantics: * For methods GetXXX, FindXXX, etc object A still owns the object B. * For methods CreateXXX (usually if A is a factory) object C, not A, owns the object B. * Therefore, the only case when you need smart pointers is for run-time polymorphic factory methods (other objects can be created with RAII). Still, the users of these polymorphic objects still receive a raw pointer, not a smart pointer.

  13. I prefer delegation (often of interfaces, by pointers) over template polymorphism, as

    1. the delegated interface is explicit
    2. it provides better compiler checks
    3. it supports run-time delegation updates
  14. If an object A delegates functionality to an object B, better declare B as a pointer in A, pass it to the constructor or create inside a constructor, not create it by value (though it still conforms to the single owner principle), because it allows TDD (supplying stubs or mocks).

2. Points specific to the project

  1. General architecture. It's a standard layered architecture, common in Domain Driven Design (see, e.g. Domain Driven Design Quickly Online by Avram and Marinescu; Patterns of Enterprise Architecture by Fowler).

  2. No UI layer, instead, a high-level client layer, file Main.cpp

  3. Controllers layer, file ImageProcessingManager.cpp

  4. Domain Model aka Business Layer * Services (Application Services) * Model (Domain Data Objects, usually plain Data Transfer Objects)

  5. No Data Access Layer :-), but Core utilities

  6. The basic project structure is from the Domain-Driven Design: Model (merely data transfer objects) and Services (see the Domain-Driven Design Quickly book). Multiple model types are included in the file Types.h for simplicity.