hasrthur
hasrthur

Reputation: 1490

Doesn't repository pattern in clean architecture violate Dependency inversion principle?

From what I have read and seen clean architecture assumes that you have some entities which know nothing about persistence though at the same layer as they reside there might be an interface which has a purpose to be a contract on how the entity should be read/updated/deleted.

// project Core
public class CarModel
{
    public string Name { get; set; }

    public void SomeImportantBehavior {}
}

public interface ICarModelRepository 
{
    CarModel FindByName(string name);
    CarModel Add(CarModel carModel);
}

Meanwhile another layer will hold the implementation of the interface:

// project Infrastructure or Persistence
public class CarModelRepository : ICarModelRepository
{
    public CarModel FindByName(string name)
    {
        return new CarModel { Name = name }; // the implementation is not really important here
    }

    public CarModel Add(CarModel carModel) {
        // somehow persist it here
        return carModel;
    }
}

So I've got a question: doesn't repository implementation violate the DiP principle? Since it not only depends on abstraction but also on concrete implementation (CarModel in this case)?

Another example of this is here.

P.S. CarModel is a domain model with behavior.

Upvotes: 0

Views: 1784

Answers (2)

felipeaf
felipeaf

Reputation: 404

In your example, the Repository implementation (which is in infrasctructure layer, outer circle) creates an entity (domain layer, inner circle), so the lower level class,Repository (implementation,) depends on the entity class (higher level, inner circle). This is the right direction. DiP Principle says you cannot have the opposite, your entity class should not depend on an infrastructure class.

BUT, you missed another thing that uncle bob sad in his book. He says the data that cross boundaries between layers should be simple data structures, not object with logic. In others words, the repository should return an Data Transfer Object, not an entity object.

Upvotes: 0

meJustAndrew
meJustAndrew

Reputation: 6623

You are missing a bit the point of Dependency Inversion principle. This principle is supposed to reflect the decouple between different modules. In other words, you shouldn't instantiate your objects where you need them, but receive them as parameters. This is the base principle for dependency injection.

To make things clear, let's suppose that you have a class Controller that uses your Repository. Without DI, at first it would look like this:

class Controller
{
    private CarModelRepository _repository;

    public Controller()
    {
        _repository = new CarModelRepository();
    }

    public void DoSomething()
    {
        //use repository here
    }
}

Looking in the constructor of this class, you can see that it creates its own dependency by doing

_repository = new CarModelRepository();

In this case, the Controller contains a dependency to the concrete CarModelRepository.

If you want to apply Dependency Inversion principle, then you will remove the instantiation there and inject the dependency as an abstraction. In this case, the controller will look like this:

class Controller
{
    private ICarModelRepository _repository;

    public Controller(ICarModelRepository repository)
    {
        _repository = repository;
    }

    public void DoSomething()
    {
        //use repository here
    }
}

Notice that now the repository is ICarModelRepository which is the interface, not the concrete type anymore and the Controller does not create it (as a concrete dependency), but it receives it as an abstract dependency (the interface).

This is an example of what Dependency Inversion principle means and in your case, you are not sending a dependency to the repository, but you are sending an object which it needs to save. Objects that represent modules of the application are things that you should consider as dependencies and inject them, as the case of a repository. Your domain objects are not the dependencies to be injected so, to answer your question:

doesn't repository implementation violate the DiP principle?

No, it doesn't.

Upvotes: 1

Related Questions