150 likes | 315 Views
Considerations for Effective Aggregate Design. Grappling with the nuances of the Aggregate Root Pattern. Agenda. Review of the Aggregate Pattern in DDD Coarse-grained Aggregate Designs Fine-grained Aggregate Designs Compound Entity and Value Object Graphs Working with Multiple Aggregates
E N D
Considerations for Effective Aggregate Design Grappling with the nuances of the Aggregate Root Pattern
Agenda • Review of the Aggregate Pattern in DDD • Coarse-grained Aggregate Designs • Fine-grained Aggregate Designs • Compound Entity and Value Object Graphs • Working with Multiple Aggregates • Experiences and Discussion
Aggregate Design Pattern “An Aggregate is a group of associated objects which are considered as one unit with regard to data changes. The Aggregate is demarcated by a boundary which separates the objects inside from those outside. Each Aggregate has one root. The root is an Entity, and it is the only object accessible from outside. The root can hold references to any of the aggregate objects, and the other objects can hold references to each other, but an outside object can hold references only to the root object. If there are other Entities inside the boundary, the identity of those entities is local, making sense only inside the aggregate.”
Aggregate Design Pattern “If objects of an Aggregate are stored in a database, only the root should be obtainable through queries. The other objects should be obtained through traversal associations. Objects inside an Aggregate should be allowed to hold references to roots of other Aggregates. The root Entity has global identity, and is responsible for maintaining the invariants. Internal Entities have local identity.”
Aggregate Design Pattern “Cluster the Entities and Value Objects into Aggregates and define boundaries around each. Choose one Entity to be the root of each Aggregate, and control all access to the objects inside the boundary through the root. Allow external objects to hold references to the root only. Transient references to internal members can be passed out for use within a single operation only. Because the root controls access, it cannot be blindsided by changes to the internals. This arrangement makes it practical to enforce all invariants for objects in the Aggregate and for the Aggregate as a whole in any state change.”
Goals of the Aggregate Pattern • Consistency Boundary • ‘Local consistency’ vs. system-wide • Enforce Invariants • Rules (“must be true”) • Increase the number of assumptions we can make about our system
Coarse-Grained Aggregates • Modeling the entire “real world” • Optimistic Concurrency Issues • Performance / Scaling Implications
Fine-Grained Aggregates • Model a smaller part of the world • Only a single Aggregate involved in a Transaction within each Bounded Context • Multi-Aggregate Consistency Solutions: • Redesign the model • Question Comprehension of Domain Knowledge • Consider Eventual Consistency
Compound Entities and Value Objects Aggregate Boundary • Prefer Value Objects to Entities • ‘Promote’ a Value Object to Entity only after careful consideration • More complexity • Persistence Challenges • Opportunities for Errors in code Entity1 Entity2 Entity3 ValueObject1 ValueObject2
Multiple Aggregate References Aggregate Boundary Aggregate Boundary Entity1 Entity1 Entity2 Entity2 Reference by ID ValueObject1 Entity3 Aggregate Boundary ValueObject1 Entity1 ValueObject2 Reference by ID ValueObject1 ValueObject3 ValueObject2 ValueObject4
Consistency of Multiple Aggregates • Aggregates only reference other Aggregates by their Root Entity • And even then, prefer a Value Object (representing a reference to the ID) rather than a reference to the Aggregate Root Entity itself • IMPORTANT: Referenced Aggregates do not enter the consistency boundary of the parent!
Loading Referenced Aggregates • Use the ID of the referenced Aggregate to load it as needed • Inject Repository into the Aggregate • Use external service to ‘look up’ the needed referenced Aggregates as required • Consider: both of these strategies are effectively ‘manual lazy-loading’ of referenced Aggregates • Consider: if only IDs are kept, references may be easily passed across bounded contexts and system boundaries • Much easier than attempting to pass actual objects/entities
Multi-Aggregate Consistency • Attempt ‘Cross-Aggregate’ consistency? • Eventual Consistency? • Domain Events • Pub-Sub Messaging Semantics • retry, resiliency, durability, compensating actions
Transaction/Consistency Guidance • If its the responsibility of the user executing the action on the Aggregate to ensure consistency, prefer the ‘Cross-Aggregate Transaction’ approach • If its the responsibility of the system to ensure consistency, prefer the eventual-consistency approach
Discussion • Viewpoints • Experiences • What Works? • What Doesn’t? • And Why?