[DDD] Domain Driven + Onion Architecture Overview

DDD serialized article

background

I recommended it in the article What is the most accessible architecture to start implementing with Domain Driven Design Was the onion architecture.

This time, I would like to explain the onion architecture in detail.

As I wrote in the above article, the three "hexagonal, onion, clean" are essentially the same, and the idea is that they are completed in hexagonal, but the onion is explained more concretely. I think it's easier to understand if you read the explanation from the architecture.
After that, if you read the explanation of hexagonal, it will be "I see" and "Oh, it's hexagonal after all". Lol

Traditional layered architecture

image.png

This architecture is designed to aggregate literally all business logic into the Business Logic layer. But,

There are disadvantages such as.

Layered architecture introduced in "Eric Evans Domain Driven"

image.png

This architecture is an attempt to improve maintainability by giving business knowledge to the domain layer model from the traditional layered architecture.

This is explained in the article What is expressing domain knowledge in a model with sample code. Please refer to that.

This design has greatly improved the ease of modeling, but it still has its weaknesses. *** The Domain layer depends on the Infrastructure layer ***.

This means that infrastructure layer changes, such as library changes or database switching, can affect the overall business logic.

Let me give you a concrete example.

image.png

Suppose you have implemented DB access for a model as an RDB.
If the implementation of Infrastructure and Domain layer is a description of the premise to be used in a specific RDBMS, how much code must be changed if you try to change RDB to Dynamo of AWS later ... ?? It's hard just to imagine.

As another example of replacing the Infrastructure layer, you can realistically imagine the case where you want to switch from creating your own email sending service to a more sophisticated external service.

The problem is that you're trying to "design around the domain model", but the Domain layer depends on some layer. I want the Domain layer to be modified only when there is a change in the domain model.

Onion architecture

Principle of dependency reversal

image.png So this is the architecture.

To explain based on the sample object introduced in the article What is expressing domain knowledge in a model ・ ・ ・

Task: Domain Model layer(Real class)
TaskRepository: Domain Service layer(Repository/Interface)
TaskApplication: Application Service layer
TaskRDBRepository: Infrastructure layer(Repository/Real class)
TaskDynamoRepository: Infrastructure layer(Repository/Real class)

image.png

Oops, I was able to successfully implement the domain model as a class that doesn't depend on anything!

What's the difference?

Yes, the dependency with the Infrastructure layer was reversed because the TaskRepository became an Interface instead of a real class.

This method is called the principle of dependency reversal. (Reference)
*** High rather than implementing low level layers and then relying on high level layers It is *** implemented by the low-level layer based on the Interface published by the level layer! This allows you to increase the independence of high-level layers.

In this case,

public inteterface TaskRepository {
  Task findById(Long taksId);

  void save(Task task);
}

In DomainService, only the call method and return type are defined in this way, and the persistence destination is not specified. * You declare it in the form of "The persistence destination can be anywhere, but the implementation class should match this because it is searched and saved in this way" *. ApplicationService is defined by TaskRepository type, and then [DI (Dependency Injection)](https://ja.wikipedia.org/wiki/%E4%BE%9D%E5%AD%98%E6% 80% A7% E3% 81% AE% E6% B3% A8% E5% 85% A5) and so on so that the real class is judged at runtime.

Now, even if you want to replace the persistence destination from RDB to Dynamo, if you prepare another implementation class, you can design without modifying DomainModel, DomainService, ApplicationService at all. It is wonderful.

The merit is not only that it is easy to replace the implementation class, but also that it is easier to read and maintainability because low-level code is not included in the model that expresses the business.

Opinion expressed in a round shape

In the above figure, the layer is represented flat for comparison with the layered architecture, but the original definition is that it is represented in a round shape because it is named "onion".

image.png

So what does this round shape mean?

It represents the model *** which has a boundary between the application and its outside, and communicates through an adapter between them. (The arrows represent the direction of the request, each receiving a response in the opposite direction)

image.png

For example, in the case of a request from a certain HttpClient, the application first receives it with a dedicated Adapter, the application performs some processing, acquires information from the DB as necessary, and the application processes the DB response and returns it as the HttpClient response. ..

In the case of integration test as well, the application receives a request from the dedicated Adapter and processes it, but in that case it is also possible to replace the DB with MockDB (in-memory etc.).

The advantage of this model is that *** DomainModel and Application can always be written independently and quality assurance can be done in that unit ***. Since it can be called only by the method permitted by Application from the outside, if the application is quality-guaranteed by the automatic test, it can be considered that the Application does not behave strangely regardless of the client that calls it. This sense of security is enormous.

Test strategy

I think this depends on the policy of each project, but I personally think that the policy of implementing only the integration test for Application Service is the most cost-effective.

In addition, DDD emphasizes refactoring to mature the model, but there is also the advantage that it is easier to freely refactor the inside by testing with a certain large particle size called Application Serice. If you test too closely on a class-by-class basis, you may feel uncomfortable with refactoring because each class disappears at the time of refactoring, and as a result, the dynamics of not refactoring may work.

As mentioned above, if you test for each Application Service, you can feel reassured about the quality. When considering a test strategy, I think you should just specify it as a reference.

Oh, this shape

Oops, and the last Adapter looks like something ...
Yes, it's a hexagonal architecture.

image.png

The hexagonal architecture introduced in the article What is the easiest architecture to get started with Domain Driven Design model figure

That's right, the idea of connecting this application with the outside world with an adapter is the same as the hexagonal one. After all, this hexagonal idea is very good, isn't it?

The onion architecture is just a bit more detailed inside the Application, specifying the type of Adapter and making it a little more specific overall.

As I wrote at the beginning of this article, did you say "Oh, it's hexagonal after all"? Lol

Summary

By the way, did you convey the appeal of the onion architecture and the implementation image? If you can imagine up to this point, I think that you can proceed little by little by referring to the detailed stories as needed.

I will write more detailed stories in the future, so please keep in touch with me if you like.

If you want to know more

We have published a book for those who are learning DDD for the first time, or for those who have actually started and are facing difficulties.

Domain Driven Design Modeling / Implementation Guide

Starting with an explanation of the "purpose of DDD" and "model" that tend to get lost, We aim to experience the appeal and effects of DDD based on examples of concrete modeling and implementation.

"Chapter 5 Architecture" in this book provides a more detailed explanation of the content of this article. Please purchase if you like.

Twitter also accepts questions about DDD and through a service called "Question Box". Please follow me if you like.

@little_hand_s

Recommended Posts

[DDD] Domain Driven + Onion Architecture Overview
Answered questions about DDD [Domain Driven Design]
What Is Domain Driven Design Trying to Solve [DDD]
[DDD] What is the most accessible architecture to get started with Domain Driven Design?
What is the difference between the responsibilities of the domain layer and the application layer in the onion architecture [DDD]