Search code examples
asp.net-coreasp.net-core-webapiclean-architecture

In clean architecture, is the presentation layer allowed to communicate directly with the infrastructure layer?


I have an application using the classic clean architecture with all the dependencies set up as described (i.e. flowing inward). I have an external service I wish to use in my project, so defined the functionality (objects that interact with the service, some interfaces etc.) for interacting with that service in the Infrastructure layer.

Currently the Presentation layer is consuming the external service directly from the Infrastructure layer.

A question about this would be: is the presentation layer communicating directly with the infrastructure layer acceptable, or must everything go via the application layer?

Ideally I would like the presentation layer to call the application layer so that I can reuse some of the functionality it has available (for things such as validation amongst others) but then with the infrastructure layer not knowing about the application layer, I would need to define the external service objects in the application layer.

I would rather avoid doing so as these are service specific rather than application specific. I would much rather have them defined in the infrastructure closest to where they are used.

So, is there a way to reuse the interfaces defined in the infrastructure layer for this external service or will I just have to suck it up and have some duplication (i.e. define interfaces in the application layer that my external service in the infrastructure layer implements)?


Solution

  • In Clean Architecture, you generally want to define interfaces in the Application layer. This is because all your business logic should live in and be dictated by the application/domain layer. It should define the interfaces it needs to send requests to and receive responses from the outside world. This allows you to build out your application's unique functionality without concern for how you will get/persist data, call external apis, etc.

    The Infrastructure layer should be aware of the Application layer so that it can implement the interfaces. Then, the Presentation layer should invoke the Application layer. Depending on how dogmatic you want to be with CA principles, the Presentation layer should either NOT reference/use the Infrastructure layer at all (in this case, you would use some compositional root project to build a DI container), or it should reference the Infrastructure layer ONLY as a means to register the Application's interfaces with the Infrastructure's implementations for a DI container.

    You shouldn't define "external service objects" in an Application layer; rather, you define only domain objects and interfaces needed by your app to do its thing. Then, the concerns of "external service" are addressed in the Infrastructure's implementation and its concerns usually look something like:

    • Knowing how to call the external service
    • Having models for sending requests to and receiving responses from the external service
    • Mapping application/domain requests from the application/domain to the external service models
    • Mapping external responses back to some application/domain model