florian norbert bepunkt
florian norbert bepunkt

Reputation: 2539

Manage aggregate boundaries (DDD)

I have a problem understanding how to separate aggregates in DDD. At least, I have a conflict of interests that I do not know how to solve. As far as I understand, in DDD an aggregate is defined as a transactional boundary that enforces invariants / consistency. However, this results in my aggregate being huge and difficult to maintain.

My use case is a system for processing e-commerce orders. The basic flow based on the business requirements is as follows:

  1. External system (shopping cart) creates an Order, containing shipping address, billing address and line items.
  2. The order is fulfilled by creating a FulfillmentOrder, which is sent to an external fulfillment service provider.
  3. The external fulfillment service sends the goods and creates one or several Shipments for a given fulfillment order. Each shipment includes shipped line items, a departure country (the country of the warehouse of this external service) and a destination country (=== shipping address country)
  4. An Invoice is created for each shipment, with VAT / sales tax calculated based on departure and destination country of the Shipment.

This is a simplified version of the domain. As you can see, there is a sequence of well-defined steps, but there are some entanglements.... Steps depend on data from previous steps and different entities. Most importantly: the relationship between Order and Shipment (and therefore Order and Invoice) is 1:many and not 1:1.

Based on the aggregate definition above I would design the described use case as one Bounded Context (order processing) with Order being my aggregate root and Fulfillment Order, Shipments and Invoices being collections of entities managed by the aggregate root.

There are several invariants, that span across all multiple entities, for example:

Having the order as the sole aggregate root allows enforcing these invariants. But it results in the order aggregate being huge and hard to maintain.

On the other hand I could model Order, Fulfillment Order, Shipment and Invoice as aggregates each. This would make each aggregate slimmer and more focused. But I lose the ability to enforce the invariants above (which is obviously bad for business, but also against DDD principles)

Is there any guidance in domain modelling in which direction to go or some comparisons of benefits / drawbacks of strategies?

Upvotes: 0

Views: 545

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57214

Is there any guidance in domain modelling in which direction to go or some comparisons of benefits / drawbacks of strategies?

A good starting point is Memories, Guesses, and Apologies (Helland - 2007).

Aggregate boundaries are motivated by domain dynamics: which pieces of information must change together. "Must change together" has a temporal aspect - we aren't talking about information that must be consistent when the system reaches equilibrium, but rather which data relationships must hold while things are changing.

To distinguish the two, you have to pay a lot of attention to questions like: what's the cost to the business if the information in this report is out of date?

You cannot create an invoice that includes a non exiting order item.

Why not? What's the cost to the business when this happens?

A microsecond difference in timing shouldn’t make a difference to core business behaviors. -- Udi Dahan, 2010

You have to be careful in your modeling to about assumptions that information travels instantly through your system. Especially in systems that touch the real world, information travels at finite speed, and the business processes include compensation protocols.

Upvotes: 2

Related Questions