Comments to Gavin King about DDD and Repositories

I was replying the Gavin King’s question about Repositories and DDD, but the comment started to become really big and I wasn’t sure if the code snippets would be well formatted. So, I decided to reply it here.

I had similar questions about Repositories. I’m from Brazil and we have discussed it many times here (see at GUJ and at my post in the Caelum Blog – unfortunately – in pt-BR; perhaps, translation tools can help). I have a personal and pragmatic conclusion that may help.

I won’t discuss if DDD is good or not, but I will suppose it is. The root problem is the way that DAOs are being used. In the classic Client --@OneToMany--> Order, if it is given a client (id=1) how could we get his orders since 10/10/2006?

Almost everyone would do dao.findOrdersFor(client, since), but that is clearly procedural (actually, not always a bad thing). What I wanted to do is client.getOrdersSince(date).

Now, suppose I love DDD and really want to do client.getOrdersSince(date). The client should be able to give its orders, that’s the “DDD-way”. How could I implement it? Load all orders in memory (maybe a regular @OneToMany mapping) and then filter what I want (bleh!) isn’t an option. One option would be as below:

class Client {
  private final ClientDao dao;
  Client(ClientDao dao) {// ioc here...}
  public List getOrdersSince(Date date) {
    return this.dao.findClientOrdersSince(this, date);
  }
}

Hmm… what about separation of concerns? DAOs are related to persistence, and persistence is infrastructure, not domain (or business related).

This is what repositories try to solve. They are a domain concept, from where we can get other domain objects. To be “DDD-compliant”, I would do:

class Client {
  private final OrderRepository orderRepository;
  Client(OrderRepository repository) {// ioc here...}
  public List getOrdersSince(Date date) {
    return orderRepository.findForClientSince(this, date);
  }
}

But err… what’s the difference? Just the name? YES! But the names are important, right? 😉

Actually, some people would rather Repositories as interfaces, and Daos might be their implementations. What really matters is that domain objects shouldn’t have to deal with infrastructure things like persistence. A Repository has nothing to do with persistence, it’s a domain concept. Lists and Maps (any container) are repositories too.

I also rate the idea to have more layers (completely agreed with you):

Client -> OrderRepository(just an interface) -> OrderDao -> Hibernate -> ...

I would just drop the indirection and make the Repository concrete:

Client -> OrderRepository -> Hibernate -> ...

Duh. You can ask: “have you just renamed the Dao?” I would say: “yes, but aren’t the names important?” 😉

Remember why I did it. I wanted to do client.getOrdersSince(date) and the client shouldn’t know anything about persistence. He doesn’t care if the repository is just a plain list or use hibernate. Repositories are domain objects, daos aren’t.

Advertisement

25 thoughts on “Comments to Gavin King about DDD and Repositories

  1. I don’t think Repositories are just a DAO renamed. Actually I think it’s not what people usually say about Repositories.

    If Repository is an extra layer than I must agree with Gavin and say that we don’t need another layer for this.

    If it’s really *just* a DDD version of the old DAO, than I think I like it 🙂 We still encapsulate all our persistence logic in one place but now this place (now named Repository) should be called inside the domain layer. It seems more OO to read, but can have some of the problems Christian said (before Gavin’s post).

    Anyway, as Gavin, I still need to read carefully the DDD book (already ordered mine ;-).

  2. Nice article but what if the client/customer package has to be used for more than taking orders? You could have an independent customer package (with all customer-related entities) and another package for orders. An order should surely have a link to a customer but is the reverse true? Won’t you pollute your customer package by adding order-related methods on your customer class? I don’t like the idea of having a circular relationship between Customer and Order (which are living in different packages). So, I think an orderRepository.findOrdersForCustomerSinceDate(customer, date) method is simply good enough.

  3. so its all about naming conventions? altogether the different posts from gavin, this one here and the other discussions about repositories/daos bear me, that a repository is just the ddd vocab of a dao.

  4. @Rafael Ferreira

    We live (for sure) in a small world (which is getting even smaller, smaller, smaller, …).

    You have two choices to mock concrete repositories:

    1. JMock + CGLib: http://www.jmock.org/mocking-classes.html
    2. public class RepositoryMock extends Repository {...}

    @Sergio Lopes

    I agree with you, that’s what I’ve said. Couldn’t we say that an “DDD version” of the old-DAOs is an old DAO with a new (and more appropriate) name? 😉

    @Xavier

    Even if the clients are being used without orders, I don’t think they are being “polluted” with an order-relationship. Being used or not, for my domain, clients always can have orders.

    They are still clients, right? IMO, if a client should have a link to its orders or not is just a design decision. You can take your decision asking to yourself: “Is there any requirement to get orders based on a client?”. If true, I would rather to do client.getOrders() (more OO) instead of dao.findOrdersFor(client) (more procedural).

    @Rene Groeschke

    See the Sergio’s comment. You may see it as an “DDD version of the old-DAO”, if you want. Furthermore, a DAO might be an implementation of the Repository.

  5. Fabio,

    I like this vision that a Repository is a DDD-DAO, but I think it’s not what most people say about Repository.
    Are we creating a “new” thing? (different from the classic DAO and different from what people usually call Repository)

  6. I’d recommend thinking about whether you actually want your domain objects to talk to the repositories, many DDDers completely avoid and its been discussed at length on the DDD forum.

    Agree about removing the DAOs, having DAOs plus repositories always seems over-engineering to me (or trying to make a new pattern fit in with an existing one).

    If you want to get this stuff I certainly wouldn’t base it on the posts by Gavin King (and the rest), I’d go to DDD/POEAA and the DDD forum. We’ve already had the sorts of discussions about these issues MANY times before so starting the discussion from scratch again is just silly.

    The DDD forum is at:
    http://tech.groups.yahoo.com/group/domaindrivendesign

  7. Thanks for the tip Colin. I will take a look at it, cause I’m particularly interested on how things like client.getSpecialOrdersSince(date) are implemented by people who avoid domain objects talking to repositories.

  8. Yeah its a good example and there is a thread on this sort of thing at DDD:

    [=>http://tech.groups.yahoo.com/group/domaindrivendesign/message/5346%5D

    Actually there are probably other threads but that one sticks in my mind.

    To me there are multiple solutions:

    1) Load all the orders and do it in memory, can’t say whether this is reasonable in this case.
    2) Leave it as a repository method, seems like a reasonable solution to me but it depends on the usage pattern.
    3) Have this as a case where you just go ahead and have the domain access a repository. If you go with this I wouldn’t necessarily have it directly talk to the repository, I’d consider having the domain talk to a Registry which knows how to get repositories and how to use them (e.g. it might have a factory for them).

    If Client and Orders are indeed seperate aggregates and a Client does not have its collection of Orders then I would suggest you shouldn’t put this method on the Client at all. A repository (or service which does some work and then calls the repository) seems like a better home.

  9. A repository (or service which does some work and then calls the repository) seems like a better home.

    Sorry, but I disagree. service.findOrders(client, date) is exactly what I’m avoiding here. It feels too much procedural.

  10. To be honest I certainly don’t think going to a repository is too procedural. I certainly don’t want to make all the queries we use available on our aggregate roots, and why should I want to do it if the interface of the repository is part of the doman anyway?

    We don’t need to hide the existence of repositories/services because they are a part of the model.

  11. “It feels too much procedural.”

    In fact, after 20 years of OO I think OO is step in the wrong direction. Procedural is good. My programming style is FOOP. My methods aim to be functional, meaning they have no side effects and don’t change state as much as possible. My objects just carry the data around and have some convenience methods for manipulating the data. All business logic is encapsulated in services, which are procedural and stateless. So my programming style is FOOP. Functional-OO-Procedural.

    Really, it’s the future 🙂

    Peace
    -stephan


    Stephan Schmidt :: stephan@reposita.org
    Reposita Open Source – Monitor your software development
    http://www.reposita.org
    Blog at http://stephan.reposita.org – No signal. No noise.

  12. @Fabio: No I’m not. After 20 years of developing applications with OO I think it’s not the best way. From my experience FOOP is easier to refactor, easier to understand, easier to reuse and easier to maintain in the long run. Perhaps I have to blog an example to make people understand.

    Peace
    -stephan

  13. @Stephan: It is interesting to read a comment like this. I’m a member of an Open Source project, called Tiny Marbles (http://www.tinymarbles.org). We are following a similar approach: we store objects in a repository. There are CRUD methods for the objects, that’s almost all. The complete business logic we encapsulate using the Command pattern. I wouldn’t say, that this approach would fit in every software project, but in a web application environment for business applications it is just wonderful. And it fits perfectly well to a RESTful architecture.

    The discussion here shows one thing very clearly: who says, the decision that ‘getOrders’ is connected to ‘Client’ is a good decision? Sometimes when starting the project the requirements are not known completely. At least while developing web application where requirements can change very often, it seems to me a better approach to maintain a stable domain model (which we do in our case in the Tiny Marbles repository), and delegate the business logic to ‘services’ (in our case using the Command pattern) which changes the state of the repository, or simply gives filtered information about the current state of the system. For the example you mentioned in your post we would prefer: getRepo.OrdersSinceDate(User, date). And we even go one step further: we are using the object ‘User’ with the role ‘customer’ or ‘client’.

    @Fabio: I would love to discuss our philosophy with you, although I know, you don’t agree and this place might not the right board for that. But hopefully some day there will be an opportunity 🙂

  14. @Dietmar: Wonderful! I’ve also implemented a large application with the business logic in commands and the data in objects. This was very useful and it was very easy to recombine and reuse commands for new business cases. I’ll certainly take a look at tiny marbles.

  15. i see what’s you mean. here is one important advantage as you apply Repository rather than DAO. one more layer — Repository, between Dao and Aggregate Entitry, which bring some flexiblity, for example, the cache or the concentration access point.

    for example if apply the Dao, then the client (caller) need to understand and learn some complicated detail or Dao objects.

    the codes should looks like:

    Client c=new Client(clientDao).

    if you do others, you also have to know the related Daos for those entities.

    but for Repository.

    the repository just apply for root entity for an aggregate.

    so there are more less repository need to learn or even you can apply repository factory pattern.

    codes looks like:

    Client c=new Client(RepositoryFactory.getInstance())

    within the Client:

    Client(factory){
    repository=factory.getRepository(Client.class);
    }

    hope can help you a little.

  16. @Fabio what about the responsability of each component?
    I still thinking about the responsability of each Repository and i dont think that a entity has the responsability to separate data in your implementation, even if the agregate data are called by a method like ‘.finbByEspecificCondition(Entity entity)’, i think separate the repository can bring you more flexibility than put all on the same object.

  17. Fabio, I think you may be watering down what the repository is for in DDD. The purpose of a Repository is to provide the illusion of an in-memory collection of aggregate roots. The subtleties abound, and without a proper study of DDD, they are summarily dismissed. For example, in DDD, a Factory is responsible for the creation of a new aggregate root (multiple or a single domain object) inasmuch that its invariants are enforced before being returned to the client. Continually, the Repository enforces the same invariants, but within the realm of retrieving and hydrating an aggregate root from a data store. It is more than a DAO, and I think that is an important abstraction which cuts out much of the clutter responsible for rendering many domain layers useless.

Leave a Reply to Sérgio Lopes Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s