On Domain-Driven Design, Anemic Domain Model, Code Generation, Dependency Injection and More…
Eric Evans has formulated what domain-driven design (DDD) is. Martin Fowler is a great supporter and advocate of DDD. These are remarkable names and it is almost certain they are supporting something worth. And I’m not here to argue with that. Maybe I’m trying to justify the way I’ve been writing software, or maybe I’m trying just to clear things and be constructive. Let’s see.
What is at the core of domain-driven design – the abstract notions of the domain, the domain model, the ubiquitous language. I’ll not go into details with that – for those interested there is wikipedia (with lots of references to read in the footer). This is all very good in theory, and the domain-driven way of building software should appeal to everyone – after all that software is being built for the benefit of that domain, not for the benefit of architects, developers or QAs.
But now comes the practical part – how to implement DDD? I’ll answer that question in its contemporary context – that is, using frameworks like spring and hibernate. And I’ll justify their usage. Spring is a non-invasive dependency-injection framework. DI is also strongly supported by Fowler, and is considered a good way to implement DDD. Hibernate is one way to use objects when working with a relational database. Another way is to use JDBC and construct the objects manually, but that is tedious. So hibernate doesn’t influence the architecture part – it is an utility (very powerful one, of course).
Throughout this post I’ll use hibernate and spring as “given”, although they may be changed with any DI framework and any ORM or other persistence mechanism that relies on objects.
The accepted way to implement DDD with spring and hibernate is:
- use
@Configurable
to make the domain objects eligible for dependency injection (they are not instantiated by spring, so they need this special approach)
- inject repository objects in the domain objects in order to allow the domain objects to do persistence-related operations
- use a thin, stateless, transactional service layer (a facade) to coordinate the domain objects
Implementation and description of this approach is shown in this extensive article. Another example (without spring) is http://dddsample.sourceforge.net/. I’ll discuss both later.
The alternative to this approach is the anemic domain model. It is considered an anti-pattern, but at the same time is very common and often used. The features of the anemic data model are simple – the domain objects have no business logic inside them – they are only data holders. Instead, the business logic is placed in services.
The reason this is considered an anti-pattern is because, first, this seems like a procedural approach. It is breaking the encapsulation, because the internal state of the object is, well, not internal at all. Second, as the domain object is the center of the design, it is harder to change it if its operations don’t belong to it, but to a number of stateless service classes instead. And domain-driven design is aimed at medium-to-large scale applications, which change a lot and need an easy way to make changes fast, without breaking other functionality. Thus it is important to have all the functionality of the object within the object itself. This also makes sure that there is less duplication of code.
So, instead of having a service calculate the price: ProductServiceImpl.calculatePrice(complexProduct)
we should simply have ComplexProduct.calculatePrice()
. And so whenever the domain experts say that the price calculation mechanism changes, the place to change it is exactly one and is the most straightforward one.
When simple operations are regarded, this looks easy. However, when one domain objects needs another domain object to do its job, it becomes more complicated. With the anemic data model this is achieved by simply injecting another Service into the current one and calling its methods. With the proposed DDD it is achieved by passing domain objects as arguments.
In my view, the domain object, which is also the hibernate entity, has its dependencies already set. But not by spring, because spring can’t know which exactly domain object to inject. They are “injected” by hibernate, because it knows exactly which (identified by primary key) domain object should be placed in another domain object. So, a little odd example – if a Product
has rotten and has to dispense smell in the warehouse, it has to call, for example, warehouse.increaseSmellLevel(getSmellCoeficient())
. And it has its precise Warehouse
without any interference from spring.
Now, here comes another point where I disagree. Most sources (including the two linked above) state that repositories / DAOs should be injected in the domain objects. No, they shouldn’t. Simply calling “save” or “update” doesn’t require knowledge of the internal state of the object. Hibernate knows everything anyway. So we are just passing the whole object to the repository.
Let’s split this in two – business logic and infrastructure logic. The domain object should not know anything of the infrastructure. That might mean that it should not know it is being saved somewhere. Does a product care of how it is stored ? No – it’s the storage mechanism that’s “interested”. And here are the practical disadvantages:
- CRUD is implemented by simply wrapping repository calls in all domain objects – duplication of code
- the domain object is transitively dependent on persistence – i.e. it is not a pure domain object, and if repositories change, it has to be changed as well. And in theory it should be changed only when the domain rules and attributes change
- people will be tempted to include transaction, caching and other logic inside the domain object
I’ll open a bracket here about a proposed solution in one of the above articles for making duplication of code, and boilerplate code easier to handle. Code generation is suggested. And I think code-generation is a sin. It moves the inability to get rid of duplicated or very similar code and abstract it, to tools. The most striking example is generating ProductDAO, CategoryDAO, WarehouseDAO, etc, etc. Generated code is hard to manage, cannot be extended and relies heavily on external metadata, which is definitely not an object-oriented approach.
Speaking of the repository, in the proposed examples each domain object should have a repository, which in turn will call the persistence mechanism. What do we get then:
User presses “save” in the UI > UI calls save on the service (in order to have transaction support) > Service calls save on the domain object > domain object calls save on the repository > the repository calls save on the persistence mechanism > the persistence mechanism saves the object.
Is it just me, or calling the domain object is redundant here. It is a pass-through method that adds nothing. And since a lot of functionality is related to CRUD (yes, even in big business applications), this looks quite bad to me.
And finally, I find the @Configurable
approach a hack. It does some magic in the background, which isn’t anything of the common language features (and is not a design pattern), and in order to understand how it happens you need a great deal of experience.
So, to summarize the big mess above
- domain objects should not be spring (IoC) managed, they should not have DAOs or anything related to infrastructure injected in them
- domain objects have the domain objects they depend on set by hibernate (or the persistence mechanism)
- domain objects perform the business logic, as the core idea of DDD is, but this does not include database queries or CRUD – only operations on the internal state of the object
- there is rarely need of DTOs – the domain objects are the DTOs themselves in most cases (which saves some boilerplate code)
- services perform CRUD operations, send emails, coordinate the domain objects, generate reports based on multiple domain objects, execute queries, etc.
- the service (application) layer isn’t that thin, but doesn’t include business rules that are intrinsic to the domain objects
- code generation should be avoided. Abstraction, design patterns and DI should be used to overcome the need of code generation, and ultimately – to get rid of code duplication.
Eric Evans has formulated what domain-driven design (DDD) is. Martin Fowler is a great supporter and advocate of DDD. These are remarkable names and it is almost certain they are supporting something worth. And I’m not here to argue with that. Maybe I’m trying to justify the way I’ve been writing software, or maybe I’m trying just to clear things and be constructive. Let’s see.
What is at the core of domain-driven design – the abstract notions of the domain, the domain model, the ubiquitous language. I’ll not go into details with that – for those interested there is wikipedia (with lots of references to read in the footer). This is all very good in theory, and the domain-driven way of building software should appeal to everyone – after all that software is being built for the benefit of that domain, not for the benefit of architects, developers or QAs.
But now comes the practical part – how to implement DDD? I’ll answer that question in its contemporary context – that is, using frameworks like spring and hibernate. And I’ll justify their usage. Spring is a non-invasive dependency-injection framework. DI is also strongly supported by Fowler, and is considered a good way to implement DDD. Hibernate is one way to use objects when working with a relational database. Another way is to use JDBC and construct the objects manually, but that is tedious. So hibernate doesn’t influence the architecture part – it is an utility (very powerful one, of course).
Throughout this post I’ll use hibernate and spring as “given”, although they may be changed with any DI framework and any ORM or other persistence mechanism that relies on objects.
The accepted way to implement DDD with spring and hibernate is:
- use
@Configurable
to make the domain objects eligible for dependency injection (they are not instantiated by spring, so they need this special approach) - inject repository objects in the domain objects in order to allow the domain objects to do persistence-related operations
- use a thin, stateless, transactional service layer (a facade) to coordinate the domain objects
Implementation and description of this approach is shown in this extensive article. Another example (without spring) is http://dddsample.sourceforge.net/. I’ll discuss both later.
The alternative to this approach is the anemic domain model. It is considered an anti-pattern, but at the same time is very common and often used. The features of the anemic data model are simple – the domain objects have no business logic inside them – they are only data holders. Instead, the business logic is placed in services.
The reason this is considered an anti-pattern is because, first, this seems like a procedural approach. It is breaking the encapsulation, because the internal state of the object is, well, not internal at all. Second, as the domain object is the center of the design, it is harder to change it if its operations don’t belong to it, but to a number of stateless service classes instead. And domain-driven design is aimed at medium-to-large scale applications, which change a lot and need an easy way to make changes fast, without breaking other functionality. Thus it is important to have all the functionality of the object within the object itself. This also makes sure that there is less duplication of code.
So, instead of having a service calculate the price: ProductServiceImpl.calculatePrice(complexProduct)
we should simply have ComplexProduct.calculatePrice()
. And so whenever the domain experts say that the price calculation mechanism changes, the place to change it is exactly one and is the most straightforward one.
When simple operations are regarded, this looks easy. However, when one domain objects needs another domain object to do its job, it becomes more complicated. With the anemic data model this is achieved by simply injecting another Service into the current one and calling its methods. With the proposed DDD it is achieved by passing domain objects as arguments.
In my view, the domain object, which is also the hibernate entity, has its dependencies already set. But not by spring, because spring can’t know which exactly domain object to inject. They are “injected” by hibernate, because it knows exactly which (identified by primary key) domain object should be placed in another domain object. So, a little odd example – if a Product
has rotten and has to dispense smell in the warehouse, it has to call, for example, warehouse.increaseSmellLevel(getSmellCoeficient())
. And it has its precise Warehouse
without any interference from spring.
Now, here comes another point where I disagree. Most sources (including the two linked above) state that repositories / DAOs should be injected in the domain objects. No, they shouldn’t. Simply calling “save” or “update” doesn’t require knowledge of the internal state of the object. Hibernate knows everything anyway. So we are just passing the whole object to the repository.
Let’s split this in two – business logic and infrastructure logic. The domain object should not know anything of the infrastructure. That might mean that it should not know it is being saved somewhere. Does a product care of how it is stored ? No – it’s the storage mechanism that’s “interested”. And here are the practical disadvantages:
- CRUD is implemented by simply wrapping repository calls in all domain objects – duplication of code
- the domain object is transitively dependent on persistence – i.e. it is not a pure domain object, and if repositories change, it has to be changed as well. And in theory it should be changed only when the domain rules and attributes change
- people will be tempted to include transaction, caching and other logic inside the domain object
I’ll open a bracket here about a proposed solution in one of the above articles for making duplication of code, and boilerplate code easier to handle. Code generation is suggested. And I think code-generation is a sin. It moves the inability to get rid of duplicated or very similar code and abstract it, to tools. The most striking example is generating ProductDAO, CategoryDAO, WarehouseDAO, etc, etc. Generated code is hard to manage, cannot be extended and relies heavily on external metadata, which is definitely not an object-oriented approach.
Speaking of the repository, in the proposed examples each domain object should have a repository, which in turn will call the persistence mechanism. What do we get then:
User presses “save” in the UI > UI calls save on the service (in order to have transaction support) > Service calls save on the domain object > domain object calls save on the repository > the repository calls save on the persistence mechanism > the persistence mechanism saves the object.
Is it just me, or calling the domain object is redundant here. It is a pass-through method that adds nothing. And since a lot of functionality is related to CRUD (yes, even in big business applications), this looks quite bad to me.
And finally, I find the @Configurable
approach a hack. It does some magic in the background, which isn’t anything of the common language features (and is not a design pattern), and in order to understand how it happens you need a great deal of experience.
So, to summarize the big mess above
- domain objects should not be spring (IoC) managed, they should not have DAOs or anything related to infrastructure injected in them
- domain objects have the domain objects they depend on set by hibernate (or the persistence mechanism)
- domain objects perform the business logic, as the core idea of DDD is, but this does not include database queries or CRUD – only operations on the internal state of the object
- there is rarely need of DTOs – the domain objects are the DTOs themselves in most cases (which saves some boilerplate code)
- services perform CRUD operations, send emails, coordinate the domain objects, generate reports based on multiple domain objects, execute queries, etc.
- the service (application) layer isn’t that thin, but doesn’t include business rules that are intrinsic to the domain objects
- code generation should be avoided. Abstraction, design patterns and DI should be used to overcome the need of code generation, and ultimately – to get rid of code duplication.
The idea that domain objects are DTOs is an oversimplification. They can expose properties similar to those in DTOs but almost all experts agree that domain objects shouldn’t be exposed to the UI (or any other presentation layer, including WebServices).
It is application layer who is responsible for translation from DTOs to domain objects and vice versa. This translation is essential to make domain objects decoupled from presentation.
Yes, you can give up some DTOs. For example, it is quite safe to don’t create DTOs for value objects because they are immutable and passing it UI won’t mess things up. But passing an entity is very dangerous because it allows its modification outside of boundaries of the Unit of Work (transaction)
I wouldn’t agree on that, however.
This is having two almost identical class definitions in order to avoid understanding and handling the states of the persistence mechanism (JPA, for instance).
For example, now I’m having an application which uses uses the domain objects for both presentation, persistence and XML. And with proper transaction and session management we never need to make translations and to duplicate any code.
An argument you might have against this is that other, less-experienced developers may not be that good in handling this which may result in unexpected behaviour. Well, the structure of the application doesn’t require other developers to think about this – it is already handled generically. They just follow the code that has already been written, which is rather simplified because it lacks redundant calls.
Great article! This is one area I disagree with Martin Fowler that anemic domain objects are anti-pattern. I don’t know if he has already changed his mind on it (the article was written 2003). to me, separating business/data access logic from domain objects is a great application of “separation of concerns”.
Bozho, A very thought provoking article indeed.
I agree with the point about not injecting the repositories onto the domains however I can see some legitimate reasons why you may want to inject onto domain classes.
If I may illustrate my case by way of an example – if you have a User class with a getAge() method on it. And lets say that the getAge() method has an unlikely complex way of calculating the age. You may want to delegate this logic to a supporting helper class or some kind of helper factory.
public Integer getAge() {
AgeCalculator ageCalculator = factory.create(this);
return ageCalculator.calculateAge();
}
In the service layer surely you would rather have :-
return user.getAge();
than :-
User user = userRepository.getUser(id);
AgeCalculator ageCalculator = factory.create(this);
return ageCalculator.calculateAge();
My point is that the logic for the calculation of the age is hidden behind the getAge() method where it logically sits.
I would be interested to hear your views on how you would consider implementing this particular example.
Very good point. Yes, for cases like this, @Configurable seems plausible. Another way would be to inject the AgeCalculator in the serivce, and pass it to the get age method, like user.getAge(ageCalculator), or pass it via a setAgeCalculator. But it would certainly be easier with @Configurable (although my ‘magic’ point remains ;))
This example does not contradict my view, but rather extends it. Since the age calculator is not related to “infrastructure”, it has its place in the domain object.
To be honest we are considering moving away from @Configurable because of the productivity lost when the ‘magic’ process fails. It is a lot of effort to track down what has gone wrong – eclipse now has 4 builders to consider when compiling.
On your point about passing in the dependent helper class to the domain object :-
1) By using a setAgeCalculator method – I could see how it would be possible to end up with domain objects in an ‘invalid’ state (the object isn’t safe), i.e. before calling getAge you always have to set the supporting objects. You also can’t protect the objects by constructor because they are hibernate objects which require an empty construct.
2) By passing in the dependency when you use the method getAge(ageCalculator) – depending upon how complex your domain objects are, could you not end up with a large number of dependencies passed in?
Personally I think I’m leaning towards option 2 as our path out of @configurableness. What do you think?
About 1) you are right. You can always verify the state at runtime and throw a more meaningful exception than a NPE, but still not that good option.
For 2 – if the object has many dependencies.. it has many dependencies, and whether you inject them in the domain object, or inject them in the service and pass them to the domain object (with optional grouping of similar ones into higher-level objects), it is roughly the same, I think.
Great article!
Thanks
Great article and I mostly agree with the contents.
For one I think that technical issues should be separated from the functional domain. That means that domain objects should not be polluted by (technical) annotations or persistence methods (seperation of concerns). Dependency Injection (technical) should be outside the core domain. Persistence methods should be in a repository gateway, which (at least the interface, functional) is part of the domain. You know that you have a repository (functiuonal, within the domain), but not the way it’s implemented (technical). That’s outside the domain.
Just as the services (functionality) which calls them are part of the domain. These services are called from the user interface or other components outside this particular domain.
Transactional boundaries and session management is not domain functionality and should be outside the domain in a separate (thin) layer, which calls the services or domain objects within the domain.
DTO’s are useful for communicating outside the domain. In simple applications (with session management in the UI) the DO’s can be used, but I would not recommend it. I prefer the use of DTO’s which are assembled within the transaction boundary, and can be used outside the transaction (and session) boundary as to avoid potential LazyInitializationExceptions, which I am, unfortunately, very familiar with.
Dependency injection should not be in Domain Objects. If you want to use something like the AgeCalculator mentioned above, just call the user.getAge() method wich Alex suggested.
This method contains something like
class User {
public int getAge() {
AgeFactory.getInstance().getAgeCalculator().calculateAge(this);
}
}
The AgeFactory is a singleton, which has the correct calculator injected. You can use Spring for that.
class AgeFactory {
AgeFactory instance = new AgeFactory();
AgeCalculator ageCalculator = null;
public AgeFactory getInstance() {
return instance;
}
public void setAgeCalculator(AgeCalculator ageCalculator) {
this.ageCalculator = ageCalculator;
}
public AgeCalculator getAgeCalculator() {
return this.ageCalculator;
}
}
The implementation of the repository gateway objects can be done in the same way.
Usage of the repository (in a service) can be something like this
class ServiceImpl implements Service {
public void save(User user) {
RepositoryFactory.getInstance().getUserRepository().save(user);
}
}
These factories must be within the domain, because the domein objects must use them. But the dependency injection of these factories can be done outside the core domain (if you don’t use annotations). This way the core functional domain is not polluted with the technical issues of dependency injection.
Finally about annotations, I hate them, because it’s a magic black box. I rather use xml configuration files because they are probably easier to understand. Furthermore without annotations you can have the configuration files outside the core domain, and can use mock objects which are created and set on the factory without dependency injection within testcases. You can even choose to use dependency injection within part of the unit tests and without DI in other unit tests.
I have a whole presentation about this idea, which I gave a couple of years ago, even before I ever heard of DDD or TDD. It suits those development styles perfectly. I was planning to write an article about it, but never came around to it. I probably will write one or more blog items about it in the near future, when my blog is up and running.
Thank you for the extensive comment. Just one note – generally I like annotations, but not @Configurable, which involves weaving.
Hi, interesting article, it’s good to see some conversation about the implementation about some of these ideas which are vague in the ddd book.
I think you’re when you mention that the Product domain object should have to call warehouse.increaseSmellLevel(getSmellCoeficient().
Luckily there are several patterns to solve this and decouple the Product domain object from updating the warehouse smell level.
1.) Mediator pattern
2.) Observer pattern
3.) Domain events
all of these approach give you a really nice clean way for domain objects to affect each other’s state with being coupled in any way. this is also probably why it could make sense for the domain objects to be able to persist themselves. I haven’t fully implemented these ideas yet, but it does bring up questions about managing transactions in the domain layer which I’m not totally sure how I’d like to tackle that yet.
Hi, I implemented the Spring PetClinic (http://static.springsource.org/docs/petclinic.html) application using Jersey, JSF and JPA with a DDD approach. I tried to use persistence in a declarative way as much as possible. There are 10 domain classes and some supporting classes for exceptions and annotations, you can see them here: http://code.google.com/p/metal-framework/source/browse/#svn%2Ftrunk%2Fmetal-framework%2Fmetal-parent%2Fmetal-samples-parent%2Fmetal-petclinic%2Fsrc%2Fmain%2Fjava%2Forg%2Fmetalframework%2Fsamples%2Fpetclinic
Great article – sums up how I feel about DDD perfectly and all expressed very cleanly. I will refer to this post in the future when discussing with colleagues, rather than trying to write my own thoughts on the subject.
This is a very well thought out and nicely written article. Your summary points are concise and I agree with them. Have you looked at Grails framework. That is basically a realization of the thoughts you have commented on, but already formulated into a framework. The spring folks base their design on rails, DDD, TDD, and many other technically “agile” facets. I have been doing grails for 1.5 years now and I no longer have to propose these ideas, as they are embedded in the framework.
I have used grails for a year, but mainly for front-end. It is nice, but was not stable and had many issues (which are resolved in later versions)
could you elaborate on why domain objects are not instantiated by spring, so they need this special approach ?
i totally agree with the following idea of domain-objects containing business logic only (operations on their internal state), and not any infrastructure logic
love the new idea of a “service layer”. would like to add that this service layer could be very well called by the domain objects (since they have the needed data); just that they don’t do the actual work themselves.
what i don’t know anything about is: why should domain objects not be managed by the spring ? so, could you elaborate on that ?
as an idea for future: couldn’t a thin layer be created between the domain objects and services (just not pojos, with setters and getters) ?
Any object created with the new operator by the program (rather than by the container) is by default not managed by spring (unless it uses @Configurable) – http://techblog.bozho.net/?p=423
Regarding this one point:
“domain objects perform the business logic, as the core idea of DDD is, but this does not include database queries or CRUD – only operations on the internal state of the object”
I would say this is always the case. Let me know where Martin Fowler or Eric Evans stated otherwise?
Almost half of your article is expressing why e.g. warehouse.save() is a bad thing, and unnecessary. Indeed it is, no question about it. It contradicts with DDD (do you “save” a warehouse? No. If you ask a domain expert they will be confused what do you mean by saving a warehouse.) and such is not an argument of supporting anemic domain models.
Why did you bring that topic into the discussion?
Because the article is not “what is DDD”, but “how to implement it”. And as you can see from the linked examples, they use “warehoues.save()”. So I’m bringing it in to illustrate how not to implement it.
Great article! I have been thinking about how to tackle the problem regarding JPA and immutable POJOs in my service layer, (a lot of duplicate code), article has made me rethink my approach
Is there some short example project that you can post in order for one to understand, how you implement an application which uses the domain objects for persistence, logic, presentation-XML.
Thanks
Unfortunately I don’t have the time right now to pack an example project. But if/when I do, I’ll post it.
Very good article, Thank you. I am pretty new to DDD and have been toiling around in how to implement DDD and the Entity to Repository relationship. I personally like the simple idea of interfacing with the persistable Domain Object for business rules and persistence by calling warehouse.save(), but I do not like the relationship created from the domain to the repository.
So, as I was reading this I thought… why not decorate the domain object with the repository operations and call it PersistableWarehouse or something like it. This would remove the dependency from the domain entity to the repository thereby keeping the domain entity clean from any non-business related operations and it would offer up a clean interface for those who want to consume a domain object with adding persistence operations.
Has this been discussed before?
Puis-je vous emprunter 2-3 paragraphes pour un site ?
Dzięki takim tekstom jak te na twojej stronie pokochałem wirtualne blogi
@Bohzo, @JavaJones : I believe Java Jones nailed it with his statement…
An event driven architecture will support DDD, reduce coupling, increase cohesion and promote better scalability.
For all who don’t like @Configurable. You can avoid it by simply creating a Hibernate interceptor (guess other ORMs support similar functionalities for this) and use Spring’s ApplicationContext#getAutowireCapableBeanFactory().autowireBean() in the interceptor’s onLoad() method. This will autowire all fields for the newly instantiated managed object.
As for non Hibernate managed objects you can do the same in the Factory or Builder you are using to instantiate your domain classes. Also to avoid illegal instantiations make your domain object’s constructor to package private so only the factory can instantiate it.
Hello Bozho, I enjoyed your point of view. I think it is problably the way to go nowadays with Spring / Hibernate.
We must have in mind that Fowler and Evans had other frameworks avaiable at the time and it could make more sense to the own objects at domain have it dependencies with active records and data mappers at the time than today, with spring managing controller -> services -> repositories beans pretty straightfoward.
We defenetely can say that the technology changed a little this pattern.
I am currently working on a Project that the Service Layer do everything. The domain layer just are just anemic, as the word says. I am curious how it would be with the way you described.
Thank you for this article. Its way more advanced than my level is, but still i enjoyed reading it. How do you think, is anemic models are easier to handle for junior-mid developer?
About the rotten product example; What about the following implementation?
class Product {
private boolean isRotten;
// or private RotAmount rotAmount;
}
And then let the warehouse object compute the smell level by checking out the `RotAmount` of every `Product` that is in the warehouse. This feels like a more correct implementation to me.
Had the implementation was this way, would this have changed your arguments?