architecturesoftware-designclean-architectureentities

Dependency inversion (DIP) in clean architecture's entities


I am fairly new to software architecture, which is probably the reason for me asking this question at all, but: How do I ensure the dependency inversion principle (DIP) when designing entities in a clean architecture?

To be more concrete, I designed an architecture based on the clean architecture with a domain model containing some entities with one entity being e.g. Entity. Since the services and use cases depend on these (concrete) entities, I asked myself whether or not I need to apply DIP here and wrap an abstraction around my entity, e.g. an interface called IEntity. Should I use DIP this way in my example? Note that IEntity would also have all the public getters and setters of Entity.

The programming language for this project is Java, but I am generally more interested in a language-agnostic answer to this problem.

I researched on the internet and found that DIP in context with clean architecture focuses on higher-level modules not depending on lower-level modules. Since this is clear to me, because this is central in clean architecture, this was not solving my problem regarding entities respectively dependencies to entities.


Solution

  • The dependency inversion principle states:

    Abstractions should not depend on details. Details should depend on abstractions.

    The entities define "enterprise business rules". These are rules that are application (and therefore use-case) independent. So the entities are more abstract then the use cases. So when a use case references an entity you have a dependency from to a more abstract part. Thus you don't need to reverse the dependencies. This is the reason why the arrows in the clean architecture point inwards. They always point in the direction of the more abstract concept.

    clean architecture

    If an enitity needs something from an outer layer it can not just reference it. This would violate the DIP. In those cases you need to introduce an interface in the entities layer and provide an implementation from an outer layer. This can be the case when you want to decouple entities from frameworks or libraries.