On the Repository pattern
The Repository pattern is one of the most popular patterns of enterprise application architecture (P of EAE, a great book by Martin Fowler). The pattern was further refined in context of Domain-Driven Design by Eric Evans. Since then wars has been waged around how to implement a Repository and when to use it. Here’s my take on this subject.
First of all, Fowler’s definition of Repository
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects
should not be treated literally. Providing a collection-like interface for relational database can be a problem much bigger than posed by most of the ‘enterprise’ systems that are being built today here and there. I would suggest a more practical ‘working’ definition like this one
- Provides access methods to domain objects
- It is meant to be used by command handlers
- Returns one object or throws exception
- If it is designed to work with Unit of Work, has no Save method. Otherwise, it has
- The interface is placed in same assembly as domain model classes
The first line is pretty obvious, right? The second could be more problematic. In my opinion the very reason why we create repositories (and I do believe we should do it) is the ability to write more explicit code in command handlers (or whatever approach you use in Application layer). There are, however, cases where repositories can be useful outside of command handlers. When employing the classic approach to DDD (synchronous, without CQRS, EventSourcing and other cool stuff) we often have to display a domain object on screen. In such case we can use a repository to retrieve our object. It’s not a deadly sin son, I forgive you.
Returns one object or throws exception… Why? Because we don’t invoke any action on a collection of domain objects. Ever. If you want to display a grid, please create a separate class (I would call it Finder) for this purpose. I am pretty sure you don’t want to display all the data associated with a domain object on a grid, so your finder will probably retrieve only a subset of information. If you need the data only for display purposes, it can be a little bit stale, so you can add caching. If I haven’t convince you yet, think about change management. Do you really want to change your repository (which is part of Domain Model) every time you add a column on a grid on some UI form? I bet no. So please place all the finder methods outside of the repository.
But what if you want to invoke an action (change state) on a collection of object? The answer is simple. You are probably missing a real-world domain object which corresponds to this collection and should be the sole owner of the piece of data you want to change. Find that object and model it explicitly in your solution.
Because I don’t want to start flame wars about using (or not using, or abusing) Unit of Work, I try to be as neutral as possible in this matter. If you want Unit of Work, it’s OK for me, but please be as kind to remove Save methods from repositories. And if you don’t know if you wan’t to use Unit of Work or not, think if there is a chance that one of the repositories will ever be implemented using anything else than your favourite ORM (which is of course NHibernate). If so, don’t use Unit of Work because it’s abstraction will break on this one repository and so will your whole beautiful architecture.
The last line is, again, pretty obvious. Repositories are part of the Domain Model so, despite the fact they are not going to be used by domain objects, they need to be put in the same assembly to maintain logical cohesion.
I hope you enjoyed my subjective view of Repository as a pattern in Domain-Drive Design. I can’t wait to hear your opinions.