Search code examples
domain-driven-designddd-repositoriesddd-service

Infrastructure repository calling a domain service


I have an application service (AppService) and an infrastructure repository (InfraRepo) that reads data from an external data provider. The AppService calls InfraRepo and returns data to the client. I have the following requirement: I have some filtering conditions and business logic. For that I created a Domain Service (DomainService) and injected it inside InfraRepo. Once I retrieve the data from the external data provider (in InfraRepo) I call the domain service, pass the data there, and get the result back. I then return the result back to the app service which is mapped to the Dto and returned to Client. Is it correct to call a domain service inside an infrastructure repository.


Solution

  • Rather than discussing purely DDD it would seem that we could bring several concepts together in a discussion to address the question and also highlight the benefits of each of the concepts.

    Depending on your familiarity with DDD, this article provides a good overview of DDD. It refers to DDD building blocks as being: entity, value object, aggregate (root), service, repository and factory. In the question there is discussion of services and a repository. There is no discussion of an entity or a value object; therefore I am unsure of the data that is being returned by the repository.

    How these elements interact can be addressed by the Onion Architecture which is discussed here. In this case it states that the domain should be at the core, then domain services, then application services and finally the outer layer being the UI, Tests and Infrastructure. In this model data access (repositories) are infrastructure. So the key is that the dependencies flow from the outer layer to the inner; that is, the domain does not rely on anything other than itself. This was in contrast to the traditional 3-tier architecture in which everything depended on the data access code, with the business code between the UI and the data access code. Onion architecture would say that the repository (InfraRepo) belongs in the outer layer, the application service in the next layer and the domain service in the next. Therefore the AppService would never call InfraRepo because control should never flow to the outer layers, only in from the outer layers. Instead the AppService would call DomainService which would call the Domain (that is, the business logic). The Domain would utilize the abstraction (an interface or pure virtual class) it defines for data access. InfraRepo would implement this abstraction and ideally the domain class would use an IoC container to get the InfraRepo instance while only being aware of the interface. That is, the IoC container acts like a Factory mentioned above in the building blocks of DDD.

    SOLID principles have been around for awhile and deal with the finer aspects of class design to allow for flexible and robust code. In this case the Dependency Inversion Principle can be realized via the IoC container as an additional argument for its utilization. Also the definition of the interface for the repository should keep the Interface Segregation Principle in mind.