-
Notifications
You must be signed in to change notification settings - Fork 9
Architecture
This document describes high-level architecture of the PorousMediaAnalysis project.
Table of Contents:
-
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.
-
Google C++ style guidelines are used, with amendments:
-
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.
-
Structured exception-handling is introduced in the project; for exception types see Exceptions.h.
-
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.
-
Default copy constructors and assignment operators are used for simple structures (data containers, Data Transfer Objects).
-
(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).
-
How object ownership is transfered:
-
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.
-
If an object A creates an object B in the constructor, it owns it (obvious).
-
If a function creates an object, it owns it (obvious).
-
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.
-
I prefer delegation (often of interfaces, by pointers) over template polymorphism, as
- the delegated interface is explicit
- it provides better compiler checks
- it supports run-time delegation updates
-
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).
-
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).
-
No UI layer, instead, a high-level client layer, file Main.cpp
-
Controllers layer, file ImageProcessingManager.cpp
-
Domain Model aka Business Layer * Services (Application Services) * Model (Domain Data Objects, usually plain Data Transfer Objects)
-
No Data Access Layer :-), but Core utilities
-
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.