Domain-Driven Design - Part 2 - Tactical Design
Tags: ddd, architecture, productivity, learning
Published: 2024-05-29 11:21:17

## Introduction
In the first part of the series we talked about the Strategic Design. We saw the subdomain types, ubiquitous language, bounded context and integration patterns.
Now, we need to deep dive into the _Tactical Design_ which is the "technical" part of the DDD concept.

## Building blocks

1. **Value objects** - *Structural equality and Immutable* 
The **value object** is a small object that represents a simple entity whose equality is not based on identity but on value. Value objects are **immutable**, meaning their state cannot be changed after they are created.

2. **Entities** - *Identifier equality and mutable*
Entities are objects that have a distinct identity that runs through time and different states. 
Unlike value objects, entities are **mutable** and their **identity** (i.e: an identifier in UUID) is more important than their attributes.

3. **Aggregates Root** - *Type of entity and mutable*
An **aggregate** is a _type of entity_ (act as a transactional boundary) that has an explicit identifier (i.e: an identifier in UUID) and whose state is expected to change over its lifecycle. The purpose of the aggregate pattern is to ensure the consistency of the data within the aggregate as one atomic transaction.

4. **Domain services** - *Stateless service*
A domain service is an object devoid of state that encapsulates the business logic. Typically, it orchestrates interactions between different components within the system to execute calculations or analyses.

5. **Domain events** - *Event occurs in the business domain*
A domain event is an event that describes a change in a business domain.

```json
{
  "eventType": "FlightScheduled",
  "eventPayload": {
    "FlightID": "AA1234",
    "Origin": "JFK",
    "Destination": "LAX",
    "DepartureTime": "2024-06-01T08:00:00Z",
    "ArrivalTime": "2024-06-01T11:00:00Z",
    "Status": "Scheduled"
  },
  "eventTimestamp": "2024-05-21T10:00:00Z"
}

```

## Architectures
There are various ways to implement application architecture. 
Below, you will find two types of application architecture that you can use. 

First one is the `Layered Architecture` and the second one the `Hexagonal Architecture`.

### Layered Architecture
![Layered Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7ak3jz87p1f8a0dv4na.png)

**User Interface / Presentation Layer**
It is the `interface for interactions` with customers (e.g : Web UI, CLI, REST API).

**Application / Service Layer**
The service layer functions as `a bridge between the presentation layer and the business logic` layer of the application.

**Model / Domain / Business Logic Layer**
This layer is responsible for `implementing and encapsulating the application's business logic`. It is where business decisions are executed.

**Infrastructure / Data Access Layer**
This layer integrates the `Persistence Systems`. In modern systems, it can be used for databases (DynamoDB, RDS, etc.), message buses (SQS, SNS, etc.), or object storage (S3, Azure Blob Storage, etc.).

### Hexagonal Architecture
![Hexagonal Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/precpdtq0iz77v1s8xmh.png)

**Business Model / Domain**
This is the heart of the application, encompassing all the business rules and logic. It operates independently and does not depend on any external systems.

**Application**
`Ports` act as gateways for communication, functioning as either inbound or outbound ports.
- `Inbound ports` : Like a service interface, exposes the core logic to the outside world.
- `Outbound ports` : Like a repository interface, enables communication from the application to a persistence system.

**Infrastructure**
`Adapters` function as implementations of ports, handling user input and converting it into language-specific commands. They contain the logic for interacting with external systems like message queues and databases, facilitating communication between external entities and the core logic.

Adapters come in two types:
- `Primary Adapters` or `driving adapters`: These drive the application using its `inbound port` (e.g: User interface adapter or REST controllers adapter.
- `Secondary Adapters` or `driven adapters`: These implement `outbound ports` and are driven by the application (e.g: message queues (SQS adapter), databases (DynamoDB adapter), and external API calls).

## Conclusion
Through the tactical lens, we delved into the building blocks of DDD: value objects, entities, aggregates, domain services, and domain events. Each component plays a specific role, from representing immutable values and maintaining entity identity to encapsulating business logic in services and signaling domain changes through events.

Moreover, we explored two principal architectural styles that facilitate the implementation of DDD: the Layered Architecture and Hexagonal Architecture. The Layered Architecture organizes code into distinct layers that separate responsibilities from the user interface down to infrastructure. In contrast, Hexagonal Architecture focuses on decoupling the core logic from external influences, emphasizing portability and adaptability through ports and adapters.

## Thank for reading

If you have any questions, feedback, or suggestions, please feel free to leave them in the comments below. I'm eager to hear from you and respond to your thoughts!