# 2. Architecture Principles

Adopt a mORMot

This framework implements established "best-practice" patterns:

These patterns enable implementing projects up to complex Domain-Driven Design architectures.


2.1. General Design

The mORMot 2 architecture follows a layered design:

┌────────────────────────────────────────────────────────────────────┐
│                      mORMot 2 Architecture                         │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌───────────────┐                       ┌───────────────┐         │
│  │  Web Clients  │                       │ REST Clients  │         │
│  │ (AJAX/Mobile) │                       │(Delphi/FPC/…) │         │
│  └───────┬───────┘                       └───────┬───────┘         │
│          │                                       │                 │
│          └───────────────┬───────────────────────┘                 │
│                          │ RESTful JSON                            │
│                          ▼                                         │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                      TRestServer                             │  │
│  │  ┌────────────┐  ┌───────────┐  ┌───────────────────────┐    │  │
│  │  │ Auth       │  │ MVC/MVVM  │  │ Services              │    │  │
│  │  │ (Sessions) │  │ WebServer │  │ (Interface-based SOA) │    │  │
│  │  └────────────┘  └───────────┘  └───────────────────────┘    │  │
│  │                         │                                    │  │
│  │                ┌────────┴────────┐                           │  │
│  │                │    IRestOrm     │                           │  │
│  │                │    ORM Layer    │                           │  │
│  │                └────────┬────────┘                           │  │
│  └─────────────────────────┼────────────────────────────────────┘  │
│                            │                                       │
│  ┌─────────────────────────┴────────────────────────────────────┐  │
│  │                    Storage Backends                          │  │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌────────────────┐   │  │
│  │  │ SQLite3 │  │External │  │ MongoDB │  │ In-Memory/File │   │  │
│  │  │ (native)│  │  SQL    │  │ (NoSQL) │  │  (JSON/Binary) │   │  │
│  │  └─────────┘  └─────────┘  └─────────┘  └────────────────┘   │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                    │
│  Cross-Cutting Features:                                           │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │ Compression │ Security │ Crypto │ Logging │ Testing │ JSON   │  │
│  └──────────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────────┘

Key concepts of mORMot 2:


2.2. Architecture Design Process

Architecture should be driven by actual application needs, not by theoretical patterns. There is no "one architecture fits all" solution. Architecture is about how you build your software.

┌─────────────────────────────────────────────────────────────────┐
│            Iterative Architecture Process                       │
│                                                                 │
│  Customer ──► BackLog ──► Design ──► Dev ──► Software           │
│     │            │          │         │         │               │
│     │            │          │         │         │               │
│  Use Cases  Requirements  Architecture Tasks   Definition       │
│                              │                   of Done        │
│                              │                                  │
│                         Risk Assessment                         │
│                         Technology & Models                     │
└─────────────────────────────────────────────────────────────────┘

Avoiding Weak Design

Common pitfalls to avoid:

Recommended Practices

Frameworks like mORMot provide integrated, working sets of classes so you can focus on your product while enjoying collaboration with the Open Source community.


2.3. Model-View-Controller (MVC)

The Model-View-Controller (MVC) pattern isolates domain logic from user interface, permitting independent development, testing, and maintenance.

┌───────────────────────────────────────────────────────────┐
│                    MVC Pattern                            │
│                                                           │
│  ┌──────────┐    Uses     ┌──────────┐                    │
│  │Controller│ ──────────► │  Model   │                    │
│  └──────────┘             └──────────┘                    │
│       │                         │                         │
│       │ Command                 │ Notify Updates          │
│       ▼                         ▼                         │
│  ┌──────────┐    Refresh  ┌──────────┐                    │
│  │   View   │ ◄────────── │  Model   │                    │
│  └──────────┘             └──────────┘                    │
└───────────────────────────────────────────────────────────┘

Model: Manages behavior and data of the application domain. Responds to requests for information about its state and instructions to change state. In mORMot, implemented via TOrmModel class which centralizes all TOrm-inherited classes.

View: Renders the model into a form suitable for interaction:

Controller: Receives user input and initiates responses by making calls on model objects. In mORMot, already implemented within RESTful commands. Custom actions implemented via TOrm classes or RESTful Services.


2.4. Multi-Tier Architecture

Multi-tier architecture separates presentation, application processing, and data management into logically separate processes.

Two-Tier (Traditional RAD)

┌─────────────────────────────────────────────────────────┐
│  ┌─────────────────────┐    ┌─────────────────────┐     │
│  │  Application Tier   │    │    Data Tier        │     │
│  │  (UI + Logic mixed) │───►│    (Database)       │     │
│  └─────────────────────┘    └─────────────────────┘     │
└─────────────────────────────────────────────────────────┘

Three-Tier (mORMot ORM/SOA)

┌─────────────────────────────────────────────────────────────────┐
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐  │
│  │ Presentation    │  │   Logic Tier    │  │   Data Tier     │  │
│  │     Tier        │─►│  (ORM + SOA)    │─►│  (Database)     │  │
│  └─────────────────┘  └─────────────────┘  └─────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

Four-Tier (Domain-Driven Design)

┌───────────────────────────────────────────────────────────────────────┐
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────┐   │
│  │ Presentation │  │ Application  │  │Business Logic│  │  Data    │   │
│  │    Tier      │─►│    Tier      │─►│    Tier      │─►│  Tier    │   │
│  │(Delphi/AJAX) │  │(JSON Server) │  │  (Domain)    │  │(Storage) │   │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────┘   │
└───────────────────────────────────────────────────────────────────────┘

In mORMot 2:


2.5. Service-Oriented Architecture (SOA)

SOA is a design approach where functionality is packaged as inter-operable services that can be used across multiple systems and business domains.

┌──────────────────────────────────────────────────────────────────┐
│                    SOA Architecture                              │
│                                                                  │
│  Consumers                Service Bus               Publishers   │
│  ─────────                ───────────               ──────────   │
│  ┌─────────┐             ┌───────────┐            ┌───────────┐  │
│  │Client A │◄───────────►│           │◄──────────►│Publisher 1│  │
│  └─────────┘             │           │            └───────────┘  │
│  ┌─────────┐             │  Service  │            ┌───────────┐  │
│  │Client B │◄───────────►│    Bus    │◄──────────►│Publisher 2│  │
│  └─────────┘             │           │            └───────────┘  │
│  ┌─────────┐             │           │            ┌───────────┐  │
│  │Client C │◄───────────►│           │◄──────────►│Publisher 3│  │
│  └─────────┘             └───────────┘            └───────────┘  │
└──────────────────────────────────────────────────────────────────┘

Key SOA Characteristics

A software service is a logical representation of a repeatable activity that produces a precise result. Services are:

SOA Benefits: Decoupling

Dependency Desired Decoupling Technique
Platform Hardware/Framework/OS should not constrain choices Standard protocols (REST/JSON)
Location Consumers unaffected by hosting changes Routing and proxies
Availability Maintenance transparent to clients Server-side support
Versions New services without client upgrades Contract marshalling

ORM + SOA Coexistence

ORM and SOA complement each other:

In mORMot 2, interface-based SOA allows the same code to run on both client and server with better server performance and full interoperability.


2.6. Object-Relational Mapping (ORM)

ORM provides methods to persist high-level objects into a relational database.

┌───────────────────────────────────────────────────────────────┐
│                      ORM Process                              │
│                                                               │
│  ┌──────────────┐    ┌─────────────┐    ┌──────────────────┐  │
│  │    Object    │───►│     ORM     │───►│     RDBMS        │  │
│  │   Instance   │    │   (CRUD)    │    │   (Database)     │  │
│  └──────────────┘    └─────────────┘    └──────────────────┘  │
│                            │                                  │
│                      SQL Mapping                              │
└───────────────────────────────────────────────────────────────┘

ORM Mapping Sources

┌────────────────────────────────────────────────────────────────┐
│  ┌─────────────────┐         ┌─────────────────┐               │
│  │   Class Type    │         │   Data Model    │               │
│  │   (via RTTI)    │────────►│   (Database)    │               │
│  └─────────────────┘         └─────────────────┘               │
│           │                           │                        │
│           └───────────┬───────────────┘                        │
│                       │                                        │
│                  ┌────┴────┐                                   │
│                  │   ORM   │                                   │
│                  └─────────┘                                   │
└────────────────────────────────────────────────────────────────┘

Comparison of Approaches

Scheme Pros Cons
RAD DB Components SQL is powerful; RAD approach Business logic limited; SQL binds to engine; Poor multi-tier
Manual SQL Mapping Elaborated business logic SQL must be hand-coded; Duplication; Engine-specific
Database ORM SQL generated by ORM; Engine-agnostic More abstraction needed; May retrieve excess data
Client-Server ORM All ORM benefits; Services for precise data; Full multi-tier More abstraction needed
mORMot implements a Client-Server ORM that can scale from stand-alone mode to complex Domain-Driven Design.


2.7. NoSQL and Object-Document Mapping (ODM)

SQL vs NoSQL

SQL (Relational):

NoSQL:

NoSQL Families

1. Graph-oriented: Store data by relations (e.g., Neo4j) 2. Aggregate-oriented: - Document-based (MongoDB, CouchDB) - Key/Value (Redis, Riak) - Column family (Cassandra, HBase)

Document Model Example

SQL stores data per table (requires JOINs):

┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│     Users       │  │    Contacts     │  │     Access      │
├─────────────────┤  ├─────────────────┤  ├─────────────────┤
│ ID | UserName   │  │ UserID | Phone  │  │ UserID | Level  │
└─────────────────┘  └─────────────────┘  └─────────────────┘

NoSQL stores as documents (embedded):

{
  "ID": 1234,
  "UserName": "John Smith",
  "Contact": {
    "Phone": "123-456-789",
    "Email": "xyz@abc.com"
  },
  "Access": {
    "Level": 5,
    "Group": "dev"
  }
}

SQL vs NoSQL Trade-offs

SQL NoSQL
Ubiquitous SQL language Maps OOP and complex types natively
Easy vertical scaling Horizontal scaling (sharding)
Data normalization Schema-less evolution
Data consistency (single source) Version management
Complex ACID transactions Graph/Document native storage
Aggregation functions Map/Reduce support
With mORMot, you can switch from SQL to MongoDB with one line of code change, even at runtime.


2.8. Domain-Driven Design (DDD)

Definition

From domaindrivendesign.org:

"The premise of domain-driven design is two-fold:

DDD in mORMot

mORMot enables DDD through:

Implementation Layers

┌─────────────────────────────────────────────────────────────────────────┐
│                        DDD with mORMot 2                                │
│                                                                         │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │ Domain Layer (Pure Pascal)                                        │  │
│  │ · TOrm entities with business logic                               │  │
│  │ · Value Objects as records                                        │  │
│  │ · Aggregates with clear boundaries                                │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│                                  │                                      │
│  ┌───────────────────────────────┴───────────────────────────────────┐  │
│  │ Application Layer (Services)                                      │  │
│  │ · IInvokable interfaces (mormot.soa.*)                            │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│                                  │                                      │
│  ┌───────────────────────────────┴───────────────────────────────────┐  │
│  │ Infrastructure Layer                                              │  │
│  │ · IRestOrm repositories (mormot.orm.*)                            │  │
│  │ · TSqlDBConnection (mormot.db.*)                                  │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│                                  │                                      │
│  ┌───────────────────────────────┴───────────────────────────────────┐  │
│  │ Presentation Layer                                                │  │
│  │ · TRestHttpServer (mormot.rest.*)                                 │  │
│  │ · MVC views (mormot.core.mvc)                                     │  │
│  └───────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────┘

2.9. SOLID Principles in mORMot 2

mORMot 2 embraces SOLID principles:

Single Responsibility

Open/Closed

Liskov Substitution

Interface Segregation

Dependency Inversion

Composition Over Inheritance (mORMot 2 Key Change)

mORMot 1 used inheritance:

TSQLRestServer = class(TSQLRest)
  // ORM methods directly in class
  function Add(...): TID;

mORMot 2 uses composition:

TRest = class
  property Orm: IRestOrm;     // ORM via interface
  property Services: TServiceContainer;  // SOA via container
end;

// Access ORM through .Orm property
Server.Orm.Add(Customer);

This change improves:


Next Chapter: Meet mORMot 2 - New Units and Structure


Navigation

Previous Index Next
Chapter 1: mORMot 2 Overview Index Chapter 3: Meet mORMot 2