2

I recently joined a large team/project that uses the repository pattern and dependency injection throughout the solution. I noticed that the repository interfaces were located in a Data layer project, requiring the Business layer project to depend directly on it. It is my understanding that when using DI you would want to reverse this dependency to decouple the business logic from data access (Data references interfaces from the Business layer). When I suggested this to the team, there was a mixed reaction. They didn't see the benefit and argued against it ("everyone knows not to directly reference the concrete types", "we'll never need to swap out our data access technology", etc.).

Is it good practice to keep repository interfaces in the same project as the implementation (Data layer)? If the Business layer only references the repository interfaces from Data layer, are there any drawbacks to this setup?

3 Answers3

2

Well personally I've always had the dependencies "flowing" from the lowest level to the highest level. The UI needs to interact with business logic, therefore it depends on the services interfaces. The services/business logic needs data access, therefore it depends on the repository interfaces to do so.

This is the general approach I've seen in most codebases.

user9993
  • 5,833
  • 11
  • 56
  • 117
  • 1
    That's sad considering this is the problem that [DI is meant to solve](https://stackoverflow.com/a/9503612/181087). Loose coupling implies that when you add a dependency, you don't drag other dependencies with it. – NightOwl888 Jun 07 '17 at 12:21
  • I think you are totally misunderstanding what I mean. I use a composition root. Of course the Service layer is going to depend on some kind of IRepository interface if it needs a repository. DI does not mean that the service can somehow magically function if theres no IRepository available. @NightOwl888 – user9993 Jun 07 '17 at 12:49
  • 2
    If you move the interfaces to the business/domain layer, you can remove the dependency on the data layer at the project level which feels like a cleaner approach. I like the idea of building/testing around the business logic without being tied to external dependencies. – user2577288 Jun 08 '17 at 14:43
2

It all depends. A wise man once said:

abstracts [should be] owned by the upper/policy layers

You might have read Mark Seemann's excellent book Dependency Injection in .NET, where he show cases this principle (see section 2.2 in the 1st edition and chapter 3 in the 2nd edition) with an example for the exact scenario you are describing (i.e. repository interface as part of the Domain Layer).

The most important argument that Mark Seemann gives for doing this is because it allows you to replace your Data Access technology with a different one, which might be a more likely scenario you might think, especially considering the world we live in right now where everything moves to the cloud and in the cloud you might not have (or want) to use the same Data Access technology.

But there are other reasons for wanting to isolate your core layer (the Domain layer) from the rest of the application and let everything depend on the most important part of the application.

One thing that comes to mind is to make it impossible for developers to accidentally couple this layer to Volatile (or impure) parts of the system that make it harder to change later on. The dependency on your Data Access functionality is one obvious thing, because it can make testing harder, but also think about accidentally coupling your Domain layer to System.Web, making it possible for developers to use HttpContext in that part of the system. Chances are quite big that once you have a dependency (from Domain layer to Data Access layer), it will become much harder to invert over time.

On the other hand, whether this high degree of isolation is beneficial to your application does obviously depends on a lot of factors. And especially when the application is already designed this way, it might be better to focus your attention on other improvements first.

Don't forget that the most important part of Dependency Inversion Principle (DIP) and Dependency Injection (DI) is that classes depend on abstractions. This enables loose coupling, and loose coupling improves maintainability. Since those developers already practice DI, they are already in a good place.

A typical improvement that I make is to get rid of most of the repositories, and introduce higher-level concepts such as a generic abstraction over business operations, a generic abstraction over queries and sometimes domain events. This limits the use of repositories to inside the Domain layer. When introducing this, this is a great moment to invert the dependencies for new (or migrated) code that uses these concepts instead of I[EntityName]Repository and I[EntityName]Service abstractions that are typically in violation of most of the SOLID principles anyway.

Another thing I advocate is to prevent the core layer of your application from having a dependency on a logger abstraction of some third party logging library. This again boils down to the DIP that states that the application should own the abstractions, which is not the case when the application depends on a third party abstraction. That's why I promote things like this.

Steven
  • 166,672
  • 24
  • 332
  • 435
-3

It belongs to data access layer in an application.

Rajesh
  • 1
  • 1