Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Repository is Dead: Long Live Repository

The title sums up the argument in Oren’s recent post about repositories. Although we have had some discussions on twitter about that post I wanted to offer people a bit more of an analysis of what he has said and the pros/cons of such a strategy. His post was originally intended to be an “alternative to the repository pattern” which he believes “is dead”.

His new solution to the problem is to  instead use query objects that are passed into the repository to remove the "complexity”. Of course this is far from a new idea in fact it has been discussed on this blog in Specification or Query Object and also in The Generic Repository where pretty much the exact same idea is put forward ( If you have not I strongly recommend reading The Generic Repository as it uses an almost identical method (except the query objects are used in the Repository implementation which composes a generic repository that it passes query objects to)). The concepts are also discussed in Domain Driven Design itself (they are just called specifications instead of query objects).

What is particularly annoying is the sensationalism associated with this post. It is extremely odd to argue against a pattern by suggesting to use the pattern eh? The suggested way to avoid the Repository pattern is to use the Repository pattern which shortening the definition he provided

Provides the domain collection semantics to a set of aggregate root objects.

So now that we have determined that he has not actually come up with anything new and is actually still using repositories let’s reframe the original argument into what it really is.

    • FindCustomer(id)
    • FindCustomerWithAddresses(id)
    • FindCustomerWith..

Oren has an issue with named query methods on a Repository interface. I will ignore the arguments provided by him and provide a simpler better argument for why you SHOULD NOT use these types of methods.

The Open Closed Principle. Versioning a Repository that uses these types of methods is extremely difficult. When I want to add a new method, or change an existing one I am changing the original contract. If I move these to a single method that takes a Query object I can change/add/remove queries without touching my Repository contract. In other words, we are simply applying SOLID to the repository interface.

Now we all know that following the Open Closed Principle amongst others is good right?

I would answer that question with “Yes in general following the SOLID principles leads to better Object Oriented code”.

I am sure I have left a few fairly confused at this point as I argue against my own point but I am leading to something important. The problem here is that the Repository interface is not necessarily Object Oriented. The Repository represents an architectural boundary, it is intended to be a LAYER/TIER boundary. Generally speaking when we define such interfaces we define them in a procedural manner (and with good cause).

Analyzing the situation given of a CustomerRepository what would happen if we were to want to put the data access behind a remote facade? With the simple procedural boundary of named methods, we would just go create a remote facade (say a webservice) and we would pass through the calls. What would happen though if we used the “other” Repository interface that is being suggested? Well our remote facade would need to support the passing of any criteria dynamically across its contract, this is generally considered bad contract design as we then will have great trouble figuring out and optimizing what our service actually does. With the explicit contract we have to explicitly add or change the contract and we know when things are being added that may need to be optimized. I am quite sure everyone has dealt at some point with the service that had 1 method and could do anything typically they take and receive strings my favorite are the ones you pass SQL to and they return you random XML (usually a serialized data table) …

One could argue against me here by saying that they don’t consider their Repositories to be LAYER/TIER boundaries… Well, I am sorry but you are using the pattern incorrectly then. If you don’t want a LAYER/TIER boundary don’t have one just use nhibernate directly … At this point you probably shouldn’t have a domain either though … If your system is complex enough to justify the cost of creating a good model why are you trying to optimize the < 2% spent on Repository abstractions?

 

After this Oren brings forth another very interesting issue that led him to his epiphany of killing Repositories.

It get worse when you have complex search criteria and complex fetch plan. Then you are stuck either creating a method per each combination that you use or generalizing that

I have had this smell in the past as well but instead of destroying the layering I am building into my domain (with good reason, see DDD by Evans for why) I went a completely different route. I noticed very quickly that it was by some random chance that my fetch plans were being different. I had a very distinct place where things were different, I needed very different fetching plans between when I was getting domain objects to perform a writing behaviour on them as opposed to when I was reading objects to say build a DTO.

This realization is what led me to command and query separation, the creation of a separate layer to process read->DTO transformations and to no longer use my domain repositories for this purpose. I should point out that for the read layer, what is being shown by Oren is a great way of implementing it. I won’t go into a large talk on command and query separation here (there is a good video from the european van and hopefully the QCon SF session will be up soon)… but if you apply command and query separation you will have almost none (read: none) read methods on your repositories in your domain.

Continuing along, Oren randomly puts forth the gem of:

A lot of people use it, mostly because of the DDD association. I am currently in the opinion that DDD should be approached with caution, since if you don’t actually need it (and have the prerequisites for it, such as business expert to work closely with or an app that can actually benefit from it), it is probably going to be more painful to try using DDD than without.

It being everyone has heard pretty much every real DDD practitioner saying this for years, I am really unsure why it has taken so long to figure this out?  This also begs the question of what systems actually need or are suitable for DDD but that’s another day and another post.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

12 Responses to Repository is Dead: Long Live Repository

  1. Rachna Shah says:

    Hi, I have to say great explanation.

    If you do consider my request, I would also like you to write articles on following topics since i strongly feel that through understanding of following terminology will greatly improve learning experience of this pattern.

    1) Lambda Expression
    2) Expression
    3) DataContext Class
    4) IEnumerable
    5) IEntity
    6) IQueryable
    7) LINQ

    Thank you

  2. Pingback: Tipos de repositorio: Separación de responsabilidades « Koalite's blog

  3. Pingback: How to design a unit testable domain model with Entity Framework Code First – Daniel Cazzulino's Blog

  4. Pingback: Interesting links from 2011-01-22 (Kanban) | What is going on under my hat

  5. sam says:

    Where does linq to nhibernate fit in then

  6. Mike says:

    “His new solution to the problem is to instead use query objects that are passed into the repository ”

    I don’think that was the actual argument. I think he was saying that you can just use NHibernate (and its query objects) directly.

    “If I move these to a single method that takes a Query object I can change/add/remove queries without touching my Repository contract.”

    But then it’s not much of a contract.

  7. DDD is full of good OOP patterns and practices. The repository pattern was a good starting point for a lot of devs to get the Persistance Ignorance thing.
    But practicing Persistance Ignorance doesn’t mean that you’re doing DDD, you don’t have to use a repository to achieve PI, and NHibernate does it quite well. I think the mix comes from here…

    The project I’m working on really need DDD and I really feel the need to go for CQS (with queries on precomputed replicated tables or cubes), and the explicit repository patterns give a strong support for the command part.

  8. Greg says:

    @stephen re:

    a query object / specification like system that works to refine a general service method is certainly possible in my eyes (if you can well agree how the specification, query is designed- why would this be any different to multiple different service calls).

    This is generally a big time service anti-pattern. Examples of this would be the service that takes SQL and returns a serialized dataset.

    re: CQS check out the video I mentioned for more discussion.

  9. Regarding my “gem”

    The fact that it is explicitly outlined doesn’t mean that people aren’t trying to do that.

  10. George Mauer says:

    Thanks Greg for that. Its a more eloquently phrased version of the argument I was giving him here: http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx#30423

    Oren’s approach is spectacular if you can commit to using NHibernate for every repository, for a broad swathe of projects that’s quite a demand to make.

    Another, more practical point is that explicit repositories make it far easier to get buy-in for NHibernate from an inexperienced team. I have done this on a recent project, I explained the pattern and suggested implementing the repositories with NHibernate. Of course if they cannot figure the appropriate mapping out then they are free to implement the repository in another manner. The fact of the matter is that against our legacy database Tanks and Products might be simple to map, but Customers very difficult, so providing the team with the reassurance that they can always default to stored procedures or ADO.NET when in a tight spot created an awful lot of enthusiasm.

    Yes, some day these things might no longer be an issue but for the foreseeable future Greg, I’m with you on this.

  11. Stephen says:

    I’m finding it hard to understand your overall point, also theres a few points in there regarding making service calls, I don’t think that nec~ means you have to have a monolithic service with tons of methods for specific scenarios.. a query object / specification like system that works to refine a general service method is certainly possible in my eyes (if you can well agree how the specification, query is designed- why would this be any different to multiple different service calls).

    Additionally you talk about command and query separation, but frankly to me thats a pretty broad statement, do you have any examples of what you mean?

  12. corey says:

    Thanks for the article Greg. This helps clear things up, but I have a question on implementation.

    If web services are required between the data and the applications, would you implement 2 separate services? One for command and one for query?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>