In the previous posts on the topic (part1 and part2) I've highlighted common characteristics and differences between the DAO and Repository patterns. In situations where the modeled domain is simple, a traditional DAO approach (backed up by frameworks) is probably good enough. If your domain is more complex, or if complexity is growing, differences between DAOs and Repositories become more important.
- A larger domain calls for a higher level of abstraction: Repositories could help implementing new functionalities because they hide more of the underlying layers.
- Complex systems cannot always be modeled with a one-database strategy: whether a Model-DAO-DB model makes sense for most of the normal application, this is a "reasonable assumption". There are anyway situation where a Repository should hide more complexity than a simple database call.
- Simply stating that "access to the database should always happen through Aggregate Roots" could be not enough to preserve your architecture's integrity.
So, given that DAOs come almost for free in a Spring plus Hibernate environment, the question now is understand if we need something more than that. To put in another way, if DAOs drawbacks (tied to the database representation, more data-oriented than model-oriented, not enforcing access only via aggregates but a one-dao-per-entity approach) are something we can live with or a call for a targeted solution. To be honest, there's also one limitation with DAOs, which is related to the layer they belong to (the persistence layer or whatever you want to call it), while it is been said that Repositories belong to the domain layer. This is a controversial issue… I'll leave it for later.
Ok, the proposed approach with Repositories and DAOs is to have Repositories on top of the persistence layer, and have Repositories call specific DAOs. Something like
Which is quite similar to Debasish's proposal on this post. Repositories expose a more business-oriented interface, compared to DAOs and could enforce access only via Aggregate Roots. Repositories should belong to the domain layer, for a couple of reasons:
- Data access isn't conceptually a dirty thing. A pure OOP approach made up by only traversing associations (and have am ORM framework doing the dirty job behind the scenes) could impact performance.
- They should not be tied to any implementation issue. Repositories expose abstract store and retrieval operations but no implementation details.
- They could contain business-oriented logic related to searches: getUnreconciledOperations(BankAccount ba) could be used instead of getOperationByAccountAndDateRange(BankAccount ba, Date from, Date to).
Personally, I like the proposed solution, which is also implemented via Spring dependency Injection. But I can't help feeling somewhat weak when it comes to explain the advantages. I mean "speaking the language of the domain" is a good thing to me. But is quite far to be a compelling principle when it comes to "sell" an architecture proposal to a team. They have established practices with DAOs, and we're suggesting to add another layer on top of it. If you are lucky enough to have a common understanding of DDD principles and values in your team, then you're probably in a sort of positive loop, and one DDD practice enforces another one and the whole result is a good thing. If this is not the case, this approach might look like it provides marginal value at the price of an increased complexity.
One more thing that could get in the way is code-generation. It is often possible to have some sort of code generation applied to DAOs. Such DAOs are good but flat, and in many cases they call for a business-oriented refinement, while hand-coded DAOs are generally somewhere in the middle. But if adding a Repository layer breaks the code-generation cycle, it could (one more time) be not worth the effort.