Overview
Step 4: connect the entities. For each pair, decide the relationship type (association, aggregation, composition, inheritance, implementation, dependency), its direction (who references whom), and multiplicity (1, 0..1, *). Draw a quick class diagram with the key methods and interfaces.
Direction matters: bidirectional references are harder to keep consistent, so prefer one-way navigation where possible (Show has ShowSeats; ShowSeat does not need to point back). Across aggregates or large boundaries, reference by ID instead of object. Interfaces mark the variation points where patterns will plug in.
Some links are ownership (a parent's child in a family tree), some are acquaintances (contacts), and some are shared (members of a club). You also decide who keeps whose phone number.
When to use it
- After assigning responsibilities.
- Before writing code in an LLD interview.
- Reviewing coupling in an existing design.
Where it shows up in interviews
Recognize it when: 'draw the class diagram'.
- Design a movie ticket system
- Design a parking lot
- Design a library system
Where it is used in real software
Standard notation for relationships and multiplicities.
@OneToMany, @ManyToOne, and cascade settings mirror relationship decisions.
DDD recommends references by ID across aggregates to limit coupling.
Key terms
- Navigability
- Direction you can traverse the relationship.
- Multiplicity
- How many instances participate.
- Composition
- Owned parts with shared lifecycle.
- Reference by ID
- Store an identifier instead of an object reference.
How it works, step by step
- 1Pick pairs from use cases
Show-Screen, Show-ShowSeat, Booking-Show.
- 2Choose the type
Composition if lifecycle is owned.
- 3Choose direction
One-way unless both sides truly need to navigate.
- 4Set multiplicity
Show 1 -- * ShowSeat.
- 5Mark interfaces
PricingStrategy, PaymentGateway, Notifier.
Relationships in the movie ticket system
Chosen types and directions
| From | To | Type | Multiplicity / notes |
|---|---|---|---|
| Cinema | Screen | Composition | 1 to * |
| Screen | Seat | Composition | 1 to * |
| Show | Movie, Screen | Association | * to 1 each |
| Show | ShowSeat | Composition | 1 to * (created per show) |
| Booking | Show | Reference by ID | * to 1 |
| BookingService | PricingStrategy, PaymentGateway | Dependency on interfaces | Injected |
NOWFrom: Cinema | To: Screen | Type: Composition | Multiplicity / notes: 1 to *
Booking stores showId rather than a Show reference, keeping aggregates independent.
Implementation
classDiagram Cinema "1" *-- "*" Screen Screen "1" *-- "*" Seat Show "*" --> "1" Movie Show "*" --> "1" Screen Show "1" *-- "*" ShowSeat ShowSeat --> Seat Booking ..> Show : showId BookingService --> PricingStrategy BookingService --> PaymentGateway PricingStrategy <|.. WeekendPricing PaymentGateway <|.. StripeGatewayComplexity and performance
Keep the diagram readable.
Iterate while coding.
Trade-offs
References are convenient to navigate; IDs decouple aggregates and ease persistence.
Two-way links simplify queries but require keeping both sides in sync.
Variants and related techniques
Resolve IDs through repositories instead of holding object graphs.
A relationship with its own data (Enrollment between Student and Course).
Common mistakes
- Everything referencing everything.
Fix: One-way navigation and IDs across boundaries.
- Inheritance where composition fits.
Fix: Use is-a only for true subtypes.
Interview questions
Why reference by ID instead of object?
It decouples aggregates, avoids loading huge object graphs, keeps each aggregate's consistency boundary clear, and maps naturally to persistence.
When is a relationship composition?
When the part is created by and cannot exist without the whole, like ShowSeats for a Show or Seats in a Screen, so deleting the whole deletes the parts.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Relationships for a food delivery system | Easy | Multiplicities. |
| Relationships for a hotel booking system | Medium | IDs vs references. |