C# – Should an Interface Be Defined in the Infrastructure Layer?

cclean-architecturedomain-driven-design

Overview

If an application is being developed following a clean architecture / DDD approach, my understanding is that the application core or domain layer should contain classes and interfaces that directly model the business logic and represent concepts and events that the end user of the application understands and has a stake in.

In my case, I'm trying to implement a service but I want this implementation to rely on other services that are abstracted behind an interface (for easy swappability/testability). The issue is that the abstraction is only tangentially related to the business logic, so I'm not sure whether to create the interface (and associated events it publishes) in the domain layer or the infrastructure layer.

Background

I'm trying to develop an ASP.NET Core application using a Clean Architecture approach, with separate projects for the API, application core/domain logic and infrastructure.

The gist of this project is to serve as a backend for an SPA that presents an "order dashboard" to sales managers, allowing them to track the progress of orders belonging to different product consultants within the company branch they're in charge of.

In my domain layer, I've defined events, entities and services that I'm fairly confident belong there, because they're directly involved in modelling the business logic and represent things that the end user (the sales managers) would understand and have a stake in:

However, the way I plan to implement IBranchStateMonitor is to make it subscribe to order event streams within EventStore and then query the database for that particular order (through an EF Core DbContext) when events for it are published (in order to determine if the state of the order has changed in a manner relevant for this application).

I want to decouple the logic for querying the current state of orders from the logic used to detect when the states of the orders may have changed. For example, instead of subscribing to event streams in a cloud-based service, I might prefer a simpler alternative that involves just prompting BranchStateMonitor to refetch the states of the orders from the database at regular intervals. Based on that, I'd want a class structure like this:

Here's the question: should I define IOrderChangeNotifier and OrderChanged within the domain layer or within the infrastructure layer?

Best Answer

The most effective designs I have seen isolate the domain model in the local process; information from "somewhere else" is passed to the domain model as in memory values. (In effect, the domain model is "just" an in memory finite state machine).

Thus, the protocol for fetching those values across a process boundary belongs somewhere else -- for instance, in the application. All of the interfaces, abstractions, etc that you require for describing and executing those protocols lives somewhere else.

Dependency Inversion Principle suggests that the definition of the abstraction lives with the client code, which in this case is the application.

SAGE suggests that what you really want is for the less stable parts to depend on the more stable parts -- which could mean that your bespoke application code depends on a stable general purpose library.

But regardless, outside of the domain model, which lives entirely within the functional core.

See also Boundaries, by Gary Bernhardt.

Related Topic