The misunderstanding of Domain Driven Design
There seem to be two mainstream approaches in Java application development: the domain driven approach, and the “fat service layer” or Transaction Script approach. As an architect, I’ve been investigating both methodologies by reading about both of them and applying them in real life enterprise projects. It is at the least amusing to see how followers of each approach think of the other. An example of how developers (disappointing to realize that these people are co-developers) react on each other’s approach can be seen in the reactions to Arjen Poutsma’s post.
In some discussions I recently had with developers as well as other architects, I noticed that Domain Driven Design and Rich Domain Model are interpreted as “put everything in the domain model”. This means (according to some of them) that each object should have a “save” method to persist its state, external systems calls are initiated by the domain objects, and so on and so forth. I have to agree with them that such an approach would not be practical at all. All it would lead to is bloated domain objects of which the real purpose is hidden in hundreds of lines of boilerplate code. However, I don’t believe that Domain Driven Design is about any of this at all. And looking at Eric Evans’ (the writer of the book Domain Driven Design) sample application, my thoughts are confirmed.
Domain Driven Design is an approach that describes the approach to designing the business layer. It doesn’t say much about the other layers of an application. The main advice is to base the domain model on the language your customer uses: the ubiquitous language. This means that you should not have a method “setAddress” on a Customer instance if your customer talks about “register a relocation”. In fact, the last application I developed hardly contained any setter on any domain instance at all.
You might wonder what happened to the other layers if DDD is really only about the business layers. Well, the service layer is still what it was, although it tends to contain less code. All that is needed in the service layer is to retrieve the correct domain instance(s) from the repository, call the appropriate methods on them and persist their new state by placing them back in the repository. With this approach, the logic of changing the state is located where the state is kept, in the domain object. The application logic, such as persistence, transactions, calling external application, raising application events, is placed in the service layer.
During one of my discussions, somebody pointed out that according to the Domain Driven Design book one should only create a service if the logic cannot be placed in any of the domain objects. Well, the book does say that, but the service the book talks about is not the type of service that you find in the service layer. The book talks about Domain Services. Whether you decide to use one of these services is completely independent of the use of services in the service layer, which are also referred to as application services.
I can conclude that applications where domain driven design has been applied are not really that different from other applications, with the exception of the domain model itself. However, this richer model tends to make applications more maintainable and easier to understand as the model exposes the language that the customer actually uses. So, in the end, Domain Driven Design does not have to be as scary as many people think. It is just, as one of my colleagues pointed out, a set of best practices for Object Oriented design.