Skip to main content

Documentation Index

Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

UML (Unified Modeling Language) diagrams help visualize system design. In LLD interviews, you’ll mainly use Class Diagrams and Sequence Diagrams. Think of UML as the architectural drawings of software. Just as a building architect sketches floor plans before laying bricks, you sketch class diagrams before writing code. The goal is not to create museum-quality diagrams β€” it is to communicate your design clearly and quickly. In a 45-minute interview, a well-drawn class diagram can replace 10 minutes of verbal explanation and immediately signal that you think structurally about code.

Class Diagrams

Class diagrams show the static structure of a system.

Basic Notation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          <<interface>>          β”‚  ◄── Stereotype
β”‚           Flyable               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                 β”‚  ◄── Attributes (empty for interface)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + fly(): void                   β”‚  ◄── Methods
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             Bird                β”‚  ◄── Class Name
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ - name: String                  β”‚  ◄── Private attribute
β”‚ # age: int                      β”‚  ◄── Protected attribute  
β”‚ + species: String               β”‚  ◄── Public attribute
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + fly(): void                   β”‚  ◄── Public method
β”‚ - sleep(): void                 β”‚  ◄── Private method
β”‚ # eat(food: Food): void         β”‚  ◄── Protected method
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Visibility Symbols

SymbolMeaningAccess
+PublicEverywhere
-PrivateSame class only
#ProtectedSame class + subclasses
~PackageSame package

Relationships

1. INHERITANCE (is-a)
   ────────────────────────▷
   (Empty triangle arrow pointing to parent)
   
   Example: Dog ────────▷ Animal
   Dog IS AN Animal

2. IMPLEMENTATION (realizes)
   - - - - - - - - - - - -β–·
   (Dashed line with empty triangle)
   
   Example: Bird - - - - β–· Flyable
   Bird IMPLEMENTS Flyable

3. ASSOCIATION (knows-about)
   ─────────────────────────
   (Simple line)
   
   Example: Teacher ───── Student
   Teacher KNOWS Student

4. AGGREGATION (has-a, weak)
   ◇─────────────────────────
   (Empty diamond at container)
   
   Example: Team ◇───── Player
   Team HAS Players (players can exist without team)

5. COMPOSITION (has-a, strong)
   ◆─────────────────────────
   (Filled diamond at container)
   
   Example: House ◆───── Room
   House HAS Rooms (rooms don't exist without house)

6. DEPENDENCY (uses)
   - - - - - - - - - - - - ->
   (Dashed arrow)
   
   Example: Order - - - -> PaymentService
   Order USES PaymentService

Multiplicity

1       Exactly one
0..1    Zero or one
*       Zero or more
1..*    One or more
n       Exactly n
n..m    Between n and m

Complete Example: E-commerce System

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      <<interface>>       β”‚
β”‚     PaymentMethod        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + pay(amount): bool      β”‚
β”‚ + refund(id): bool       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β–³
            β”‚
            β”‚ implements
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
    β”‚               β”‚
β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CreditCard   β”‚  β”‚    PayPal     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ - cardNumber  β”‚  β”‚ - email       β”‚
β”‚ - cvv         β”‚  β”‚ - password    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + pay()       β”‚  β”‚ + pay()       β”‚
β”‚ + refund()    β”‚  β”‚ + refund()    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Customer     β”‚         β”‚       Order       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€         β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ - id: UUID        β”‚    1    β”‚ - id: UUID        β”‚
β”‚ - name: String    │◆────────│ - status: Status  β”‚
β”‚ - email: String   β”‚    *    β”‚ - createdAt: Date β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€         β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ + placeOrder()    β”‚         β”‚ + calculateTotal()β”‚
β”‚ + getOrders()     β”‚         β”‚ + cancel()        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β”‚ 1..*
                                        β—†
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚     OrderItem     β”‚
                              β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                              β”‚ - quantity: int   β”‚
                              β”‚ - price: Decimal  β”‚
                              β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                              β”‚ + getSubtotal()   β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β”‚ *..1
                                        β”‚
                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                              β”‚      Product      β”‚
                              β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                              β”‚ - id: UUID        β”‚
                              β”‚ - name: String    β”‚
                              β”‚ - price: Decimal  β”‚
                              β”‚ - stock: int      β”‚
                              β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
                              β”‚ + reserve()       β”‚
                              β”‚ + release()       β”‚
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Sequence Diagrams

Sequence diagrams show how objects interact over time.

Basic Elements

β”Œβ”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”
β”‚Clientβ”‚          β”‚Serverβ”‚          β”‚  DB  β”‚
β””β”€β”€β”¬β”€β”€β”€β”˜          β””β”€β”€β”¬β”€β”€β”€β”˜          β””β”€β”€β”¬β”€β”€β”€β”˜
   β”‚                 β”‚                 β”‚
   β”‚  1. request()   β”‚                 β”‚
   │────────────────>β”‚                 β”‚
   β”‚                 β”‚  2. query()     β”‚
   β”‚                 │────────────────>β”‚
   β”‚                 β”‚                 β”‚
   β”‚                 β”‚  3. result      β”‚
   β”‚                 β”‚<- - - - - - - - β”‚
   β”‚  4. response    β”‚                 β”‚
   β”‚<- - - - - - - - β”‚                 β”‚
   β”‚                 β”‚                 β”‚

Legend:
─────────────>  Synchronous call
- - - - - - ->  Return/Response
═════════════>  Async message
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Activation  β”‚  (box on lifeline = processing)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Complete Example: Order Checkout

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  User  β”‚   β”‚   Cart    β”‚   β”‚  Checkout  β”‚   β”‚ Payment β”‚   β”‚ Inventory β”‚
β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚ checkout()   β”‚                β”‚              β”‚              β”‚
    │─────────────>β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚ createOrder()  β”‚              β”‚              β”‚
    β”‚              │───────────────>β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚ reserveItems()              β”‚
    β”‚              β”‚                │─────────────────────────────>
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚   reserved   β”‚
    β”‚              β”‚                β”‚<- - - - - - - - - - - - - - β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚  orderCreated  β”‚              β”‚              β”‚
    β”‚              β”‚<- - - - - - - -β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚ enterPayment β”‚                β”‚              β”‚              β”‚
    β”‚<- - - - - - -β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚ paymentInfo  β”‚                β”‚              β”‚              β”‚
    │─────────────>β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚ processPayment()              β”‚              β”‚
    β”‚              │───────────────────────────────>              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚ charge()     β”‚
    β”‚              β”‚                β”‚              │─────────────>β”‚
    β”‚              β”‚                β”‚              β”‚   (external) β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚   success    β”‚              β”‚
    β”‚              β”‚<- - - - - - - - - - - - - - - β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚ confirmOrder() β”‚              β”‚              β”‚
    β”‚              │───────────────>β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚ commitInventory()           β”‚
    β”‚              β”‚                │─────────────────────────────>
    β”‚              β”‚                β”‚              β”‚              β”‚
    β”‚  confirmationβ”‚                β”‚              β”‚              β”‚
    β”‚<- - - - - - -β”‚                β”‚              β”‚              β”‚
    β”‚              β”‚                β”‚              β”‚              β”‚

Alt/Opt/Loop Fragments

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  alt  [payment successful]                      β”‚
β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚       β”‚  confirmOrder()                         β”‚
β”‚       β”‚  sendConfirmationEmail()                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚       β”‚ [payment failed]                        β”‚
β”‚       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚       β”‚  releaseInventory()                     β”‚
β”‚       β”‚  showError()                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  opt  [user is premium]                         β”‚
β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚       β”‚  applyPremiumDiscount()                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  loop [for each item in cart]                   β”‚
β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚       β”‚  validateStock(item)                    β”‚
β”‚       β”‚  calculatePrice(item)                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use Case Diagram (Bonus)

For understanding system scope:
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚      E-commerce System          β”‚
                    β”‚                                 β”‚
   β”Œβ”€β”€β”€β”€β”€β”          β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
   β”‚     β”‚          β”‚    β”‚  Browse Products β”‚         β”‚
   β”‚ Userβ”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€>β”‚                 β”‚         β”‚
   β”‚     β”‚          β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
   β””β”€β”€β”¬β”€β”€β”˜          β”‚                                 β”‚
      β”‚             β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
      β”‚             β”‚    β”‚   Add to Cart   β”‚         β”‚
      └─────────────┼───>β”‚                 β”‚         β”‚
                    β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
                    β”‚             β”‚                   β”‚
                    β”‚             β”‚ <<include>>       β”‚
                    β”‚             β–Ό                   β”‚
   β”Œβ”€β”€β”€β”€β”€β”          β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
   β”‚     β”‚          β”‚    β”‚    Checkout     β”‚         β”‚
   β”‚Adminβ”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€>β”‚                 β”‚         β”‚
   β”‚     β”‚          β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
   β””β”€β”€β”€β”€β”€β”˜          β”‚             β”‚                   β”‚
                    β”‚             β”‚ <<extend>>        β”‚
                    β”‚             β–Ό                   β”‚
                    β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
                    β”‚    β”‚  Apply Coupon   β”‚         β”‚
                    β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Interview Tips

Begin with 3-4 core classes and their relationships. Add details as you discuss with the interviewer. The strongest candidates draw the skeleton first (class names and arrows), then progressively add attributes and methods as the conversation unfolds. This mirrors how experienced architects work β€” broad strokes before fine details.
Explain your thought process as you draw. Say things like β€œI am making this a composition because a Room cannot exist without a Hotel” or β€œThis is aggregation because a Player can exist independently of a Team.” This shows your reasoning skills and demonstrates that every arrow on your diagram is a deliberate design decision, not decoration.
Know the difference between composition (filled diamond) and aggregation (empty diamond). Interviewers notice! Composition means the contained object’s lifecycle is tied to the container (Order contains OrderItems β€” delete the order, delete the items). Aggregation means the contained object can exist independently (Team has Players β€” dissolve the team, players still exist). Getting this right signals you understand ownership semantics.
You don’t need every getter/setter. Focus on key attributes and methods that reveal your design decisions. Include the method signatures that show polymorphism, the attributes that drive business logic, and the relationships that embody your design patterns. Skip boilerplate β€” interviewers can infer constructors and simple accessors.
Always annotate relationships with multiplicity (1, 0.., 1..). Saying β€œa Customer has many Orders” is vague β€” does β€œmany” include zero? Writing β€œ1..” (at least one) vs β€œ0..” (possibly none) communicates precision that separates senior-level thinking from hand-waving.
Practice Tip: Draw diagrams for common systems (Parking Lot, Library, etc.) until the notation becomes second nature.

Interview Questions

Strong Answer:
  • Hotel to Room is composition (filled diamond on the Hotel side). A Room cannot exist independently of a Hotel. If the Hotel is destroyed (deleted from the system), its Rooms have no meaning. The Hotel controls the Room lifecycle. Multiplicity is 1 on Hotel, 1..* on Room (a hotel must have at least one room).
  • Hotel to Guest is association (simple line). A Guest interacts with a Hotel but has an independent lifecycle. The Guest existed before booking and continues to exist after checkout. Multiplicity is 0..* on both sides (a hotel has many guests over time, a guest can visit many hotels).
  • Guest to Room is NOT a direct relationship. Instead, there is a Booking (or Reservation) class that connects them. Booking to Guest is association (1 Guest per booking, a Guest has 0..* bookings). Booking to Room is also association (1..* Rooms per booking, a Room has 0..* bookings over time).
  • The Booking class is critical because it carries its own data: check-in date, check-out date, status, payment reference. Without it, you cannot model the temporal aspect (a room is available some dates but not others). This is the β€œassociation class” pattern in UML β€” when the relationship itself has attributes.
Red flag answer: β€œRoom is aggregation because rooms can exist without a hotel” (misunderstands lifecycle dependency) or drawing a direct line from Guest to Room without a Booking class (misses temporal data and many-to-many resolution).Follow-ups:
  1. The interviewer says β€œwhat if a Room can be transferred to a different Hotel during a renovation?” Does this change your relationship from composition to aggregation, and what are the implications for your code?
  2. How would you represent a RoomType (Standard, Deluxe, Suite) in the diagram β€” as an enum attribute on Room, a separate class, or an inheritance hierarchy?
Strong Answer:
  • An association means one class knows about another and holds a reference to it, typically as an instance variable. The relationship is long-lived β€” the reference persists for the lifetime of the object. For example, an Order has a customer: Customer field. The Order always knows which Customer placed it.
  • A dependency means one class uses another temporarily, usually as a method parameter, local variable, or return type. The relationship is transient β€” it exists only during a method call. For example, an Order’s generateInvoice() method might take an InvoicePrinter as a parameter. Order does not hold a reference to InvoicePrinter; it only uses it momentarily.
  • The practical importance: associations create tighter coupling than dependencies. If Customer changes its interface, Order is affected because it holds a persistent reference. If InvoicePrinter changes, Order is only affected if generateInvoice() is called. This distinction matters for understanding change propagation and testability.
  • In your diagram, use solid lines (association) for β€œthis class has a field of that type.” Use dashed arrows (dependency) for β€œthis class receives that type as a parameter or creates it locally.” Getting this right shows you understand coupling strength, not just β€œthings are connected.”
Red flag answer: β€œThey are basically the same thing, just use a solid line for everything” or confusing dependency with inheritance (dashed line with triangle vs dashed arrow).Follow-ups:
  1. In the e-commerce diagram, CheckoutService depends on PaymentProcessor but does not have an association. Why is that a deliberate design choice, and how does it relate to Dependency Inversion?
  2. Can a dependency become an association over time as requirements evolve? Give an example of when you would promote a dependency to an association.
Strong Answer:
  • A chain of 7 synchronous calls creates a fragile pipeline. If any single call in the chain fails or is slow, the entire operation hangs or fails. The total latency is the sum of all 7 calls. The error handling is complex because a failure at step 5 might require rolling back steps 1 through 4. This is the β€œdistributed monolith” anti-pattern hiding behind an object-oriented design.
  • The first fix is to identify which calls MUST be synchronous (they depend on the previous result) and which can be async (they are notifications or side effects). In a checkout flow: validating inventory and processing payment must be synchronous (you need the result before proceeding). But sending confirmation email, updating analytics, and notifying the warehouse can be asynchronous.
  • I would redraw the sequence diagram splitting it into two phases: a synchronous critical path (validate stock, reserve inventory, charge payment, confirm order β€” 4 calls) and an async fan-out (email, analytics, warehouse notification β€” 3 calls via a message queue or event bus). The async calls use the Observer pattern or pub/sub.
  • On the diagram, I would show the async messages with double-lined arrows or annotate them with <<async>>. I would also add an alt fragment around the payment call to show the failure path: if payment fails, release inventory and return error. This makes the failure handling explicit in the diagram.
Red flag answer: β€œ7 calls is fine, that is just how the flow works” (no concern for latency or failure) or β€œMake everything async” (losing transactional guarantees on the critical path).Follow-ups:
  1. In the async fan-out, what happens if the email service is down? The order is confirmed but the customer never gets the confirmation email. How do you handle this and how would it show on the diagram?
  2. How would you represent a retry mechanism with exponential backoff on the sequence diagram?
Strong Answer:
  • For SRP violations: classes with many unrelated methods. If an Order class box has methods for processPayment(), sendEmail(), generatePDF(), and updateInventory() alongside calculateTotal(), that is visible multi-responsibility. Also watch for class names ending in β€œManager,” β€œHandler,” or β€œUtils” β€” they are magnets for unrelated behavior.
  • For OCP violations: missing abstraction layers. If CheckoutService has a direct association arrow to StripePayment (a concrete class) instead of to a PaymentGateway interface, adding PayPal requires modifying CheckoutService. The visual signal is solid arrows pointing to concrete classes rather than to interfaces (boxes with <<interface>> stereotype).
  • For LSP violations: inheritance arrows where the child class likely cannot honor the parent’s contract. If ReadOnlyFile inherits from File which has write() in its method list, that is a visible LSP smell. Also watch for deep hierarchies (4+ levels) β€” the deeper the hierarchy, the more likely LSP violations lurk.
  • For ISP violations: interfaces with many methods where some implementors stub them out. If an <<interface>> IWorker has 5 methods and Robot implements it, and you know robots cannot eat or sleep, those empty implementations are ISP violations. The visual signal is a fat interface box with many methods.
  • For DIP violations: high-level classes with association arrows pointing directly to low-level concrete classes. If OrderService points to MySQLDatabase rather than to a Database interface, that is DIP on the diagram.
Red flag answer: β€œYou cannot detect design problems from a diagram” (dismissive) or only mentioning one or two principles while ignoring the others.Follow-ups:
  1. Can you always detect design problems from a class diagram alone? What kinds of problems require a sequence diagram or code inspection to find?
  2. If you see a class implementing 6 interfaces, is that a design smell or a sign of good ISP compliance? How do you tell the difference?
Strong Answer:
  • <<include>> means the base use case ALWAYS incorporates the included use case. It is mandatory. β€œCheckout” always includes β€œValidate Payment.” Every time checkout runs, payment validation runs. Think of it as a function call that always happens.
  • <<extend>> means the extending use case SOMETIMES augments the base use case, under certain conditions. β€œApply Coupon” extends β€œCheckout” β€” it only happens if the user has a coupon. It is conditional and optional. The base use case is complete without it.
  • Candidates get this wrong because the arrows point in counterintuitive directions. In <<include>>, the arrow goes FROM the base use case TO the included one (Checkout β€”includeβ€”> Validate Payment). In <<extend>>, the arrow goes FROM the extension TO the base (Apply Coupon β€”extendβ€”> Checkout). The extension β€œoffers itself” to the base, which is backwards from how most people think about optional behavior.
  • The practical test: if removing the relationship would make the base use case incomplete or broken, it is <<include>>. If removing it would just mean a feature is missing but the base still works, it is <<extend>>.
Red flag answer: Swapping the two definitions (saying include is optional and extend is mandatory) or not knowing which direction the arrows point.Follow-ups:
  1. In practice, how useful are Use Case Diagrams in LLD interviews compared to Class and Sequence Diagrams? When would you proactively draw one versus waiting for the interviewer to ask?
  2. Can you have an <<extend>> that extends another <<extend>>? If so, give an example. If not, why not?
Strong Answer:
  • First 60 seconds: identify the core nouns from the problem statement. Parking Lot, Floor, Parking Spot, Vehicle, Ticket, and Payment. These become my class candidates. I write them as boxes on the board without any details β€” just names.
  • Next 60 seconds: draw the relationships. ParkingLot to Floor is composition (floors do not exist without the lot), Floor to ParkingSpot is composition (spots do not exist without the floor), ParkingSpot to Vehicle is association (a spot may or may not have a vehicle), Ticket ties together a Vehicle and a ParkingSpot with timestamps. I add multiplicity: 1 ParkingLot, 1..* Floors, n ParkingSpotsPerFloor, 0..1 Vehicle per spot.
  • Next 60 seconds: add the key attributes and methods that reveal design decisions. ParkingSpot gets a type (compact, regular, large) and an isAvailable() method. Vehicle gets a type (motorcycle, car, bus) that determines which spot it can use. Ticket gets entryTime and exitTime for billing.
  • Next 60 seconds: add the abstraction layer. Vehicle becomes an abstract class or interface with Motorcycle, Car, Bus subclasses. ParkingSpot might also be abstract with CompactSpot, RegularSpot, LargeSpot subclasses, or simply use a type enum β€” I would ask the interviewer which they prefer and explain the trade-off.
  • Final 60 seconds: add the Strategy pattern for payment (CashPayment, CardPayment) and a Singleton annotation on ParkingLot if appropriate. Review the diagram for any missing relationships.
Red flag answer: Starting with detailed attributes and methods before establishing the class structure and relationships (bottom-up instead of top-down), or spending 4 minutes on a single class and running out of time.Follow-ups:
  1. You drew ParkingSpot with subtypes CompactSpot, RegularSpot, LargeSpot. The interviewer says β€œa bus takes up 5 regular spots.” How does your diagram handle this, and does it change the relationship between Vehicle and ParkingSpot?
  2. How would you add an entry/exit gate system to the diagram? What relationship does it have with Ticket and ParkingLot?
Strong Answer:
  • The colleague raises a legitimate point, and in most real e-commerce systems, they are right β€” it should be aggregation, not composition. Here is why: in a real business, an Order has legal and financial significance beyond the Customer. Tax records, audit trails, and fulfillment obligations require the Order to persist even if the Customer deletes their account. GDPR might require anonymizing the Customer data, but the Order itself (amounts, dates, items) must be retained for accounting.
  • However, the β€œcorrect” answer depends on the domain requirements. If your system is a simple MVP where deleting a customer cascades to their orders (no legal or financial obligations), composition is appropriate. If it is a production e-commerce platform with regulatory requirements, aggregation is correct.
  • This is exactly the kind of design discussion interviewers want to hear. The best answer is not β€œcomposition” or β€œaggregation” β€” it is β€œhere is the question I would ask the interviewer to decide: what happens to orders when a customer is deleted?” This shows you understand that UML relationships encode business rules, not just structural preferences.
  • In database terms, composition maps to ON DELETE CASCADE. Aggregation maps to ON DELETE SET NULL or a soft-delete pattern. The diagram choice directly affects your schema design, and getting it wrong in production means either orphaned records or illegally deleted financial records.
Red flag answer: β€œIt is composition because Customer owns Orders” (does not consider the business implications) or β€œIt does not matter, it is just a diagram” (misses that the diagram drives implementation decisions).Follow-ups:
  1. If you change this to aggregation, how do you handle the display of β€œCustomer’s Order History” when the Customer object still exists? Does the Order need a customer_id field, a direct reference, or both?
  2. How does the composition vs aggregation choice affect your API design? If a client sends DELETE /customers/123, what should happen to their orders in each case?
Strong Answer:
  • 0..* means the collection can be empty. 1..* means there must be at least one element at all times. The difference is an invariant β€” code that assumes at least one element will crash or behave incorrectly if the collection is empty.
  • Real example: Order to OrderItem. If you mark this as 0..*, your system allows an Order with zero items. Downstream code that calls order.items[0] to get the first item for display, or sum(item.price for item in order.items) for the total, will either crash with an IndexError or silently return 0 β€” which might trigger a β€œfree order” bug. Marking it 1..* means the Order class must enforce this invariant in its constructor or add_item() method, and reject orders with no items.
  • Another real case: a User to Addresses with 1..* means the system requires at least one address on file. But during onboarding, the user has not entered an address yet. If your system insists on 1..* from day one, the registration flow breaks. The correct multiplicity might be 0..* on the User-Address association but 1..* on the Order-ShippingAddress association (you need an address to ship, but not to create an account).
  • In code, 1..* should be enforced. In Python, the constructor checks if len(items) == 0: raise ValueError("Order must have at least one item"). In Java, you might use a non-empty collection type. The multiplicity on the diagram is a specification that drives validation logic.
Red flag answer: β€œI just use * for everything, the code handles it” (no precision, no invariant enforcement) or β€œIt is just documentation, it does not affect code” (misses the design-to-implementation link).Follow-ups:
  1. How do you enforce 1..* in a database schema? What constraint would you add, and why is it harder to enforce than it sounds?
  2. In the e-commerce diagram, Product has stock: int. What multiplicity would you put on the association between Product and OrderItem, and what happens at the boundary when stock reaches zero?

Interview Deep-Dive

Strong Answer:
  • The distinction is lifecycle ownership. Composition (filled diamond) means the contained object’s lifecycle is entirely controlled by the container. If the container is destroyed, the contained objects are destroyed with it. Aggregation (open diamond) means the contained objects have independent lifecycles and can exist without the container.
  • For example, in an e-commerce system: Order and OrderItem are composition. If you delete an order, its line items have no meaning on their own. But Team and Player are aggregation β€” if a team is dissolved, the players still exist and can join other teams.
  • In my diagram, I chose composition here because [specific to the relationship] the contained object has no identity or purpose outside the container. It cannot be shared across multiple containers, and creating it independently would be a design error.
  • A practical test I use: β€œCan I meaningfully create this object without the container existing first?” If the answer is no, it is composition. If yes, it is aggregation.
Follow-up: Does this distinction affect your code, or is it just a diagram convention?It absolutely affects code. Composition typically means the container creates the contained object in its constructor and does not expose it for external sharing. Aggregation means the contained object is passed in (dependency injection) and the container holds a reference but does not own the lifecycle. In Python, composition often means the container’s init creates the objects; aggregation means init receives them as parameters. This also affects garbage collection, serialization (do you cascade-delete?), and database schema design (embedded documents vs. foreign keys).
Strong Answer:
  • I use a sequence diagram when the interviewer asks about a specific interaction flow, like β€œwalk me through the checkout process” or β€œwhat happens when a user books a seat.” Sequence diagrams show temporal ordering and message passing between objects, which class diagrams cannot express.
  • The key elements I always include: lifelines (vertical dashed lines) for each participating object, synchronous call arrows (solid lines with filled arrowheads) for method invocations, return arrows (dashed lines) for responses, and activation boxes (rectangles on the lifeline) to show when an object is actively processing.
  • I also use alt/opt/loop fragments when relevant. Alt shows branching (payment succeeds vs. fails). Opt shows conditional behavior (apply coupon if present). Loop shows iteration (validate each item in cart).
  • What I skip: I do not draw every getter call or logging statement. I focus on the meaningful interactions that show the design’s flow of control and the responsibilities of each object.
Follow-up: How do you use the sequence diagram to identify design problems?Long chains of synchronous calls (A calls B calls C calls D calls E) suggest tight coupling and fragility. If one object is receiving messages from many different sources, it might be a God class accumulating too many responsibilities. If two objects are ping-ponging messages back and forth excessively, it suggests they should be merged or their responsibilities redistributed. I also look for missing return arrows, which can indicate fire-and-forget calls that should probably be async (Observer pattern) rather than synchronous.
Strong Answer:
  • For SRP violations, I look at class names ending in β€œManager,” β€œHandler,” or β€œUtils,” and at classes with many unrelated methods. If an Order class has methods for payment processing, email sending, and PDF generation alongside order management, that is a multi-responsibility class.
  • For OCP violations, I look for missing abstractions. If the diagram shows a concrete PaymentProcessor with no interface above it and a direct dependency from CheckoutService, adding a new payment method will require modifying PaymentProcessor.
  • For LSP violations, I look at inheritance hierarchies where a child class is likely to break the parent’s contract. If ReadOnlyFile inherits from File which has a write() method, that is a classic LSP violation visible on the diagram.
  • For ISP violations, I look at interfaces with many methods and implementing classes that only use a subset. If an IWorker interface has work(), eat(), and sleep() methods but Robot implements IWorker, that fat interface is visible on the diagram.
  • For DIP violations, I look at dependency arrows pointing from high-level classes directly to concrete low-level classes rather than to interfaces. If OrderService has an arrow directly to MySQLDatabase rather than to a Database interface, that is a DIP violation.
  • Multiplicity also reveals design issues. If every relationship is β€œ1 to *” with no upper bound, that might indicate unbounded collections that cause performance problems.
Follow-up: Can you always detect design problems from a class diagram alone?No. Class diagrams show static structure, not runtime behavior. You cannot detect concurrency issues, performance bottlenecks, or incorrect state transitions from a class diagram alone. You also cannot tell whether a method implementation violates LSP just from the signature. The diagram is a starting point for asking good questions β€” β€œI see ReadOnlyFile inherits from File. Does the write() contract get honored?” β€” but verification requires looking at the code or drawing a sequence diagram.