Help

I've recently read the book Domain Driven Design, which apparently is now the new bible for some folks who totally think in objects. I even mentioned it in HiA and JPwH - unfortunately I didn't read it before.

I now think that quite a few of the patterns promoted by this book are actually a step backwards. I also miss a list of Pros and Cons of each pattern (like in the GoF book). So readers have to guess why and when a pattern might be applicable and when not. Or, when the Cons bullet items would outweigh the Pros.

One example would be the /Repository/ pattern. If I understand it correctly, this is how it works (the DDD author says that this similar summary is correct):

  • Developers don't want to decide if they should call order.getLineItems() or rather lineItemDAO.findAllForOrderId(order.getId()) if they need a bunch of line items from the data store. (I completely agree that this is a typical and common issue - however, I don't agree with the proposed solution.)
  • We can restrict that and take away that decision by forcing access to always go through a repository. For example, there is only an OrderRepository and the only way to get line items would be OrderRepository.getLineItems(order). This repository thing uses DAOs internally to actually get the data. So we wrap DAOs in repositories, creating an additional layer. You are not supposed to call the DAO anymore.
  • Now, we generalize the OrderRepository into an interface and put the DAO access into OrderRepositoryImpl.
  • And finally: We then inject this concrete OrderRepository instance into the Order class, so that when you call order.getLineItems(), it will internally access the repository. This requires interception of domain model instance creation but that is easy enough to do these days with containers/factories/services everywhere. Nobody creates a /new/ instance anymore, right?

The advantages seem to be that repositories speak the language of the domain (eh, what? This seems to be related to passing IDs as DAO finder arguments...) and that, well, you no longer have to make these difficult choices when you want to access a data store, because there is only one way to get the stuff.

I think this pattern is a step backwards and should not be recommended:

  1. If you do not want to have to decide between order.getLineItems() and lineItemDAO.findAllForOrderId(order.getId()) - kick out one of these methods! Nobody forces you to map a persistent lineItems collection on your Order class. You did that because you like the features you get when you load data that way (in Hibernate: transparent pre-fetching of other lineItems collections with batches or subselects, can't do that nicely in DAO finders). If you don't need that, don't create it. The same is true for any other association in your domain model. Or, vice versa, if there is no difference between a DAO finder method and a domain model traversal, remove the DAO method.
  2. If there really is a difference between order.getLineItems() and lineItemDAO.findAllForOrderId(order.getId()) - for example, one returns more associated stuff, like the product for each line item - keep them both. I do that all the time. I document it properly, saying this finder method does eager fetching of the product for each line item and on the getter method I write this returns line items, the products are unloaded proxies. And of course I need them both. Actually, I rename the DAO finder to lineItemDAO.findAllForOrderIdWithProducts(order.getId()) or, if I want to speak the language of the domain nothing stops me from defining it as lineItemDAO.findAllForOrderWithProducts(order). Because I don't like repeating myself, I finally end up with lineItemDAO.findWithProducts(order). It's now quite easy to decide if I call this, or rather order.getLineItems() - they have a different fetch strategy and fetch plan.
  3. You could argue that it would be nice if everything would /look/ the same. That is, following this repository pattern I would end up with an API like order.getLineItems() and order.getLineItemsWithProducts(). But the price I'd have to pay is A) a completely new layer in my application that is at least as complex as the DAO layer (conceptually there really is not much difference between them) and B) coupling my domain model to these repositories. And because I think there is really no difference between a generic, interface-based DAO architecture and these repositories, it means injecting DAOs into my domain model instances at runtime. That means they don't run anymore without DAOs (mock or real). Wrapping the DAOs again and again does not change that.
  4. If you do not inject and call repositories in your domain model classes, you gained nothing. You created a layer on top of the DAOs that looks like the DAOs, albeit with funny new names.

My personal best practices, when you have to decide how the persistence layer and services are integrated with the rest of the system, would be these:

  • Optimize access paths and simplify data access by carefully designing the domain model associations and persistence layer API (the latter following some good DAO pattern and related best practices - yes, there are books about this). Use the features of your transparent persistence service to make sure that all these access paths do the right thing, depending on what you need.
  • Document the access paths properly, and when each should be used. I adopt some simple conventions, for example: Never map a persistent collection unless it is absolutely necessary - this already makes things a lot easier.
  • Keep the domain model implementation clean, testable, and reusable: no security checks, transaction demarcation, or explicit data store access in any of these classes.
47 comments:
 
11. Nov 2007, 01:48 CET | Link
Magnus Heino

Imho you missed the part about aggregate roots, and the fact that repositories are part of your domain model.

Using aggregate roots you can protect how you access your persisted objects, and protect how they are updated. It's quite likely that you will need insert update delete dao methods for all your persisted objects, but it's very unlikely to have those kind of methods for all persisted objects in your repository. You will probably even not have a repository for every type of persisted objects, even though they might have daos. Respositories does not expose anything about how and if they are persisted, dao's do, even by the name.

Respoitories are part of your domain model, daos are an implementation detail.

For applications without a rich domain model, with much work being done in the service layer in a transaction script way, repositories probably doesn't make much sense though.

ReplyQuote
 
11. Nov 2007, 01:48 CET | Link
Marcus

I read Domain Driven Design as well, and I learned a lot from the ideas, and particularly the focus on creating a ubiquitous language. At the same time, I found the patterns difficult to apply directly because they appear to be rooted in a very specific style of layered development that is just a little passe when you've discovered Seam conversational components, and as both Seam and Guice promote, loosely coupled and strongly typed.

I do believe the more abstract principles in the book are extremely useful though. In fact, I feel that the Seam style of conversational components, combined with ORM mapping to relational data, just happens to be a whole lot better and more progressive paradigm for more or less the same ideas.

I have gone to the extent of claiming that projects I lead are DDD, knowing full well that plenty of DDD experts would doubt that.

Other connections I make are to both Agile and Behavior Driven Design, the former promoting iterations of user stories, and the latter basing development around testing for expected customer-facing behavior development, both correlating to ubiquitous language rather well. I can't help but think that all roads are leading to Rome: less about layers, less ivory tower, less mindless pattern implementation, and less abstraction.

I find with all of the above, if you take the abstract principles rather than the specific implementation ideas, it's easy to squint and see EntityHomes and conversational components instead.

The only really hard part is all the religious zealotry drowning out the good parts in all of these :-)

 
11. Nov 2007, 02:06 CET | Link
Marcus

I also agree with Magnus. Repositories as an idea rather than perhaps a specific implementation idiom, are quite a helpful design concept.

 
11. Nov 2007, 02:07 CET | Link

I agree with Magnus' first comment. A repository might not even use a database; it might be fetching/retrieving/updating objects from another application, like a legacy app or many many legacy apps. The abstraction it implements is not retrieve rows from a database, it represents retrieve or store meaningful business objects from the appropriate source.

My key takeaway from DDD is that the words and objects we choose to represent things in the code are very important to the long term viability of a codebase, with a lot less emphasis on the lower level code patterns.

 
11. Nov 2007, 02:25 CET | Link
repositories are part of your domain model

I'm struggling to see how this can be true. If the repository is truly part of your domain model, then it is part of the entity layer, right? The entities are the realization, in Java, of your conceptual model of the business domain.

I may be missing something here, but this repository idea stinks /architectural pattern/ to me. Just /asserting/ that it is part of the domain model does not make it so.

I'll have to read the book to form a conclusion upon whether this extra layer is worth the cost (in general, I take a dim view of introducing extra layers unless truly required by some /external/ requirement of the system). But I don't see how it can /possibly/ be part of the domain model unless it is something that we identify and specify as part of the process of /domain modelling!/

i.e. The domain model models the business domain. An architectural pattern can't possibly introduce new things into the domain model :-)

 
11. Nov 2007, 02:30 CET | Link

I don't make calls to update instances, I have a transparent persistence service and metadata to define that, not application code. And if I need to make the occasional persist(o) call, my DAO API (just like the repository thing) restricts me to pass the right root aggregate as an argument - it's typesafe. So where is the difference? The name?

I call everything that loads or saves data with some persistent store a DAO, no matter what the data store is. I think that's why we write DAOs and a persistence layer, no? Calling something FooDAO does not imply anything about how or where stuff is stored permanently. It's as meaningless (or not) as FooRepository.

The fact that DAOs suddendly become part of my domain model is indeed what I am arguing about here: It's a terribly bad idea. It's a step backwards from transparent persistence.

(Btw, don't post buzzwords such as agile and behavior driven design here. You don't get points for handwaving. This is about good maintainable code vs. this application will end up on daily WTF for sure.)

 
11. Nov 2007, 03:33 CET | Link
Debasish Ghosh | dghosh(AT)acm.org
The fact that DAOs suddendly become part of my domain model is indeed what I am arguing about here:
 
11. Nov 2007, 03:36 CET | Link
The domain model models the business domain. An architectural pattern can't possibly introduce new things into the domain model

Exactly. You do have to have some way to map the real world into the domain though. The repository is a very abstract way of representing that; the domain experts are then free to stop worrying about the actual mechanism. Even just calling it a Database is less abstract, and can color the way the domain expert starts to think about what can/can't be put there.

It's not necessarily an entire layer either. In most of the applications in our domain, the concept of a customer is not just something that resides in a database. We often have to do some pretty complex assembly. Say, start with retrieving the record in our database, which would use a data access pattern, then use some information in that record to fill out some customer info from system A, and some more from system B.

It's most likely that the fact that certain parts of the customer information are stored on various back-end systems in different forms is not a domain concern. The repository is what hides these implementation details so the domain model can focus on the domain.

Repository is not a required concept in DDD, it's just a useful abstraction. You have a successful domain focused design without ever implementing a repository in name, although I suspect with complex domains you'll find a few classes that do the same job in spirit. As long as your domain experts understand the idea and the name and aren't burdened with the implementation details of storage, it doesn't matter what you call it.

This may not be the exact repository idea expressed in the book, but just my $.02 as to what it's come to mean to our team after about two years of working on our domain model.

 
11. Nov 2007, 03:49 CET | Link
Debasish Ghosh | dghosh(AT)acm.org
The fact that DAOs suddendly become part of my domain model is indeed what I am arguing about here:

As I see it, DAOs are NOT part of the domain model. They are part of the persistence layer. Repositories are part of the domain service layer. And there r 2 value propositions for the Repository pattern : a) Repositories are designed at the level of Aggregate Root and they encapsulate the whole aggregate. So it provides a layer of abstraction to the user as far as the accessibility of the aggregate is concerned. b) Repositories speak the domain language (the Ubiquitous language). DAO methods may often be at a lower level of granularity than what the domain users speak.

 
11. Nov 2007, 04:05 CET | Link

Sorry, your repositories are the same as my (and everybody elses) DAOs. Explain what makes the root aggregate and the ubiqfoobar language so special.

 
11. Nov 2007, 04:13 CET | Link

For some reason my comment was truncated. Is there a text-only non-markup option for comments?

Point is, repositories are not the whole domain driven design. They are just an abstraction you may find useful.

Repositories are what give life to your business objects with a lifecycle outside of the application. In our example, we usually have a local database, and using the info from that database, to create the full concept of a customer we need to use that information to go retrieve some info from system A, and some from system B.

The domain expert likely doesn't care about that, they just want to see the customer. A customer repository can help hide those implementation details (assuming they are implementation details and not part of the domain; it's not always clear cut) and handle assembly or updating of complex domain objects.

So it's not part of the domain model, but it's an important bridge to the outside world. To think about repositories in terms of persistence only doesn't really capture the essence. If your entire source of record for your concept of a customer exists in your database with no other assembly required, you probably don't need a repository.

I think you can have a fine domain driven design without ever having a repository, and just because your design is full of Services, Aggregates, and Specifications doesn't necessarily mean that you are getting the most out of domain driven design.

 
11. Nov 2007, 04:16 CET | Link
Xavier

I think one of the most important thing to remember from DDD and its aggregate root concept is that when you have an order, you should always access order lines inside the context of an order (which means calling order.addLine(product, qty), order.removeLine(product, qty).). That seems obvious but thrust me, many developpers are not aware of this.

I would never directly access or store order lines from a dao because it could break things. For example, adding an order line to an order would probably mean adjusting the order's total price. You could also enforce inside your order class that it may contain at most 5 different products. If you store the line directly through an OrderLineDao, you may end up bypassing that policy. Too many times, I have seen developpers having exactly one dao for each entity in their model... how crazy is that?

The way you retrieve the order lines from an order is an implementation detail and hibernate IS certainly an enabling and facilitating technology to achieve that.

In defense of Eric Evans, I would say he started writing his book before the rise of hibernate... at that time, how would you retrieve lines from an order without the cool lazy-loaded-collections hibernate brings? Clearly, calling a findLinesForOrder(this) on some object from inside the order was probably one solution... but today, thanks to hibernate it's not needed anymore.

To recap, I think the concepts of DDD are still valuable and are certainly compatible with orm frameworks... just implement those concepts with today's technology

 
11. Nov 2007, 04:24 CET | Link

And please explain it using code.

 
11. Nov 2007, 04:25 CET | Link
In our example, we usually have a local database, and using the info from that database, to create the full concept of a customer we need to use that information to go retrieve some info from system A, and some from system B.

So it's the same as the DAO pattern, retrieving that data from somewhere without exposing the implementation details. I'm still not going to call this additional layer in my domain model classes.

Does anyone have some code that would show why we need to call one thing repository object and the other thing data access object? So far I've only seen the example from the blog entry I linked to above, with the employee stuff. This was awful code that smells badly of maintenance nightmare. Where is the value of this new thing?

 
11. Nov 2007, 04:39 CET | Link

If your data access objects exist outside of just databases, then yes I think we are talking about the same thing with a different name.

I've not seen people use DAO's as a pattern for wrapping web services calls, or legacy mainframe messaging before; if you had DAO's for that, and then wrapped them up into a single object in a broader DAO responsible for coordinating them that used the more specific ones, then that's about analogous to a repository. I think that goes pretty far beyond the typical definition of DAO.

I've just never seen anyone use DAO's for anything but fronting for databases, and a repository doesn't imply that there's a database anywhere. Often there isn't.

 
11. Nov 2007, 08:37 CET | Link
Marcus

Christian, I don't think that finding a correlation between what the many different dogmas are saying is such a bad thing, if anything it removes some of the mysticism behind whatever new terminology they tend to bring into the picture.

If all three dogmas that I mentioned are clearly dealing with a fairly similar concept at their heart, that of ubiquitous business language, then they are a whole lot less unique, special, magical, whatever, and back to more practical, intuitive, etc.

In any case, the whole repository thing really is pretty intuitive, and my point was to say that I found that what I am doing with conversational components plus ORM slips pretty easily into what DDD is promoting without really trying.

I'm more annoyed than most by the zealous proponents of whatever is the flavor of the day in architect circles, but I also think its important to discuss, deconstruct and correlate than ignore. Being allergic to their mention is just another form of fanaticism too, isn't it? :-)

 
11. Nov 2007, 14:22 CET | Link
I've not seen people use DAO's as a pattern for wrapping web services calls, or legacy mainframe messaging before; if you had DAO's for that, and then wrapped them up into a single object in a broader DAO responsible for coordinating them that used the more specific ones, then that's about analogous to a repository.

OK, so it's really the same. DAO means /data access/ not /data access through SQL/. I even write DAOs if I have to read something from a text file. So we are back here: Don't call them in your domain model classes.

 
11. Nov 2007, 18:13 CET | Link
Magnus Heino

Christian,

Articles like the one you wrote called Generic DAO pattern with JDK 5 on the old blog, and the seam examples where you inject EntityManagers into just about everything doesn't show what you are saying. These kind of patterns and examples does not communicate things like aggregate roots etc. The repository pattern does. Its more the semantics that are different than the actual implementation.

The repository pattern is not vs. transparent persistence as the title of this blog entry says. Repository pattern talks about removing and inserting objects, and you cannot do that transparently for your aggregate roots, not even with hibernate... ;-)

 
11. Nov 2007, 19:58 CET | Link

Show me the code and I will show you how to do it.

 
11. Nov 2007, 20:07 CET | Link
Alexandre Poitras

A prof that DAOs or repository are part of the business layer (and of the domain layer if you use one) is that they have a dependency on your domain object. A lower layer can't reference upper layer objects.

 
11. Nov 2007, 20:10 CET | Link
A prof that DAOs or repository are part of the business layer (and of the domain layer if you use one) is that they have a dependency on your domain object.

The problem is that this pattern encourages people to create model classes that depend on data access classes. Of course data access classes depend on domain model classes...

 
11. Nov 2007, 23:19 CET | Link
Alexandre Poitras

I see what you mean. You should check this post from Eric Evans : http://tech.groups.yahoo.com/group/domaindrivendesign/message/5802

 
12. Nov 2007, 06:51 CET | Link
anon

Here is another post with code samples. Christian and/or Gavin, your thoughts please.

http://debasishg.blogspot.com/2007/02/domain-driven-design-inject.html

 
12. Nov 2007, 14:00 CET | Link
Magnus Heino

I think these examples are getting way to technical for this discussion, and I'm not so sure I even like them. There are other uses for repositories than injecting them into entities.

I get the feeling that some people here thinks that a domain model is the same as the domain layer, which is the same thing as an entity layer which contains entities only and that is what your orm tool manages.

A domain model in the DDD sense is much more. Its about entities, value objects, repositories, services (not the same kind of service as you may have in your service layer to orchestrate calls to your domain model from your controllers or such), factories, aggregates etc...

And then you have all the strategic design patterns...

DDD is so much more than technical solutions.

(This blog is way to restrictive in what content is allowed imho. What is dangerous with a slash or equals sign?)

 
12. Nov 2007, 14:42 CET | Link
Here is another post with code samples. Christian andor Gavin, your thoughts please. http://debasishg.blogspot.com/2007/02/domain-driven-design-inject.html

Uhm, that is the blog article I linked to and referred to in my article.

 
12. Nov 2007, 20:06 CET | Link
Michael Stachel

Hi, I think Xavier has given the response, what repositories in DDD mean. They are a part of your domain layer, which means you use them to get access to entities in other aggregates. Translated into technology by using Hibernate, I would implement entities and value objects in the same aggregate with eager loading and the repository thing with lazy loading. In such cases Hibernate's lazy loading collection proxies are the implementation of the repository. This has IMHO nothing to do with the DAO pattern, which really belongs to the persistence layer and not in the domain. So in the concrete example mentioned above I would model an aggregate with the root order and the eager loaded lineItems as additional entities in that aggregate and an aggregate with product as a root. The lineItems have a mapped collection to the products with the FetchMode lazy. If the lineItems then have to work on the products, they would use logically a repository to get the appropriate products. So you have implemented the idea of an aggregate and a repository by using Hibernate. Just my 2 cents.

 
12. Nov 2007, 20:30 CET | Link
In such cases Hibernate's lazy loading collection proxies are the implementation of the repository.

Ok, great, because that is what I'm arguing for here.

However, any data access you /can't/ implement transparently (with fetch strategy, fetch plan, cascading metadata, etc.) should certainly not result in direct calls from domain model classes to data access classes. Which, if I understand it correctly - and I'm still not sure why the advocates of this pattern don't see that - is what this repository pattern recommends.

 
12. Nov 2007, 21:21 CET | Link
Michael Stachel

Your inspection of this DDD pattern is IMHO way too technical only. Your strongly disagreement with the domain object not being allowed to use a dao object is only an observation snapshot of moments technology best practices. In former days you have to implement this pattern with access to dao. Now you could use Hibernate. But if you look at it abstractly, nothing has changed. Also Hibernate does use your persistence store to get your lazy loading done. The differences are only that first the framework (Hibernate) does that for you instead of your own daos and second that you have a certain kind of metadata providing some kind of loose coupling defining that. But you could also invent metadata on your own and use your daos then. So in the end it's the idea what counts and the rest are implementation details.

 
12. Nov 2007, 21:52 CET | Link
Your strongly disagreement with the domain object not being allowed to use a dao object is only an observation snapshot of moments technology best practices. In former days you have to implement this pattern with access to dao.

No! I certainly would never call DAOs from domain model classes. Just like I'd never recommend you call a repository from these classes.

 
13. Nov 2007, 07:46 CET | Link
Dan

I think the example you chose raises one set of issues - when you have an entity Order that is in a one-to-many relationship with an entity LineItem, you have a choice to navigate that relationship either transparently, lazy-loaded or not, via an object-oriented path of order.getLineItems(), or you can choose to not map that relationship and have to go through a DAO.

And that's an interesting question. But I think an example that's more to the point is brought up in one of the responses (www.fabiokung.com/2007/11/12/comments-to-gavin-king-about-ddd-and-repositories): When you have a one-to-many of Client to Orders, and want to find all of the orders since a particular date (client.getOrdersSince(date)), that's not something where you really have the option of using a mapped association.

There seems to be a bit of a semantic question around DAO and Repository, but the most interesting question to me is whether it's acceptable to embed a DAO inside an entity, which may contradict a particular notion about a separation of concerns, but which provides a more intuitive, friendly, object-oriented API.

I feel like I am doing something wrong to put the DAO inside the entity, but I just can't argue with the simplicity of: order.save() instead of getOrderManager().save(order) which forwards to getOrderDao().save(order). Most of my service layer constructs have vanished, and when they do exist, it's to perform real business logic, not to delegate through a layer for purity's sake.

 
13. Nov 2007, 16:04 CET | Link
Tolomaüs

Very interesting discussion.

In my opinion Hibernate (or any other ORM) makes it possible to hide the data storage details from your domain layer so that it appears as if all your business entities are available in one central registry.

Before a use case can start using and manipulating one or more entities in order to get its work done, it obviously needs to get a hold of them first. So we have to foresee something to take up this responsibility. In my own solution I called this something the Portal (it's in fact the door towards the centrally stored entities), but after reading the article mentioned before I changed its name to Repository. (I could have called it DAO of course, but I didn't like the D of Data in it, after all, we're talking about entities here, not data).

Some more things I noticed while using this Repository pattern:

1) As it is used by the use cases, it is part of the domain layer, no discussion about that. I would even consider it to move it up towards the presentation layer if it contains too much use case specific functionalities that cannot be reused by other use cases.

(I consider a use case as being one way - of many possible ways - to accomplish a certain task. All necessary steps are in the domain model, the use case can only decide on the sequence of these steps.)

2) Whenever the use case needs a set of entities that fundamentally belong to an entity it already has (like the order lines of an order), I will make sure they are available as a collection of this entity, so no need to go through the Repository here.

3) Although I have not yet had the need for it, it seems perfectly OK for me to use the Repository inside an entity. Sometimes it is only the entity that knows which additional entities it needs to accomplish its task. This could even depend on the outcome of a certain algorithm inside this entity.

So far about the term Repository as a concept. Implementation-wise it could take different forms. If coupling and reusability are not an issue, I could use the Hibernate session itself as a Repository. Or, if I want more abstraction, I could create my own ORM-independent object query language. If I also want reusability I could use a Repository class to store my queries (either one big Repository or one for each entity). I prefer the last approach because it also abstracts all query related functionalities from the rest of the application.

(Note that I have not read the DDD-book yet, so maybe I'm not using the correct terms)

 
18. Nov 2007, 20:48 CET | Link

Appologies for being rude but I don't think you really understand the repository pattern.

You have focused too much on one possible implemenattion choice. Repository is a high level pattern, whether you use DAO's/interfaces/depdency injection is up to you and certainly is not covered in detail in the DDD book.

My personal implementation is to have repositories that all inherit from an abstract base class that does the majority of the work (GetById, GetAll, SaveOrUpdate). I'm using NHibernate and i haven't felt the need to include DAO's or to have my repositories implement interfaces (well sometimes), most of the time my domain classes never directly use repositories and I'm quite happy with that approach. So even if I do consider them part of the domain model they aren't a part that I want my normal (entity or value object or service) classes communicating directly with.

Thats just one way to do it though

---

You also say

Sorry, your repositories are the same as my (and everybody elses) DAOs. Explain what makes the root aggregate and the ubiqfoobar language so special.

See the bit in POEAA, DDD or the DDD forum which has lots of posts about this...how far they are from DAOs would seem to depend on the way you implement them though.

---

No! I certainly would never call DAOs from domain model classes. Just like I'd never recommend you call a repository from these classes.

Agree completely, though we've had to do it a few times when we couldn't get NHibernate ot play ball.

 
18. Nov 2007, 21:58 CET | Link

I tried to post my own response:

http://colinjack.blogspot.com/2007/11/repository-implementation-dddnhibernate.html

I personally think that (other than a few issues like the unit of work) Hibernate actually makes repositories much easier to use...

 
20. Nov 2007, 06:47 CET | Link
Jeffrey Lebowski

I'm curious about this best practice?

Never map a persistent collection unless it is absolutely necessary - this already makes things a lot easier.

Would you mind elaborating a little as we do that a lot. I understand your concern having multiple access paths for accessing data - but is that the only reason? Why choose to kick out the order.getLineItems() method instead of kicking out the the lineItemDAO.findAllForOrderId(order.getId()) method. You must have a strong preference for the latter and I'm curious why?

 
23. Nov 2007, 18:06 CET | Link
Adib

My read of the DDD book, is that the repository is a part of the Domain Layer rather the the domain model.

The domain model has classes and objects which represent concepts from the problem domain.

The domain layer includes the domain model, and factories, and repositories and domain services designed to make the usage of the domain model simple and efficient for the layers above the domain layer.

I would personally consider hibernate to be something that provides me with a infrastructure service, and the objects that I persist with hibernate are not necessarily part of my domain model.

my 2 cents.

 
02. Dec 2007, 14:14 CET | Link
Gianni
...carefully designing the domain model associations and persistence layer API (the latter following some good DAO pattern and related best practices - yes, there are books about this)

Can you recommend some books please.

 
16. Dec 2007, 00:32 CET | Link
Dan

@Christian - Sorry, your repositories are the same as my (and everybody elses) DAOs. From this and other comments you made, I have to ask - have you read the book? I suspect your view might be a bit more nuanced and less dismissive if you had.

When I saw this thread and others before I had read the book, it all seemed like a lot of vague hand waving to me too. Then I read the book, and now I understand things much better. I think there is something interesting in the Repository idea in certain situations, particularly when used with the idea of aggregates that draw a line of responsibility around certain entities.

Like everything, it's not a silver bullet. You use it when it makes sense, you don't when it doesn't.

 
15. Jan 2008, 19:14 CET | Link

Hmm... I have to admit that when I first read about the Repository pattern (PoEAA and then DDD, bul also POSA, although withna different name) I thought that this was just another name for a DAO.

But some differences do exists (and some have already been pointed out here), like being more Domain-Oriented than normal DAOs, or unrelated to persistence representation choices. Maybe the point here is what is exactly a DAO? (or what is the reference Bible ;-) ); overlapping pattern definitions, common use and code generation gave us a perception of DAOs as bound to a relational representation of data in a database. Is this a constraint? Probably not: as Christian points out, a DAO can be as abstract as needed, and it can be a matter of style to be data-bound or domain-bound. It's less of an issue in many domains, but can become interesting if the domain - or the underlying architecture gets more complicated.

Repositories, also enforces persistence access only via Aggregate Roots. This is good and simplifies a lot of things when mapping lazy associations or dealing with parent-child relationships. We observed that an Aggregate Root approach quickly solved tricky situations where we were tangled in propagating updates and the same. Forcing to access to storage only via aggregates is definitely a good thing. Enforcing this practice using a Repository layer over the DAO layer might be overkill.

 
29. Jan 2008, 02:13 CET | Link
Larry Chu

The reference newsgroup discussion is a bit dated, and at the time it was written (Jan 2004), hibernate 3.0 was pre-alpha I believe. I don't think it was the intent of the author of the discussion to propose layering Repositories over DAOs but rather to propose a solution to a particular problem he had been facing that hibernate was not capable of providing a solution for at the time. Given the new features in hibernate 3, it is probably possible to map the association directly in hibernate. Furthermore, in the reference article, the author is not proposing injecting an Entity with a Repository. The Entity is injected with a DAO to implement the association because his version of hibernate is unable to provide a mapping for his legacy database. In fact the author takes care not to call his injected DAO a Repository.

The point is that a Repository can be implemented with or without an ORM tool (such as hibernate), and its implementation can be as complex or as simple as needed because its implementation is encapsulated.

When I first read the DDD book, I too had a lot of difficulty grasping the fundamental differences between the DAO and the Repository. Now, it is my opinion that Repository is a further refinement of the DAO pattern rather than something in addition to it. Perhaps the Repository can be thought of as a subset of DAOs best used when working with rich domain models, while the more general DAO pattern should be used in conjunction with Transaction Scripts and DTOs. There does not appear to be much reason why an object cannot be both a DAO and a Repository at the same time. To draw an analogy, in the GoF book, the Interpreter pattern is an application of the Composite pattern for a more specific usage. Fundamentally, the difference is that the Repository is a domain-oriented pattern, and the DAO is a technical pattern.

 
30. May 2008, 03:52 CET | Link
bogdan

My conclusion... Today's DAO are much liky a Repository and today's DAO are NOT a Table Data Gateway (not a DAO for every table but a DAO for a root only, the rest is done by Hibernate's fetching)

 
13. Jul 2008, 03:32 CET | Link

This thread has completely missed one point that the DDD book was trying to make: Repositories return a sane, fully constructed object. This includes assertion checking and building, something which (I think, not completely sure) transparent persistence doesn't do.

And what happens if you want to use foowhizzbang instead of hibernate to implement persistence? With repositories, that change is mitigated.

Erich

 
14. Nov 2008, 22:51 CET | Link
Cyril

A bit late to the thread, but my thoughts ...

My Objects need to collaborate with other Objects. If the Object instance I want to collaborate / associate with already exists then I want a Repository to go and get it for me. I don't use the term DAO because that implies that I'm just asking for data; I want an Object. Of course I don't want to couple up to the details of accessing data from the database (or other store), but I have to get my Objects from somewhere and Repository is a good term for a type of Service that I need to do this task. I don't see any harm in this pattern, In my unit-tests I can easily mock the Repository, though its a little bit more work than using the hibernate proxy way of doing things i guess.

 
05. Jun 2009, 03:53 CET | Link

OK -- So I started a contract a few weeks ago and the customer is suggesting using the Repository pattern from DDD. I wanted to get some information on the pattern and found this blog. It's a great discussion, but ...

If anyone is still paying attention to this, isn't the Repository pattern acting more like a Builder pattern in most of the instances here? I'm not sure that it should even be called a Repository pattern; maybe something else would convey the pattern more ubiquitously :). Transparent persistence seems to handle the persistence layer very well (i.e. Hibernate/JPA -- very nice job Gavin). If your business objects are not represented well enough as a result of the persistence layer implementation (entity objects, etc.), would that not be the job of a Builder or Manager class.

Once again, it seems like we are really over-thinking the persistence layer and trying to introduce another thin layer in order to bring the technical world one step closer to the business folks. Maybe it's just the cynic in me, but are we trying to make business people into application architects/developers again, just like we tried with SQL and 4GL's a couple of decades ago? At some point in time, we need to realize that there are only so many damn layers that you can introduce before you're actually managing the architecture and not the code.

Whew, thanks --- I needed that. I look forward to your dissension.

Erich

 
17. Feb 2010, 02:22 CET | Link

@Christian Bauer,

show me the code: I like the spirit :)

if you use DAO to read and write to flat files, and to orchestrate other DAO calls, Repository will do you no good, keep using that DAO, I agree it is a Data Access Pattern, so it is a pattern to access data nothing more, nothing less.

I think Repository make sense in DDD world, but not as a stand alone pattern, and yes, DDD is a whole different world, I don't think it makes sense to pull out individual patterns from it.

On the other note, you guys are sooo worried about those developers. Your developers always don't understand something, always weak on logic, always need some extra help from architects (you are architects, right? ha ha :) ). Well a couple of advises to all people who worry about their developers: Train Them!, and/or Hire Solid Ones. What is the point of having Silly Developers if you always need to spend more and more money on all this delicate architecture to please them, and make their life easier...

/Toly

 
11. Mar 2010, 08:04 CET | Link
Timex
Toly, well said!

Before I posted, my write-up exploded into a billion pages...almost. Yikes. I might write a blog about what my view is. Nonetheless I'll try to be relatively concise.

In a nutshell, I think the real issues are:

[1] Choosing whether you will have a dedicated domain model to begin with v.s. a classic data model;
[2] accept the fact that they have different roles; one cannot and should not be coerced into the other;
[3] obey the interface segregation principle:
    [*] don't pollute interfaces;
    [*] different clients need different interfaces; don't mutate, rather demarcate;
    [*] and no fatties, please! (morbidly obese interfaces - including the concrete public interfaces)

So, we first must grow up (come on, really, its compatible with success) and admit that DAOs as they appear in classic DALs are completely different than a domain model or associated repositories. Second, this "domain" seems to have an uneccasary sense of esoterism to it. If I were to reference ISO11179 naming standards for "domain model", domain would be the property term and "model" would be the representation term. But where is the qualifier terms? Let's fix it: BusinessDomainModel. I read and think, "Duh! Oh yeah! Its business." Case in point, the domain layer is the business logic layer (BLL, for you classicists). Not data; business. Rules. Policies. Security. Activities. Processes. Administration. Business.

Secondly, the repository should not have any notion of "unit of work". Per interface segregation principle (ISP), the repository's interface should only define what it intends to provide: a view of the model.

You read right: model, view. Where is the controller? Bingo! That is the missing piece here. Add a controller that your clients interact with, and if you follow the practices, this should end up being a cohesive solution. Beautifully enough, in the "real-world" there is the notion of a "controller". What is it? The process. But to stay true to DDD, the process should be dedicated only the very-closely-related real world aspects: the What. But you still have the How. In a real-world order process, for example, a salesperson must tell a warehouse packaging person which products to pick and package. That is the WHAT (i.e a TODO) - a noun. To accomplish this, though, the saleperson may email, phone, or physically walk down to (maybe the system is down) tell the fulfillment crew about the order. That is the HOW - the action verb. The process dictates what but not how per se.

So, if you make your controller represent the HOW aspect, all of the rest fall into place. The DAL and its DAOs and/or ORM can be specific (and thus optimized) for data-centric things, your repositories (any respectable system should have more than one) can concern themselves with the view of the data from the underlying DAL (not replacing the DAL), and your controller (it needs a fancy DDD name) deals with coordinating with the model and the view to accomplish a unit of work (which is often transactional, conceptually).

With this approach, I see many benefits:

+ leverage code-generation/template tools
+ cleanly keeps domain abstracted from infrastructure
+ clearly defines expertise areas and roles (part of the problem, I think)
+ encourages agile development due to good separation of concern
  > one can prototype directly against a DAL or DAO, until the repository is built, etc.
  > one can choose to go forward OR backward based on needs, not affecting visible deliverables
    ex. For a CTP, you may temporarily jerk the repository for refactoring, but for a subsequent Beta put it back.
+ one can mock up their models for testing via the IoC facilities provided by a dedicated controller

There are a few drawbacks

- slightly larger architecture
- for small shops, requires a high degree of lateral knowledge from developers
- not enough tooling yet to promote realization of long-term productivity of this approach

As is always the case, "it depends". But the realcase in point are the principles. In either case, if you follow the SOLID and GRASS principles you can't go that terribly wrong. If you do need a repository (or want to future proof yourself in anticipation of business growth - a smart idea), then I say implement a controller as part of your infrastructure. Decide if you need it or not, do your recon and modeling, pick your candidates, and roll.

- Timex
 
11. Oct 2010, 19:58 CET | Link
Wix

Timex,

I believe you hit the nail on the head. The repository is not about replacing DAO but really hiding them and only concerning itself with giving the caller the object it asked for. That caller in many cases is a controller. The controller doesn't care where the data comes from all it know is it asked for an Order object and it better get it.

So the OrderRepository may call an OrderDao (Data Mapper or whatervr), CustomerDao, LineItemDAO, etc. Then the repository constructs the object graph and returns it to the caller. This allows for our separation of concerns:

Repository: Constructs the object graph of an aggregate root from the data returned from DAOs, and returns that domain aggregate to the caller. DAO: The object that actually retrieves a piece of data from a data source.

 
05. May 2011, 21:19 CET | Link
Rafi

Hi Christian!

This is pretty old post, however it was very interesting for me, like whole discussion about it. Thanks!

My question is, what do you mean by below statement?

Never map a persistent collection unless it is absolutely necessary - this already makes things a lot easier.

Could you please give me longer explanation or maybe some example or article on this?

Best regards! R;

Post Comment