How should we pass data between layers in the Clean Architecture?

Viewed 1696

I have been reading "Clean Architecture" by Robert Martin and have been struggling to understand one thing: How should we pass data between layers in the "Clean Architecture"?

According to Robert Martin:

The important thing is that isolated, simple data structures are passed across the boundaries. We don’t want to cheat and pass Entity objects or database rows. We don’t want the data structures to have any kind of dependency that violates the Dependency Rule.

If I understand it correctly, we should always pass DTOs between layers. For example, Business Logic layer should never return Domain Entity back to UI layer, it should map Domain Entity to DTO and return it instead.

Similarly, Business Logic layer maps Domain Entity to DTO and passes it to Data Access layer, so Data Access layer knows nothing about Domain Entity.

It is kind of scary, because we have to perform 8 mappings for one request (4 in -> and 4 out <-) Please see the picture below.

Please note that arrows on the diagram show the data flow, not the dependencies.

enter image description here

I tried to find good examples but they only confused me. For instance, some examples have Domain Entity which is directly used by Data Access layer, so that Domain Entity dictates the structure of the table in the database (Domain entity used as an Entity Framework Entity).

But what if one day I decide to change the table structure? It means I'll have to make changes not only in my Data Access layer, but also in my Business Logic layer as well. It defeats the "Plugin Architecture".

What is the correct way?

1 Answers

Maybe it is not perfectly aligned with Uncle Bob's clean architecture but this is how I pass data across boundaries in my clean architecture based projects:

  • request object (DTO) from view to controller
  • request model (DTO) from controller to use case interactor
  • domain entity to/from repository
  • response model (DTO) from use case interactor to presenter
  • response/view model (DTO) from presenter to view

In some cases I cheat and my response models contain domain entities. I keep this pragmatic compromise as long as I don't see severe issues.

This setup works well for me in several projects. The number of mappings has more pros than cons. The domain model is still independent from persistence layer as the mapping from domain entity to e.g. table rows can be changed in the repository implementation easily at any time.

Related