Understanding Association, Aggregation, and Composition in Domain Modelling
Understanding Association, Aggregation, and Composition in Domain Modelling
When modeling your domain, not all relationships between classes are equal.
In Object-Oriented Design (OOD) and Domain-Driven Design (DDD), three core relationship types define how objects relate to each other: Association, Aggregation, and Composition.
These relationships go beyond mere “connections” — they express ownership, lifecycle, and dependency between entities.
Understanding the difference is critical for designing clean, maintainable software — and for making the right calls in your ORM (like Entity Framework or JPA) implementation.
Let’s unpack these three with examples from our GoProcure project 👇
1. Association — A Simple Link
Association is the most basic relationship between two classes. It simply means: “These two classes know about each other or interact in some way.”
There’s no ownership or lifecycle dependency implied.
In the GoProcure system, consider the relationship between Vendor and Item.
A Vendor supplies many Items, and each Item belongs to one Vendor.
But deleting a Vendor doesn’t necessarily delete the Items. In our business case, Item is an independent entity. If we terminate a vendor’s contract, it doesn’t mean the item/product is lost. We can simply pick another vendor next time as a preferred supplier for the item.
Here, both entities exist independently — this is a loose coupling.
In UML, we represent this as an arrow (—>) or solid line without diamonds.
💡 ORM Note:
In EF Core, this is typically configured with aHasOne().WithMany()relationship.
You can decide the cascade delete behavior depending on whether items should survive if the vendor is deleted.
2. Aggregation — “Has-A” but Independent Lifecycle
Aggregation expresses a “whole-part” relationship, but the parts can exist independently of the whole. This relationship suggests ownership without dependency.
In GoProcure, consider PurchaseRequest ↔ Approvals.
A PurchaseRequest may have multiple Approvals.
If the request is deleted, we may still keep the Approval records for audit or compliance — so the lifecycles are loosely connected.
In UML, Aggregation is represented with a hollow diamond (o—).
💡 Think of it like this:
APurchaseRequesthasApprovals, but those approvals can outlive the request itself.
Real-world analogy:
A University Department aggregates Professors.
If the department closes, professors don’t cease to exist — they can transfer elsewhere.
3. Composition — “Part-Of” and Dependent Lifecycle
Composition is the strongest form of relationship — it implies ownership and dependency. If the parent (whole) dies, all the children (parts) die with it.
In GoProcure, the classic example is PurchaseOrder ↔ PurchaseOrderLine.
A PurchaseOrderLine cannot exist without its PurchaseOrder.
If we delete the order, all its lines must be deleted as well.
In UML, Composition is represented with a filled diamond (◆).
💡 Think of it like this:
A Purchase Order owns its lines.
If you destroy the order, there’s no reason for its line items to exist.
Real-world analogy:
A House is composed of Rooms.
If the house is demolished, its rooms no longer exist.
Quick Comparison Table
| Concept | UML Symbol | Lifecycle Dependency | Ownership | Example (GoProcure) |
|---|---|---|---|---|
| Association | → or — | Independent | None | Vendor ↔ Item |
| Aggregation | o— | Part can outlive whole | Weak ownership | PurchaseRequest ↔ Approval |
| Composition | ◆ | Part dies with whole | Strong ownership | PurchaseOrder ↔ PurchaseOrderLine |
Implementation Tips (EF Core / JPA)
-
Use cascade delete only for composition relationships.
-
For aggregation, prefer manual cleanup or soft delete.
-
For association, configure relationship direction carefully — use
WithMany()only where needed. -
Avoid bidirectional relationships unless navigation both ways is truly required — they increase complexity and risk circular references. I will discuss how to handle bidirectional realtionship in another post.
Summary
-
Association → Entities interact, but no ownership.
-
Aggregation → “Has-A” relationship, weak ownership.
-
Composition → “Part-Of” relationship, strong ownership and shared lifecycle.
Understanding these distinctions ensures you:
-
Design cleaner class models
-
Avoid unintended cascading deletes
-
Communicate business intent clearly through your code
In the next article, we’ll begin implementing our domain models in code — applying these principles inside our .NET 8 GoProcure project, with equivalent notes for Java (JPA) developers.
Stay tuned — the engineering part starts to get exciting from here
