Reputation: 56
I'm delving into Domain-Driven Design (DDD) and encountered a scenario that seems like a typical challenge. It revolves around creating domain objects, such as Aggregates, that depend on IDs which are only available after an object has been persisted to the database.
Consider this example: We have a feature to add a passenger to a booking. The business logic and rules for this action are encapsulated within the Booking aggregate. However, the Booking aggregate's passenger list requires each passenger to have an ID. The catch is, a passenger should not be created in the database unless they meet the specific rules set by the Booking aggregate. Also from my understanding we want to persist the aggregate as whole than parts of the aggregate separately.
What's the best approach to handle such common situations in DDD, where the creation of one aggregate depends on the ID of another, yet both need to adhere to certain business rules and validations?
Thanks in advance for your insights!
From my side, I've tried using a union type for objects requiring an ID, which offers some flexibility. However, it's not ideal, as it adds extra checks and type assertions in many cases where an ID is typically expected. Also in the past I tried to assign random UUID when non exist, but some database providers don't allow you to assign an Id, so I also didn't like that solution.
Upvotes: 1
Views: 544
Reputation: 711
Before getting into details, I must note that DDD is not about implementation details, it's about tackling complexity by focusing on the domain knowledge rather than implementation details. Domain model pattern helps it to separate these details from the domain model and lets you concentrate on core business logic.
About your question, first, let's look at the aggregate design. Is it valid to have passenger and booking in the same aggregate? You can design it to have both of them. Otherwise, you should consider eventual consistency approaches.
For eventual consistency, if the case is simple, it can be achieved by an integration event. You can set the dependent entities' IDs after persisting them by publishing an event.
But if it's complex (like the need for compensation actions), consider using the Saga pattern (a booking would be a request that passes some states in a long-running process).
For database design issues, loosen the relationship with other aggregates by removing foreign key constraints or making the FK nullable. Another way is to use client-generated IDs like you just said, it solves most of the problems.
Upvotes: 0