When developing a project following Domain-Driven Design and clean architecture, one might ask themselves the following question: Should my domain models implement interfaces? After all, a good programmer should program against abstraction, not concretions. But then why do most public examples of domain-driven design projects on the internet not create interfaces for their entities? This is one of the questions I came across while implementing a DDD project, and it made me think of reasons for and against implementing interfaces for models that I'd like to share with you.
Why You Might Want to Create an Interface for Your Models
Domain models encapsulate a rich understanding of the processes and rules of a domain 1 and depending on the programming language you use, you might find yourself encapsulating the properties behind getters and setters. If that is the case, you will have an object that only exposes methods, which means that it could be abstracted by an interface, given that no properties are publicly exposed.
SOLID
Since we aspire to be great programmers, we want to apply SOLID principles pervasively through our project so as to build upon a good foundation. The 'I' in SOLID stands for Interface segregation principle and it states:
No code should be forced to depend on methods it does not use.
The idea is for "consumers" of the entity to rely on interfaces offering the methods they need, so as to decouple the consumers from the entity itself. Decoupled code is much easier to replace, refactor, and work with than coupled code.
Unit Tests
Having interfaces helps with unit testing. When creating an unit test for a module that depends on a model's interface, there is no need to instantiate complex domain models just to test a path of the service. Creating a mock model that complies with the model's interface can be easier than instantiating a real one.
The Case Against Interfaces For Domain Models
The theory might suggest that domain models should be kept behind interfaces, but there are good reasons why not to do that.
Adding Unnecessary Complexity and Abstraction
The idea of having decoupled layers is to be able to replace them eventually. Perhaps one day you will be using a relational database, and the next day you will need to use a non-relational one. But unless you're designing a framework, the reality is that you will never have to replace the domain layer. Your domain is the most stable dependency you will have in your other layers. It is the core of the application, and replacing it would mean creating an entire different application. Additionally, adding seams into your application just to follow a design principle blindly can add complexity without any benefits.
Domain Models Should Be Simple
Domain models tend to encapsulate simple domain behavior. This is because domain services are the ones responsible for carrying out the complex business behavior that include more than one model. Given this, and the fact that model contain deterministic behavior, it can be argued that a domain model interfaces would not provide a big benefit when it came to writing unit tests for modules that rely on domain models. If you find yourself working with complex models, that is a sign that the domain should go through a distillation process to simplify it.
Conclusion
It is not a white-black issue. I would consider both of them to be valid interpretations of DDD, clean architecture, and SOLID. Personally, I side more with not implementing since adding extra abstractions has a cost, and as long as the models stay simple, unit testing modules that depend on domain models should not be a problem.
Top comments (0)