0

Eric Evan's DDD book, pg. 152:

Provide Repositories only for AGGREGATE roots that actually need direct access.

1. Should Aggregate Roots that don't need direct access be retrieved and saved via repositories of those Aggregate Roots that do need direct access?

For example, if we have Customer and Order Aggregate roots and if for whatever reason we don't need direct access to Order AR, then I assume only way orders can be obtained is by traversing Customer.Orders property?

2. When should ICustomerRepository retrieve orders? When Customer AR is retrieved ( via ICustomerRepository.GetCustomer ) or when we traverse Customer.GetOrders property?

3. Should ICustomerRepository itself retrieve orders or should it delegate this responsibility to a IOrderRepository? If the latter, then one option would be to inject IOrderRepository into ICustomerRepository. But since outside code shouldn't know that IOrderRepository even exists ( if outside code was aware of its existence, then it may also use IOrderRepository directly ), how then should ICustomerRepository get a reference to IOrderREpository?

UPDATE:

1

With regards to implementation, if done with an ORM like NHibernate, there is no need for an IOrderRepository.

a) Are you saying that when using ORM, we usually don't need to implement repositories, since ORMs implicitly provide them?

b) I do plan on learning one of ORM technologies ( probably EF ), but from little I did read on ORMs, it seems that if you want to completely decouple Domain or Application layers from Persistence layer, then these two layers shouldn't use ORM expressions, which also implies that ORM expressions and POCOs should exist only within Repository implementations?

c) If there is a scenario where for some reason AR root doesn't have a direct access ( and project doesn't use ORM ), what would your answer to 3. be?

thanks

EdvRusj
  • 745
  • 7
  • 14

1 Answers1

3

I'm hard-pressed to think of an example where an aggregate does not require direct access. However, I think at the time of writing (circa 2003), the emphasis on limiting or eliminating traversable object references between aggregates wasn't as prevalent as it is today. Therefore, it could have been the case that a Customer aggregate would reference a collection of Order aggregates. In this scenario, there may be no need to reference an Order directly because traversal from Customer is acceptable.

With regards to implementation, if done with an ORM like NHibernate, there is no need for an IOrderRepository. The Order aggregate would simply have a mapping. Additionally, the mapping for Customer would specify that changes should cascade down to corresponding Order aggregates.

When should ICustomerRepository retrieve orders?

This is the question which raises concern over traversable object references between aggregates. A solution provided by ORM is lazy loading, but lazy loading can be problematic. Ideally, a customer's orders would only be retrieved when needed and this depends on context. My suggestion, therefore, is to avoid traversable references between aggregates and use a repository search instead.

UPDATE

a) You would still need something that implements ICustomerRepository, but the implementation would be largely trivial if the mappings are configured - you'd delegate to the ORM's API to implement each repository method. No need for a IOrderRepository however.

b) For full encapsulation, the repository interface would not contain anything ORM-specific. The repository implementation would adapt the repository contract to ORM specifics.

c) Hard to make a judgement on a scenario I can't picture, but it would seem there is no need for Order repository interface, you can still have an Order Repository to better separate responsibilities. No need for injection either, just have the Customer repo implementation create an instance of Order repo.

eulerfx
  • 36,769
  • 7
  • 61
  • 83
  • I take it you usually don't completely decouple App/domain layer from persistence layer, simply because using ORM expressions in App/Domain layers offers so many benefits? – EdvRusj May 22 '13 at 20:09
  • 1
    It depends on the project. Sometimes it isn't very valuable to abstract repository implementation. Other times it makes sense for encapsulation purposes. They key is not to over-engineer the abstraction. – eulerfx May 22 '13 at 20:24
  • I think that the most important is actually to understand that an Aggregate Repository is not a 1 <-> 1 relationship between your entity and a repository implementation, the Repository itself should represent how is designed your aggregate, and therefore your domain, in your case, you could gather both query to get Customer and Orders by Customer in your Repository without the need to do Object Traversal (let's say your Customers' Orders may get bigger and bigger), but as always, it depends™ – Boris Guéry Jul 19 '13 at 09:07