Friday, January 18, 2008

Domain Driven Design in Java: Repositories and DAOs part 2

In my previous post I've scratched the surface of the Repositores vs DAO debate, showing that there are points in common but also some differences. Now it's time to become a little less technology agnostic and try to solve the problem in a common java environment such as Spring plus Hibernate.

The original specification was totally technology agnostic – the only reference in the DDD book was to entity beans (which sound so naïve nowadays) – but there were some recommendations, quoting Eric Evans:

"Before implementing something like a repository, you need to think carefully about the infrastructure you are committed to, specially any architectural frameworks"

Ore the more concise:

"In general, don't fight your frameworks"

Which sounds as pragmatic as one would expect. Ok, we have frameworks. We have Hibernate that provides a convenient abstraction for database access, and we have Spring that suggest a mainstream way to deal with persistence through DAOs and the xxxDAOSupport classes. Do we still need repositories? In many cases the DAO approach could be quite sufficient, even if some attention must be put when dealing with Aggregate Roots.

Accessing persistence only through aggregates

One of the strongest recommendations of DDD is to partition the domain model, to highlight Aggregate Roots and related Entities and Value Objects. As a result you could conceptually draw regions on the class diagram, with some properties:

  • There's only one Aggregate Root per region
  • An Entity can belong to only one region
  • Value objects can be used in different regions

Mapping the concepts to Hibernate, a Value Object can be more or less implemented as a Hibernate Custom Type, while there's no difference in the implementation for simple Entities or Aggregate root. Put in another way, Hibernate's view of the domain model is flatter than the one you can achieve by applying domain driven principles to modeling. Does this matter? It depends a lot on the complexity of the domain. When dealing with relations such as the classic OrderLineItem, applying strictly the "access the data only through the Aggregate Root" rule help solving a lot of complex situations. They're simply less complex. As the system grows, you have a view (I liked the regions on the class diagram) that helps keeping coherence of the system. It's probably overkill for small systems, but DDD is for managing complexity, and it helps. Moreover, this type of approach gives also a consistent way to deal with Hibernate's features like lazy-loading: associations crossing regions boundaries were forced to be lazy-loaded, while inside the regions one could apply eager-loading if needed. So it makes sense to have a centralized access point related to Aggregate Roots instead of generic entities. Still you can enforce this rule by using only one DAO per Aggregate Root, or go for the more radical approach proposed by Debasish Ghosh in his blog, which is to have a Repository Layer on top of DAOs.

Continues on part 3.

No comments: