Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm diving in to Domain Driven Design and some of the concepts i'm coming across make a lot of sense on the surface, but when I think about them more I have to wonder if that's really a good idea.

The concept of Aggregates, for instance makes sense. You create small domains of ownership so that you don't have to deal with the entire domain model.

However, when I think about this in the context of a web app, we're frequently hitting the database to pull back small subsets of data. For instance, a page may only list the number of orders, with links to click on to open the order and see its order id's.

If i'm understanding Aggregates right, I would typically use the repository pattern to return an OrderAggregate that would contain the members GetAll, GetByID, Delete, and Save. Ok, that sounds good. But...

If I call GetAll to list all my order's, it would seem to me that this pattern would require the entire list of aggregate information to be returned, complete orders, order lines, etc... When I only need a small subset of that information (just header information).

Am I missing something? Or is there some level of optimization you would use here? I can't imagine that anyone would advocate returning entire aggregates of information when you don't need it.

Certainly, one could create methods on your repository like GetOrderHeaders, but that seems to defeat the purpose of using a pattern like repository in the first place.

Can anyone clarify this for me?

EDIT:

After a lot more research, I think the disconnect here is that a pure Repository pattern is different from what most people think of a Repository as being.

Fowler defines a repository as a data store that uses collection semantics, and is generally kept in-memory. This means creating an entire object graph.

Evans alters the Repository to include Aggregate Roots, and thus the repository is amputated to only support the objects in an Aggregate.

Most people seem to think of repositories as glorified Data Access Objects, where you just create methods to get whatever data you want. That doesn't seem to be the intent as described in Fowler's Patterns of Enterprise Application Architecture.

Still others think of a repository as a simple abstraction used primarily to make testing and mocking easier, or to decouple persistence from the rest of the system.

I guess the answer is that this is a much more complex concept than I first thought it was.

share|improve this question
1  
"I guess the answer is that this is a much more complex concept than I first thought it was." This is very true. –  qes Feb 16 '11 at 22:35
    
for your situation, you might create a proxy for the aggregate root object that selectively retrieves and caches data only when it is requested –  Steven A. Lowe Jun 3 '11 at 15:55

4 Answers 4

Don't use your Domain Model and aggregates for querying.

In fact, what you are asking is a common enough question that a set of principles and patterns has been established to avoid just that. It is called CQRS.

share|improve this answer
    
Interesting, I have not found mention of CQRS in any of the typical DDD sources... I'll look into it. –  Erik Funkenbusch Feb 14 '11 at 6:21
    
So, after googling a bit on this, it doesn't seem that CQRS is intended to solve the problem i'm referring to. CQRS is about seperating command and query operations, and removing state. It seems more like CQRS is designed to solve various consistency problems, not providing the minimal data needed for an operation (which is basically what i'm discussing) –  Erik Funkenbusch Feb 14 '11 at 6:40
1  
@Mystere Man: No, it is for providing the minimal data needed. That's one of the large purposes of a separated read model. It also helps tackle some concurrency issues up front. CQRS has several benefits when applied to DDD. –  qes Feb 14 '11 at 14:31
    
The purpose of the read side is to have exactly the data you need for each individual task, easy and efficiently available. Also, CQRS can be implemented with fully synchronous, in-process buses, so that eventual consistency doesn't really come into play. –  qes Feb 14 '11 at 14:32
2  
"I can't imagine that anyone would advocate returning entire aggregates of information when you don't need it." I'm trying to say that you are exactly correct with this statement. Do not retrieve an entire aggregate of information when you do not need it. This is the very core of CQRS applied to DDD. You don't need an aggregate to query. Get the data through a different mechanism, and then do that consistently. –  qes Feb 16 '11 at 22:37

I struggled, and am still struggling, with how to best use the repository pattern in a Domain Driven Design. After using it now for the first time, I came up with the following practices:

  1. A repository should be simple; it is only responsible for storing domain objects and retrieving them. All other logic should be in other objects, like factories and domain services.

  2. A repository behaves like a collection as if it's an in memory collection of aggregate roots.

  3. A repository is not a generic DAO, each repository has its unique and narrow interface. A repository often has specific finder methods that allow you to search the collection in terms of the domain (for example: give me all open orders for user X). The repository itself can be implemented with the help of a generic DAO.

  4. Ideally the finder methods will return only aggregate roots. If that's to inefficient it can also return read only value objects than contain exactly what you need (although it’s a plus if these value objects can also be expressed in terms of the domain). As a last resort the repository can also be used to return subsets or collections of subsets of an aggregate root.

  5. Choices like these depend on the technologies used, as you need to find a way to most efficiently express your domain model with the technologies used.

share|improve this answer
    
Its definitely a complex subject for sure. It's hard to turn theory into practice especially when its combining two distinct and separate theories into a single practice. –  Sebastian Patten Sep 3 at 18:54

I don't think your GetOrderHeaders method defeats the purpose of the repository at all.

DDD is concerned (among other things) with ensuring that you get what you need by way of the aggregate root (you wouldn't have a OrderDetailsRepository, for instance), but it doesn't limit you in the way you are mentioning.

If an OrderHeader is a Domain concept, then you should have it defined as such and have the appropriate repository methods for retrieving them. Just make sure that you're going through the correct aggregate root when you do.

share|improve this answer
    
Perhaps i'm confusing concepts here, but my understanding of the repository pattern is to decouple the persistence from the domain, by use of a standard interface for persistence. If you have to add custom methods for a specific feature, that seems to to be coupling things back up again. –  Erik Funkenbusch Feb 14 '11 at 6:19
    
The persistence mechanism is decoupled from the domain, but not what is being persisted. If you find yourself saying things like "we need to list the Order Headers here", then you need to model OrderHeader in your Domain and provide a way to retrieve them from your repository. –  Eric King Feb 14 '11 at 13:23
    
Also, don't get hung up on the "standard interface for persistence". There's no such thing as a generic repository pattern that will suffice for all possible apps. Each app will have many repository methods beyond the standard "GetById", "Save", etc. Those methods are the starting point, not the end point. –  Eric King Feb 14 '11 at 13:27

My use of DDD may not be considered "pure" DDD but I have adapted the following real world strategies using DDD against a DB data store.

  • A aggregate root has an associated repository
  • The associated repository is only used by that aggregate root (it is not publicly available)
  • A repository can contain query calls (e.g. GetAllActiveOrders, GetOrderItemsForOrder)
  • A service exposes a public subset of the repository and other non-crud operations (e.g. Transfer Money from one bank account to another, LoadById, Search / Find, CreateEntity, etc.).
  • I use the Root -> Service -> Repository stack. A DDD service is only suppose to be used for anything an Entity can't answer itself (e.g. LoadById, TransferMoneyFromAccountToAccount), but in the real world I tend to also stick in other CRUD related services (Save, Delete, Query) even though the root should be able to "answer/perform" these themselves. Note that there is nothing wrong with giving an entity access to another aggregate root service! However, remember you would not include in a service (GetOrderItemsForOrder) but would include that in the repository so that the Aggregate Root can make use of it. Note that a service shouldn't expose any open queries like the repository can.
  • I usually define a Repository abstractly in the domain model (via interface) and provide a separate concrete implementation. I fully define a service in the domain model injecting in a concrete repository for its use.

** You do not have to bring back an entire aggregate. However, if you want more you have to ask the root, not some other service or repository. This is lazy loading and can either be done manually with poor man lazy loading (injecting the appropriate repository/service into the root) or using and ORM that supports this.

In your example, I would probably provide a repository call that brought just the order headers if I wanted to load the details on a separate call. Note that by having an "OrderHeader" we are actually introducing an additional concept into the domain.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.