All Your Repositories Are Belong To Us

Who would have thought that the Repository Pattern could become a battleground?  I always thought it was pretty straightforward—at least, that’s how I felt when I first read Domain-Driven Design a few years ago.

While I could immediately see the benefits of using a repository, there were a few things that really bothered me as I started implementing the pattern that I could never fully reconcile:

  1. How do we best query the repository to find the particular aggregates that we care about?
  2. How do we handle UI concerns such as paging within the repository?
  3. Does the repository even care about UI concerns?
  4. How do we display domain objects to the UI (this is only slightly related to the repository pattern).
  5. How do we modify our domain objects to support lazy loading?

When I first stumbled upon Greg Young’s solution of Command Query Separation as an architectural pattern, I immediately knew that this was the way to go.  It was as though someone turned on a light bulb—a really big light bulb.  It was an idea whose time had come.  Paradigm shifts are like that.  The bigger the attachment to the old philosophy, the bigger the “ah ha!” when you finally see it in a new light.

CQS instantly solved all of my problems and questions with repositories.  The answer is simple—you don’t query the repository to perform searches.  Instead, you load specific aggregates from the repository by their identity.  Further, paging is purely a UI concern, therefore we query a completely different data source–or at least access the data source through another mechanism.  Queries and searches are performed against this alternate mechanism as well.  Lastly we don’t display our domain objects.  We display simple DTOs that have been queried through this alternate data access mechanism.

With all of this as introduction, it has been very amusing and informative to see Oren and Greg battle it out regarding repositories in general:

All of the posts are worth reading several times.  Summing them up in a single phrase doesn’t do them justice.  Further, the summary I gave is a bit arbitrary as it may not accurately express the main concepts of each post.

Being a huge fan of CQS, I’m going to have to go with Greg on this one.  No surprises there.  Even so, I find Oren’s blog inspiring to read.  The frequency of his posts make me wonder if he does anything else, but the amount of tested code he cranks out is astounding.  In frequency of blog posts, Oren wins hands down.

To conclude, I see this debate as a healthy thing in the DDD community and the ALT.NET community.

  • http://openid.thinkbeforecoding.com/jeremie.chassaing jeremie.chassaing

    I’m totally following you on this one..
    I had the same errance.. you can witness it on my blog…
    The same paging question : http://thinkbeforecoding.com/post/2009/01/19/Repositories-and-IQueryable-the-paging-case
    and the same answer :
    http://thinkbeforecoding.com/post/2009/04/08/Back-on-Repositories-and-Paging-Introducing-reporting

    But it seems that every one as to stumble on it to get it…
    It’s perhaps the missigne chapter from the blue book ?

  • http://chadly.net Chad Lee

    I’m very interested to hear more about CQS. Do you have any good references? I checked out Greg Young’s blog, but he seems to be talking about it more in the context of distributed systems.

  • http://www.blogger.com/profile/16836313591238262040 Jonathan Oliver

    Chad,

    My blog talks about it a little bit. You don’t necessarily need to be running a distributed environment to get the benefits of CQS. You can do everything in process and use simple C# events. The trick is to have a repository for populating your aggregate roots and then a simple querying mechanism to talk to the database.

  • http://www.blogger.com/profile/16836313591238262040 Jonathan Oliver

    Jeremie,

    Great posts! I agree that there isn’t a lot of guidance just yet as most are only beginning to discover that the repository isn’t the best place for queries.

  • http://www.blogger.com/profile/08948488698923418322 ryzam

    Why don’t we separate repository to two interface one is focusing on command meaning it will dealing only with aggregate root and another one is for querying that using repository but it will return object DTO

  • http://www.blogger.com/profile/16836313591238262040 Jonathan Oliver

    Ryzam,

    A repository is an abstraction meant to give the feeling of a collection to a data access mechanism–usually a database. It is a useful level of indirection in a domain model. When you’re operating outside of a domain model (like you are in the query side of the CQS), you don’t need the extra layer of abstraction–just go straight to your data access objects.

  • http://www.blogger.com/profile/08948488698923418322 ryzam

    I’m preferred when query object we are not enforce to follow DDD rule of aggregate.

  • Joe

    Jonathan,

    It seems like some people suggest that CQS and Event Sourcing can be used with a single repository. In your experience, is there any reason not to go the extra mile and store change events in one data store and a reporting model in another data store like Greg describes (distributed system or not)?

  • http://www.blogger.com/profile/16836313591238262040 Jonathan Oliver

    I'd actually recommend a completely separate storage mechanism for the commands and another for the queries. The query side is typically done using a relational database because that's what relational DBs are good at.

  • Joe

    I agree on completely separate storage mechanisms.

    It seems like the only sensible way of doing it (to me at least), but some people have stated that a single storage mechanism could be used. I'm having trouble envisioning how/why one would choose a shared storage mechanism…?

  • http://www.blogger.com/profile/16836313591238262040 Jonathan Oliver

    The main reasons people tend toward a single storage system in CQS is that they think it is less work. "Hey, I've already built the database–why build it again?" They figure that the only difference is the way you access the data.

    While it's true that you *could* use the same database, the purposes behind the "command" storage and the "query" storage are so different that you're going to be fighting it the whole way if you combine them.

    I'd recommend biting the bullet and investing a little in a completely separate storage mechanism from the outset.