Denis Brandi
2 min readOct 30, 2021

--

Few comments based on your reply:

1. Use cases can receive only entities, if they receive DTOs it means they know about the outer layer and so the dependency rule is violated (Dependencies point only inwards never outwards, so framework layer sees interface adapter layer which sees the use case layer which sees the entity layer).

2. Domain layer must be independent from the persistence.

In your code example the use case knows everything about how data is persisted and any change to the persistence logic will require a code change in the use case class.

Imagine you decide to add caching for products, in your example you would need to add a dependency to `GetProductUseCase` for the extra caching logic.

Basically your use case is doing both application level business logic and persistence logic.

3. The interface adapter is not `per framework`, it is `per domain model`.

1 domain model -> 1 interface adapter.

This goes back to Ports and Adapters architecture (Hexagonal architecture) and Clean Architecture is mostly based on that.

4. By looking at the code it feels like your team starts developing a feature from the persistence layer rather than the business logic layer, given how much persistence logic is leaked in the use cases.

The correct flow of development when working with Hexagonal, Onion or Clean should be the following:

a. You start writing the use case class which will make you write the port of the persistence in the process (repository interface, part of application layer/use case layer).

Outcome: GetProductUseCase + ProductRepository.

b. Now that the port is designed you need to implement it (or its new methods) and so you write the repository class (interface adapter), which in the process will make you write the framework abstraction (still part of the interface adapter layer).

Outcome: ProductRepositoryImpl + Mappers + GraphQLProductService + RestProductService + DBProductDao.....

c. Now that you have the framework abstraction (interface adapter layer) it is time to write the implementation of such interface (framework layer)

Outcome: GraphQLProductServiceImpl + RestProductServiceImpl + DBProductDaoImpl.

Hope this is more clear now

--

--