Search code examples
domain-driven-designddd-repositories

DDD, Aggregates and Entities


I have a following domain object structure

Invoice
 - List<Items>
      - Service

Invoice has a list of items, and each of that items has a service.

DB Structure is following

Invoices Table
Items Table (fk to invoice, fk to service)
Services Table

If i understood correctly, Invoice is aggregate, items are entities and service is value object for Item in this scenario?

What happens if i need to add new services to database. Should i create a new Service class, which will then be aggregate for that scenario, and have it's own repository?


Solution

  • Invoice
     - List<Items>
          - Service
    

    First thing to note - that's a description of structure. The motivation of aggregates in DDD isn't structure, but behavior. The role of an aggregate is to ensure that a modification made to the structure conforms to the business rules.

    If i understood correctly, Invoice is aggregate, items are entities and service is value object for Item in this scenario?

    Close, but the terminology is a bit more murky than that (sorry). If this structure represents the state within an aggregate boundary, then Invoice will be an entity that acts as the aggregate root, and the aggregate itself will normally be called the Invoice aggregate.

    Items and Service might be value types, or they might be entities. You'd need more information to know for sure. Guessing from the names (which should be taken from the ubiquitous language), they are probably both entities. ServiceName or ServiceId are more likely to be value types.

    An important point: if these are entities, their life cycles are subordinate to that of the Invoice. In other words, a "cascade delete" of the invoice would take the items and the service with it.

    What happens if i need to add new services to database. Should i create a new Service class, which will then be aggregate for that scenario, and have it's own repository?

    Slightly backwards: the persistence component supports the domain model, not the other way around.

    If Service is an entity, and that entity has a life cycle that is independent of any one invoice (for instance, if two different invoices can refer to the "same" Service), then the Service entity should be in a different aggregate than the Invoice, and the state of the invoice contains a reference to the service, rather than the service itself.

    If that's the right model, then it follows that the Service aggregate will have its own repository.