4

I have a quite complex aggregate, with aggregate root Order. It contains entities (eg. OrderItem) which are meaningless outside an aggregate. But there are also entities that are supposed to be part of this aggregate, but also do make sense outside this aggregate (eg. ShippingMethod or Invoice).

Is it right to have a repository for this complex aggregate (loading whole aggregate by root's id) and also have CRUD repository for managing possible shipping methods and another repository for listing invoices?

More generally, is it possible in DDD to have an aggregate, which is part of another aggregate?

Matěj Koubík
  • 1,087
  • 1
  • 9
  • 25
  • Does this help: http://stackoverflow.com/questions/17611635/reference-another-aggregate-root-inside-another-aggregate-root/17620246#17620246 – Eben Roux Jul 18 '13 at 10:34
  • 1
    Having just a value object representing data from `ShippingMethod` looks like a good idea, thanks. – Matěj Koubík Jul 18 '13 at 11:31

1 Answers1

4

You can consider "an aggregate, which is part of another aggregate" as "an aggregate holds another aggregate's reference".

For example

public class Order {
    private Invoice invoice;
}

<class name="Order" table="T_ORDER">
    <one-to-one name="invoice" column="INVOICE_ID" />
</class>

If both Order and Invoice are aggregates in this context, I'll have a OrderRepository and a InvoiceRepository.You can retrieve an Order using

orderRepository.findBy(orderId)

And you can retrieve an Invoice using

invoiceRepository.findBy(invoiceId) 

or

Order order = orderRepository.findBy(orderId);
Invoice invoice = order.getInvoice();

And there is famous article about how to design aggregates(http://dddcommunity.org/library/vernon_2011/) which suggests realizing this relationships using Identity reference.

public Class Order {
    private InvoiceId invoiceId;
}

<class name="Order" table="T_ORDER">
    <component name="invoiceId">
        <property name="value" column="INVOICE_ID" />
    </component>
</class>

You can retrieve an Order using

orderRepository.findBy(orderId)

And you can retrieve an Invoice using

invoiceRepository.findBy(invoiceId) 

or

Order order = orderRepository.findBy(orderId);
Invoice invoice = invoiceRepository.findBy(order.getInvoiceId()); 
Yugang Zhou
  • 7,123
  • 6
  • 32
  • 60
  • How to implement this using ORM (I'm using php and doctrine)? Isn't having a referencing id directly in entity considered as an antipattern? – Matěj Koubík Jul 18 '13 at 11:28
  • I'm not familiar with php and doctrine. But it could be implemented using regular one-to-one mapping with Hibernate in Java(In Aggregate reference Aggregate case). I'm not sure is referencing id an anti-pattern, is there some articles or resources that discuss this? – Yugang Zhou Jul 18 '13 at 11:39
  • Doctrine is heavily inspired by Hibernate. I mean having an integer attribute like invoiceId in an entity is an antipattern, according to http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/best-practices.html#don-t-map-foreign-keys-to-fields-in-an-entity. Edit: Now I see you meant not an integer, but a value object containing just id. – Matěj Koubík Jul 18 '13 at 11:55
  • The referencing id is a value object. You would now issue two queries instead of navigating through `Order` to `Orderitems`. – JefClaes Jul 18 '13 at 16:33
  • But I'd like to have Order.invoice_id in db as a foreign key because of easier reporting. Is there way to map it to VO in domain model and to related entity in reporting model? Or should I separate domain entities and persistance entities (they would be almost the same)? – Matěj Koubík Jul 19 '13 at 08:47
  • @MatějKoubík Answer updated for adding hibernate mapping example. You'd better not seperate domain models and persistence objects, see http://stackoverflow.com/questions/17650073/orm-how-to-deal-with-the-correspondence-between-domain-object-and-persistent-o. – Yugang Zhou Jul 19 '13 at 09:47
  • But then I couln't use HQL for reporting, because invoice_id is an integer, not a reference to Invoice entity. Or? – Matěj Koubík Jul 19 '13 at 15:19
  • Honestly, I have the same question if adopting the identity reference case. I'm reading Vernon's article, hope to find some clue. – Yugang Zhou Jul 19 '13 at 15:23