On domain-driven design, anemic domain models, 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 pricise 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 in the warehouse? No – it’s the warehouse 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 these do 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, executing 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, and abstraction, design patterns and DI should be use instead, to overcome the need of code generation
About these ads

6 Responses to “On domain-driven design, anemic domain models, code generation, dependency injection and more…”

  1. Szymon Pobiega Says:

    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)

  2. Bozho Says:

    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 my 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.

  3. sudarshan Says:

    According to what i understand of DDD, Repository Interfaces are part of the domain and are coded in terms of the UL, so even if they are injected into the domain model, i see no harm in it.

    However the implementation may have knowledge of persistence and so on which should not be included into the domain layer

  4. David Says:

    This is a great post. I whole heartily agree by having domain objects focus on business logic increases encapsulation and reusability. I have been on several projects where domain logic has leaked into the services making it very difficult to reuse and very hard to maintain.

  5. domain names for sale Says:

    domain names for sale…

    [...]On domain-driven design, anemic domain models, code generation, dependency injection and more… « Bozho’s Weblog[...]…

  6. Nova domaca muzika download Says:

    Another Title…

    I saw this really good post today….

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: