Reputation: 1490
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
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
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