1
votes

How to reuse code in an application layer without mapping?

Let's have an application service OrderService with AddOrder(OrderDto) method. The method is used by rest api. A controller method calls OrderService.AddOrder(OrderDto) and it maps the OrderDto param to the Order entity. The Order entity is then added to a repository. The mapping is done there because OrderService and AddOrder is an application interface.

It would be nice to reuse the code and call OrderService.AddOrder(orderDto) not just from the controller but also from another method in OrderService or even from another application service.

However, it always needs mapping from an entity to DTO inside the application service method before calling another application method and then mapping the result back from DTO to entity.

=> Useless mapping in the same layer. With the system going bigger it ends up with mapping from and to DTO everywhere. BAD.

It would be good to avoid the mapping inside and do it only on the top of the application interface. We could write a service accepting an domain model (entity) instead of DTO in the params: OrderDomainService.AddOrder(order).

This resolves the "mapping problem". Domain services can call each other without mapping and Application services can also call the domain services. However, it means a domain service has to use a repository from Infrastructure layer to load data because we moved the code from an application service method to the domain service method. This creates a dependency from Domain layer to Infrastructure layer.

=> Wrong dependency. Infrastructure should depend on Domain, not Domain on Inrastructure.

How to resolve that?

The application service shouldn't contains methods with params of domain model types. The domain service can't use repository.

Where to write the reusable code then?

Or I'm wrong and the domain service can use the repository. Via an interface in Domain layer it wouldn't be dependent directly on the infrastructure layer. However then it would end up with a controller method calling an application service method calling an domain service method.

1

1 Answers

0
votes

I think you are on the right track moving towards domain services when it comes to reusing logic. Application services are suited for orchestrating specific use cases and only call different actions in the correct order. Domain logic should always be in the domain layer.

Concerning the infrastructure dependency: for using repositories in DDD (or clean architecture) the repository interfaces should reside in the domain layer while the concrete implementation of these interfaces reside in the infrastructure layer.

Both the application layer and the domain layer should depend on the interfaces rather than the infrastructure layer then.

The domain service can't use repository.

So it can use a repository by being dependent on the repository interface while the concrete infrastructure repository is injected at runtime following dependency injection.

However then it would end up with a controller method calling an application service method calling an domain service method.

If there is no justification for an application service as there is no real orchestration required you at least don't break any dependency rules when letting a controller call domain classes directly, e.g. if the use case is too simply and no abstraction between the API layer (here a controller) and the domain layer is needed. But I usually rather like to use Application services as they make the domain layer independent from this outer layer and allow both, the domain layer and the API layer to evolve independently from each other.