Architecture of a DDD application

Description Article
Table of Contents
Summary

A complete application consists of four major layers:

Domain
Infrastructure
Application
User Interface

The domain layer contains the domain entities and stand-alone domain services.
Any domain concepts (this includes domain services, but also repositories) that depend on external resources, are defined by interfaces.

The infrastructure layer contains the implementation of the interfaces from the domain layer
and all non-domain required libraries required for communication between all the layers and other systems – infrastructure services

The application layer contains the implementation of the application services, corresponding to the model use cases providing an API that can be directly called by the client.

The user interface layer is responsible for presenting information to the user and interpreting user commands mapping them to application layer services.

 

This perspective of DDD definition of services, does separate the domain from the application and allows to share the domain (and infrastructure) assemblies between several applications.

Domain Driven Design - Overview of a Layered Architecture

Operations
Presentation Layer

This layer holds everything that interacts with other systems, such as web services, RMI interfaces or web applications, and batch processing frontends. It handles:

  • Interpretation, validation and translation (i.e. rendering) of incoming data; and
  • Serialization of outgoing data, such as HTML or XML across HTTP to web browsers or web service clients, or DTO classes.

Application Layer

This layer It is responsible for the navigation between the UI screens in the application as well as the interaction with the application layers of other systems.

This includes:

  • Translation of commands received from the upper layer to use cases invocation and coordinate the consequent application activity;
  • Perform the basic (non-business related) validation on the user input data before transmitting it to the other (lower) layers of the application;
  • Managing transaction scope and well suited for high-level logging and security;

It does not contain business logic.

How to do it

The application layer drives the workflow of the application, and defines application-specific operations corresponding to the use cases model and implemented following a service oriented architecture (SOA): Usually there will be one application service per aggregate root.

Application services are a facade purposed with providing an API: they are called directly by the Client and are interface-independent.

Application service: Description

An application service provides a hosting environment for the execution of domain logic, orchestrate execution of domain logic and delegate to the underlying entities, value objects and domain services. Setup and CRUD operation steps are exposed here:

An application service mediate data transfer to and from domain objects between upper and under layers using DTO objects
and it can directly invoke repositories to obtain or create/update domain objects or instead invoke a domain service if some business rule is required.

The methods in the application services exposed to the Client should have names that represent the application’s use cases. Second level application services performs technical tasks which domain experts are not interested in and would hardly understood.

Application services can operate upon:

  • Trivial parameters such as business entities identity values: This would be used by the service to load the appropriate entity object from the persistence store before working with it; or
  • Complex parameters as business entities representation objects or structures (DTO’s): This would be used when the service is requested to update the entity state  on the persistence store. This option take place if a specific reason exists to maintain decoupled application layer from the domain layer; or
  • Complex parameters as business identities class instances: This would be used when the service is requested to update the entity state. This option can only be considered if decouple application layer from the domain layer is possible. Consequently it will reduce the number of classes.

 

How to use it

Sample 1: Application service using directly a business entity

Part of the entitiy “Order” code

public class Order
{
       public virtual Money CalculateCost()
       {
              Money cost = Money.Zero;
              foreach (OrderLine line in OrderLines)
              {
                     cost = cost.Add(line.Cost);
              }
              cost = cost.Add(this.ShippingCosts);
              return ApplyTaxes(cost);
       }
}

Part of the application service “OrderService” code:

public class OrderService
{
       public virtual Money CalculateCostForOrder(int pOrderId)
       {
              Order lvOrder = Repository<Order>.Find(o = > o.pOrderId == orderId)
                           .SetFetchMode("OrderLines", FetchMode.Eager));
              return lvOrder.CalculateCost();
       }
}
urn order.CalculateCost();

       }
}

The business logic is in the entity.

In case of CRUD operations the application service loads, saves or updates the “Order” entity together with the “OrderLines” collection through repository calls. Then delegates the main operation on a specific method of the entity – in this sample the “Order::CalculateCost” method.

Sample 2: Application service invoking a domain service

public class AccountApplicationService
{
    private IAccountRepository _accountRepo;

    public AccountApplicationService(IAccountRepository pAccountRepo)
    {
        _accountRepo = pAccountRepo;
    }

    public void TransferFunds(double pAmount, int pSourceAccountNumber, int pTargetAccountNumber)
    {
        Account lvSourceAccount = _accountRepo.GetById(pSourceAccountNumber);
        Account lvTargetAccount = _accountRepo.GetById(pTargetAccountNumber);

        IAccountDomainService lvAccountDomaintService = new AccountDomainService();

        lvAccountDomainService.TransferFunds(pAmount, pSourceAccount, pTargetAccount);

        using(Transaction tran = _accountRepo.BeginTransaction())
        {
             _accountRepo.Save(pSourceAccount);
             _accountRepo.Save(pTargetAccount);
             tran.Commit();
        }
    }
}

In case of CRUD operations the application service loads the source and destination “Account” entities through repository calls. Then it delegates the main operation on a specific method of the “AccountDomainServicedomain service.

Services Layer

This layer exists when the application functionality is to be exposed to external systems through as a set of ReST resources or SOAP services (usually through WCF technology).

Its role is to simply map the WCF requests onto the application services.

How to do it

The WCF services are parametrized using DTO objects to transfer data to and from the business entities manipulated by these services, and next delegating command execution responsibilites to the application layer.

Alternatively, the application services can be decorated with the WCF attributes suppressing the need for the definition of additional DTO objects.

The services on this layer can operate upon:

  • Trivial parameters such as business entities identity values; or
  • Complex parameters as business entities representation objects or structures (DTO’s)

that will be used to parameterize and invoke the correspondent application services

Domain Layer

This layer contains information about the business domain.

It is responsible for the concepts of business domain, information about the business use cases and the business rules.

Domain objects encapsulate the state and behavior of business entities.

How to do it

The domain itself must be isolated from other domains in the business as well as other layers in the application architecture.

It must be carefully designed in order to be:

  • loosely coupled with other layers in the application, avoiding dependencies on the layers on either side of domain layer; and
  • reusable to avoid any duplicate models and implementations of the same core business domain elements on distinct applications.

All domain objects (entitiesdomain services and repository interfaces) that don’t depend on external resources are implemented in this layer.
Any domain concepts that depend on external resources are defined by an interface and implemented in the infrastructure layer.

Refer to The Domain Model article for implementaion details of domain objects.

Infrastructure Layer

This layer acts as a supporting and cross-cutting library for all the other layers facilitating communication between all layers.

It’s responsibilities include:

  • Provide communication between layers;
  • Implements persistence for business objects;
  • Provide supporting libraries for the user interface layer, configuration files, etc
  • Provide logging cache and securyy services

This features are made available as infrastructure services.