From 3-Layered to DDD Architecture in one step

iamprovidence
4 min readJul 24, 2022

--

Any architecture is aimed to make your code better. The more complex your system becomes, the more your architecture evolving. For some projects, it is enough to implement your code in controllers, while others require a more complex approach.

Currently, most projects implement 3-layered architecture. It achieves separation of concern by introducing next layers:

  • Presentation layer (User-Interface, UI) — usually is responsible for interaction with client.

(Important to understand that client can be a real person ‘pressing’ buttons on screen but also HttpClient that sends request with API endpoints)

  • Business logic layer (BLL, Domain) — represents concepts of the business. It rules what your application is doing and makes it so unique comparing to others.
  • Data Access layer (DAL) — persists data in memory and keep state of your application

With such architecture, layers depend on each other and execute API of deeply lying layers as follows:

Dependencies in 3-layered architecture

Although such architecture solves most of the issues, it has its own drawbacks:

  • The main component in such system is Data Access and not Business Logic, which force developers to think about persistence in the first place.
  • Data Access becomes hard to change, since all other layers depend on it.
  • Layers are strongly coupled and every change to DAL will affect others.

DDD architecture solves those issues by making Business logic a core part of your system instead of Data Access. It can be achieved with dependency inversion.

(Yes, exactly, that mythical letter ‘D’ from SOLID everybody talks about and no one understands)

Take a look at the picture below. All the components remain the same, what does change is how they execute and depend on each other.

Dependencies in DDD architecture

What does it change? Apart from that all advantages of 3-layered architectures remain, we also fix its issues:

  • Business Logic stands as core component of the system and can be reused
  • Business Logic becomes hard to replace. And that is okay. You can not imagine a system that in one day stops doing, for example, online shop and starts banking. On the other hand, frameworks constantly developing and switching from one technology to another is a common thing
  • Every change to BLL will affect others. Which is correct. The only time a system should change it is when its domain changes, and not frameworks.

How do you achieve that?

Let's take a closer look at the dependencies between Business Logic and Data Access from the very first picture.

OrderService requires some data to work, and it gets it by executing SqlOrderRepository. As we see, BLL depends on DAL. Let's turn around the dependency arrow.

(I hope you noticed I have emphasized “to turn around the dependency arrow”. There is a reason for that. It is extremely important to understand this powerful architectural technique)

We got unlucky 😥. Business service depends on implementation rather than on interface. Let’s introduce one.

The next step would be to move the interface of repository to Business logic layer.

And Voilà! We're done 😃.

As a result, OrderService still depends on IOrderRepository, but now dependencies between layers are inverted. BLL still executes classes in DAL, but DAL depends on BLL.

This is so-called dependency inversion when execution and dependencies flows are inverted.

We also got a nice bonus. We have reduced coupling between modules, and now can replace DAL with any arbitrary technology (EF, MongoDB, Redis etc) with no effect on our Business logic.

I hope you have no longer difficulties with understanding dependency inversion. Give it a clap if so 👏

Buy me a coffee if you want to support me ☕️

And don’t forget to follow to learn more about Software Architecture ✅

--

--

iamprovidence

👨🏼‍💻 Full Stack Dev writing about software architecture, patterns and other programming stuff https://www.buymeacoffee.com/iamprovidence