How should I design DDD aggregate with an invariant based on information from multiple aggregates?

Viewed 304

I'm new to Domain Driven Desing and completely stucked with modelling problem. Here is a screenshot of design level event storming of simple feature with only one invariant: event storming Let's assume that eventual consistency is not allowed for certificate's condition and it is absolutely crucial to fulfill this condition immediately to process an order. In this case to check my certificate invariant I need an access to:

  • season of the order
  • supplier's country
  • season from which certificates are checked for specific country
  • supplier's certificates and if they are accepted and up to date

Initially I tried to split my application into multiple bounded contexts and for me those informations belong to different bounded contexts. Should I then have all these necassary data (list above) in one aggregate in order to ensure consistency and have its quite large or maybe there is any other solution? Maybe my whole reasoning is wrong and it doesn't make much sense? Maybe the bounded contexts boundaries are wrong due to necesity to reach for data to other contexts (not being autonomous)? Maybe domain service could be a solution? I would be really grateful for any help because I'm quite confused with those ddd topics :/

1 Answers

before answering your question I suggest you keep in mind the next statements:

  1. Consolidate your business invariants(rules) inside Aggregate.
  2. Design small and autonomous aggregates, if it is possible.
  3. Reference other Aggregates by using their id.
  4. Update other Aggregates using eventual consistency.

now let me share my opinion and give you advice (I've used C# syntax in below code snippets)

I recommend to you use 2 BC - Order and Supplier, and each of those is a good candidate for the individual aggregate. Certificate is not an aggregate and we have access to it via Supplier aggregate.

Preface: We have 2 services, - Order application service which injects repository interfaces to retrieve specific data. Also, we have an Order domain service where we're working with our aggregates.

Now if you want to check the certificate invariant, to do the next steps -

  • We should arrange all required data in the order application service by pulling data from repositories

  • Now it's time to validate (supplier's certificates and if they are accepted and up to date) certificate invariant.

  • Let's switch to the Order domain service to decide about order processing where we have the next method public void AddOrder(Order newOrder, Supplier supplier).

    • But let's start with adding the concrete business rule class like that
    public class SupplierCertificatesAreValidRule{ 
    public SupplierCertificatesAreValidRule(IList<Certificate> supplierCertificates){
    ...

    }
    
    public bool IsValid() {...}
    }
  • Get from the Supplier entity collection of its certificates.
  • Let's define the season of the order
  • Then get the supplier's country
  • Fetch the season from which certificates are checked for specific country
  • Add the Add method in the Order entity itself, where at beginning of this method we should call our business rule like that :
public static Order Add(Order newOrder, Supplier supplier){
CheckRule(new SupplierCertificatesAreValidRule(supplier.Certificates));
return new Order();
}
  • If the rule does not meet, then we should throw some business rule validation exception and explain the reason there.
  • If our rule is met, then it means that we can process our order
Related