Episode 9 — System Design / 9.1 — LLD Foundations

9.1.d — UML Diagrams

In one sentence: UML (Unified Modeling Language) diagrams are the visual language of LLD — class diagrams show static structure (what exists), sequence diagrams show dynamic behavior (what happens over time), and knowing both is essential for communicating designs in interviews and teams.


Table of Contents


1. What Is UML?

UML (Unified Modeling Language) is a standardized visual language for describing software designs. It is NOT a programming language — it is a communication tool.

┌─────────────────────────────────────────────────────────┐
│                    UML DIAGRAM TYPES                    │
│                                                         │
│  STRUCTURAL (Static)          BEHAVIORAL (Dynamic)      │
│  ─────────────────            ────────────────────      │
│  • Class Diagram      ◄───   • Sequence Diagram  ◄──── │
│  • Object Diagram       │    • Activity Diagram    │   │
│  • Component Diagram    │    • State Diagram       │   │
│  • Package Diagram      │    • Use Case Diagram    │   │
│                         │                          │   │
│                   Most used              Most used      │
│                   in LLD                 in LLD         │
└─────────────────────────────────────────────────────────┘

For LLD interviews, you primarily need two diagram types:

  1. Class Diagrams — show the structure (classes, attributes, methods, relationships)
  2. Sequence Diagrams — show the flow (how objects interact over time for a specific scenario)

2. Class Diagrams

A class diagram shows the static structure of a system: what classes exist, what they contain, and how they relate.

2.1 Anatomy of a Class Box

Every class in a UML class diagram is drawn as a rectangle divided into three compartments:

┌─────────────────────────────┐
│         ClassName           │  ← 1. Class Name (bold, centered)
├─────────────────────────────┤
│ - privateField: Type        │  ← 2. Attributes (fields/properties)
│ # protectedField: Type      │
│ + publicField: Type         │
├─────────────────────────────┤
│ + publicMethod(): RetType   │  ← 3. Methods (operations)
│ - privateMethod(): void     │
│ # protectedMethod(): Type   │
└─────────────────────────────┘

Rules:

  • The class name goes in the top compartment. Abstract classes use italics or the label <<abstract>>.
  • Attributes go in the middle compartment with visibility, name, and type.
  • Methods go in the bottom compartment with visibility, name, parameters, and return type.

2.2 Visibility Modifiers

SymbolModifierMeaningWho Can Access
+publicOpen to allAny class
-privateHiddenOnly the class itself
#protectedFamily-onlyThe class and its subclasses
~packageNeighbors-onlyClasses in the same package/module

2.3 Attributes and Methods

Attribute notation:

visibility name: Type = defaultValue

Examples:

- id: string
- name: string = "Unknown"
- balance: number = 0
+ readonly email: string
- items: OrderItem[]

Method notation:

visibility name(param1: Type, param2: Type): ReturnType

Examples:

+ getName(): string
+ setName(name: string): void
- validateEmail(email: string): boolean
+ findById(id: string): User | null
+ processPayment(amount: number, currency: string): PaymentResult
# calculateDiscount(): number

Static members are shown with an underline:

┌───────────────────────────┐
│        Logger             │
├───────────────────────────┤
│ - instance: Logger        │  ← underlined = static
├───────────────────────────┤
│ + getInstance(): Logger   │  ← underlined = static
│ + log(msg: string): void  │
└───────────────────────────┘

Abstract classes and methods use italics or <<abstract>>:

┌───────────────────────────┐
│     <<abstract>>          │
│       Shape               │
├───────────────────────────┤
│ # color: string           │
├───────────────────────────┤
│ + area(): number          │  ← italic = abstract method
│ + perimeter(): number     │  ← italic = abstract method
│ + getColor(): string      │  ← regular = concrete method
└───────────────────────────┘

Interfaces use the <<interface>> stereotype:

┌───────────────────────────┐
│     <<interface>>         │
│      Serializable         │
├───────────────────────────┤
│                           │  ← no attributes (typically)
├───────────────────────────┤
│ + serialize(): string     │
│ + deserialize(s: string): │
│   void                    │
└───────────────────────────┘

2.4 Relationship Arrows

┌──────────────────────────────────────────────────────────────────┐
│                  UML RELATIONSHIP ARROWS                         │
│                                                                  │
│  Association:        A ──────────── B     (solid line)           │
│                                                                  │
│  Aggregation:        A ◇─────────── B     (hollow diamond at A) │
│                                                                  │
│  Composition:        A ◆─────────── B     (filled diamond at A) │
│                                                                  │
│  Dependency:         A ┄┄┄┄┄┄┄┄┄┄► B     (dashed arrow)        │
│                                                                  │
│  Inheritance:        B ─────────────▷ A   (solid + hollow tri)  │
│                       child          parent                      │
│                                                                  │
│  Implementation:     B ┄┄┄┄┄┄┄┄┄┄┄▷ A   (dashed + hollow tri) │
│                       class        interface                     │
│                                                                  │
│  Directed Assoc:     A ─────────────► B   (solid + open arrow)  │
│                       A knows B, not vice versa                  │
└──────────────────────────────────────────────────────────────────┘

Adding multiplicity to arrows:

  ┌──────────┐   1       *   ┌──────────┐
  │ Customer │───────────────│  Order   │
  └──────────┘               └──────────┘

  Read: "One Customer has many (*) Orders"
  Read: "Each Order belongs to one (1) Customer"

Adding role names:

  ┌──────────┐  manager  1    *  ┌──────────┐
  │ Employee │───────────────────│  Project  │
  └──────────┘   manages         └──────────┘

2.5 Complete Class Diagram Example

Scenario: Online Bookstore

                          ┌───────────────────┐
                          │   <<interface>>    │
                          │    Searchable      │
                          ├───────────────────┤
                          │ +search(q): Book[]│
                          └────────▲──────────┘
                                   ┆ implements
                                   ┆
┌─────────────────┐       ┌───────┴───────────┐       ┌──────────────────┐
│   <<abstract>>  │       │   BookCatalog     │       │     Author       │
│    BaseEntity   │       ├───────────────────┤       ├──────────────────┤
├─────────────────┤       │ - books: Book[]   │       │ - name: string   │
│ # id: string    │       ├───────────────────┤       │ - bio: string    │
│ # createdAt: Date       │ + addBook(b): void│       ├──────────────────┤
├─────────────────┤       │ + search(q): Book[]       │ + getName(): str │
│ # generateId()  │       │ + findByISBN(isbn)│       └────────┬─────────┘
│ + getId(): str  │       │   : Book | null   │                │
└────────▲────────┘       └───────────────────┘                │
         │ extends                ◆                             │
    ┌────┴────┐                   │ composition                │ 1
    │         │                   │ 1..*                        │
┌───┴──────┐ ┌┴──────────┐ ┌─────┴──────────┐                  │
│ Customer │ │   Order    │ │     Book       │──────────────────┘
├──────────┤ ├────────────┤ ├────────────────┤  association
│ - name   │ │ - total    │ │ - isbn: string │  (book knows author)
│ - email  │ │ - status   │ │ - title: string│
├──────────┤ ├────────────┤ │ - price: number│
│ +getEmail│ │ +addItem() │ │ - author: Author
│ +getName │ │ +getTotal()│ ├────────────────┤
└──────────┘ │ +checkout()│ │ +getTitle(): str
             └─────┬──────┘ │ +getPrice(): num
                   │        └────────────────┘
                   │ ◆ composition
                   │ 1..*
             ┌─────┴──────────┐
             │ OrderLineItem  │
             ├────────────────┤
             │ - book: Book   │
             │ - quantity: num│
             │ - unitPrice:num│
             ├────────────────┤
             │ +getSubtotal() │
             └────────────────┘

3. Sequence Diagrams

A sequence diagram shows how objects interact over time for a specific scenario or use case. It captures the dynamic behavior of the system.

3.1 Components of a Sequence Diagram

┌──────────────────────────────────────────────────────────────────┐
│              SEQUENCE DIAGRAM COMPONENTS                         │
│                                                                  │
│  ACTORS / OBJECTS:                                               │
│  ┌───────┐  ┌───────┐  ┌───────┐                                │
│  │ User  │  │ Server│  │  DB   │   ← boxes at the top           │
│  └───┬───┘  └───┬───┘  └───┬───┘                                │
│      │          │          │       ← LIFELINES (dashed vertical) │
│      │          │          │                                     │
│                                                                  │
│  MESSAGES:                                                       │
│  ──────────────►  Synchronous call (solid arrow)                │
│  ┄┄┄┄┄┄┄┄┄┄┄┄►  Asynchronous call (dashed arrow)              │
│  ◄─ ─ ─ ─ ─ ─   Return (dashed line, open arrow)              │
│                                                                  │
│  ACTIVATION BARS:                                                │
│  ┌──┐                                                            │
│  │  │  ← thin rectangle on lifeline = object is processing      │
│  └──┘                                                            │
│                                                                  │
│  TIME flows DOWNWARD ↓                                           │
└──────────────────────────────────────────────────────────────────┘

3.2 Message Types

ArrowTypeMeaningExample
──────►SynchronousCaller waits for responseAPI call, method invocation
┄┄┄┄┄►AsynchronousCaller does NOT waitEvent emission, queue message
◄─ ─ ─ ─ReturnResponse back to callerReturn value, HTTP response
──────► (to self)Self-callObject calls its own methodInternal validation

3.3 Activation Bars

Activation bars show when an object is actively processing a request:

  ┌──────┐          ┌──────┐
  │Client│          │Server│
  └──┬───┘          └──┬───┘
     │                 │
     │  request()      │
     │────────────────►│
     │                 ┌┴┐  ← activation starts (Server is processing)
     │                 │ │
     │                 │ │  (server does work here)
     │                 │ │
     │  response       │ │
     │◄─ ─ ─ ─ ─ ─ ─ ─┤ │
     │                 └┬┘  ← activation ends
     │                 │

3.4 Complete Sequence Diagram Example

Scenario: User places an order in an e-commerce system

  ┌──────┐    ┌────────────┐    ┌────────────┐    ┌──────────┐    ┌─────┐
  │ User │    │ Controller │    │OrderService│    │PaymentSvc│    │ DB  │
  └──┬───┘    └─────┬──────┘    └─────┬──────┘    └────┬─────┘    └──┬──┘
     │              │                 │                 │             │
     │ POST /orders │                 │                 │             │
     │─────────────►│                 │                 │             │
     │              │                 │                 │             │
     │              │ createOrder(dto)│                 │             │
     │              │────────────────►│                 │             │
     │              │                 │                 │             │
     │              │                 │ validate()      │             │
     │              │                 │───┐             │             │
     │              │                 │   │ (self-call) │             │
     │              │                 │◄──┘             │             │
     │              │                 │                 │             │
     │              │                 │ save(order)     │             │
     │              │                 │────────────────────────────►  │
     │              │                 │                 │             │
     │              │                 │        orderId  │             │
     │              │                 │◄─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│
     │              │                 │                 │             │
     │              │                 │ charge(amount)  │             │
     │              │                 │────────────────►│             │
     │              │                 │                 │             │
     │              │                 │                 │ save(txn)   │
     │              │                 │                 │────────────►│
     │              │                 │                 │    txnId    │
     │              │                 │                 │◄─ ─ ─ ─ ─ ─│
     │              │                 │                 │             │
     │              │                 │  PaymentResult  │             │
     │              │                 │◄─ ─ ─ ─ ─ ─ ─ ─│             │
     │              │                 │                 │             │
     │              │                 │ updateStatus()  │             │
     │              │                 │────────────────────────────►  │
     │              │                 │             ok  │             │
     │              │                 │◄─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│
     │              │                 │                 │             │
     │              │  OrderResponse  │                 │             │
     │              │◄─ ─ ─ ─ ─ ─ ─ ─│                 │             │
     │              │                 │                 │             │
     │ 201 Created  │                 │                 │             │
     │◄─ ─ ─ ─ ─ ─ │                 │                 │             │
     │              │                 │                 │             │

Reading this diagram:

  1. User sends a POST request to the Controller.
  2. Controller calls createOrder() on the OrderService.
  3. OrderService validates the order (self-call).
  4. OrderService saves the order to the DB and gets back an orderId.
  5. OrderService calls the PaymentService to charge the amount.
  6. PaymentService saves the transaction to the DB.
  7. PaymentService returns a PaymentResult.
  8. OrderService updates the order status in the DB.
  9. OrderService returns the OrderResponse to the Controller.
  10. Controller sends 201 Created to the User.

4. When to Use Each Diagram

DiagramShowsUse WhenInterview Usage
Class DiagramStatic structure — classes, attributes, methods, relationshipsYou need to show WHAT exists in the systemAlmost always — this is the primary LLD artifact
Sequence DiagramDynamic behavior — how objects interact for a specific flowYou need to show HOW a particular operation works step-by-stepWhen interviewer asks "walk me through the flow of X"

Decision Guide

┌────────────────────────────────────────────────────────────┐
│              WHICH DIAGRAM TO DRAW?                        │
│                                                            │
│  Interviewer asks:                     Draw:               │
│  ──────────────────                    ─────               │
│  "Design the classes for X"         → Class Diagram        │
│  "What classes and methods?"        → Class Diagram        │
│  "Show me the structure"            → Class Diagram        │
│                                                            │
│  "Walk me through the flow"         → Sequence Diagram     │
│  "What happens when a user does X?" → Sequence Diagram     │
│  "How do objects interact?"         → Sequence Diagram     │
│                                                            │
│  "Design a parking lot system"      → Class Diagram FIRST, │
│                                       then Sequence for    │
│                                       key flows            │
└────────────────────────────────────────────────────────────┘

5. How to Draw UML in Interviews

5.1 Whiteboard / Paper Tips

  1. Start with class boxes — draw them as simple rectangles with three sections. Do not worry about perfect alignment.
  2. Add attributes first — list the most important fields. Skip getters/setters unless specifically asked.
  3. Add key methods — focus on the 3–5 most important methods per class. Mark visibility with +/-/#.
  4. Draw relationships — use the correct arrows. Label with multiplicity (1, , 1..).
  5. Annotate — write relationship type names near the arrows if clarity helps.

5.2 Speed Tricks for 45-Minute Interviews

TrickHow
Abbreviate typesstr for string, num for number, bool for boolean
Skip obvious gettersDo not write getName() if you have - name: str — interviewer assumes it
Group related classesDraw them near each other on the board
Use consistent spacingLeave room between boxes for arrows
Draw sequence diagrams verticallyThey naturally flow top-to-bottom
Start simple, add detailBegin with 3–4 core classes, then expand

5.3 Common Interview Mistakes

MistakeWhy It HurtsFix
Drawing ALL classes at onceOverwhelming, hard to modifyStart with core entities, expand
No visibility modifiersShows lack of encapsulation awarenessAlways use +/-/#
Missing relationshipsDiagram is just isolated boxesConnect every class that interacts
Wrong diamond directionDiamond goes on the WHOLE sideMemorize: ◆ sits on the "owner"
Skipping multiplicityLoses important design informationAdd 1, , 1.. to every relationship
Too much detail on sequenceInterviewer loses trackFocus on the happy path first

5.4 Minimal Interview Class Diagram Template

┌──────────────┐      ┌──────────────┐
│   ClassA     │      │   ClassB     │
├──────────────┤      ├──────────────┤
│ - field: Type│      │ - field: Type│
├──────────────┤      ├──────────────┤
│ + method()   │      │ + method()   │
└──────┬───────┘      └──────┬───────┘
       │ 1                 * │
       │◆────────────────────│
       │    composition

6. More ASCII-Based Examples

6.1 Chat Application — Class Diagram

┌────────────────────┐
│   <<interface>>    │
│   MessageSender    │
├────────────────────┤
│ +send(msg): bool   │
└────────▲───────────┘
         ┆ implements
    ┌────┴────────┐
    │             │
┌───┴──────────┐ ┌┴───────────────┐
│ TextSender   │ │ MediaSender    │
├──────────────┤ ├────────────────┤
│ +send(): bool│ │ +send(): bool  │
│              │ │ +compress():   │
│              │ │   void         │
└──────────────┘ └────────────────┘

┌──────────────────┐  1    *  ┌──────────────────┐
│      User        │─────────│    ChatRoom      │
├──────────────────┤          ├──────────────────┤
│ - userId: str    │          │ - roomId: str    │
│ - username: str  │          │ - name: str      │
│ - status: Status │          │ - members: User[]│
├──────────────────┤          ├──────────────────┤
│ + sendMessage()  │          │ + addMember()    │
│ + joinRoom()     │          │ + removeMember() │
│ + leaveRoom()    │          │ + broadcast()    │
└──────────────────┘          └────────┬─────────┘
                                       │ ◆ 0..*
                              ┌────────┴─────────┐
                              │    Message       │
                              ├──────────────────┤
                              │ - msgId: str     │
                              │ - sender: User   │
                              │ - content: str   │
                              │ - timestamp: Date│
                              │ - type: MsgType  │
                              ├──────────────────┤
                              │ + getContent()   │
                              │ + getTimestamp()  │
                              └──────────────────┘

6.2 Login Flow — Sequence Diagram

  ┌──────┐    ┌────────────┐    ┌──────────┐    ┌──────┐    ┌────────┐
  │ User │    │  AuthCtrl   │    │ AuthSvc  │    │  DB  │    │  JWT   │
  └──┬───┘    └─────┬──────┘    └────┬─────┘    └──┬───┘    └───┬────┘
     │              │                │             │            │
     │ POST /login  │                │             │            │
     │ {email, pwd} │                │             │            │
     │─────────────►│                │             │            │
     │              │                │             │            │
     │              │ login(email,   │             │            │
     │              │   password)    │             │            │
     │              │───────────────►│             │            │
     │              │                │             │            │
     │              │                │ findByEmail │            │
     │              │                │────────────►│            │
     │              │                │             │            │
     │              │                │    user     │            │
     │              │                │◄─ ─ ─ ─ ─ ─│            │
     │              │                │             │            │
     │              │                │ verifyHash  │            │
     │              │                │──┐          │            │
     │              │                │  │          │            │
     │              │                │◄─┘          │            │
     │              │                │             │            │
     │              │                │         sign(payload)    │
     │              │                │─────────────────────────►│
     │              │                │                          │
     │              │                │            token         │
     │              │                │◄─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│
     │              │                │             │            │
     │              │  AuthResponse  │             │            │
     │              │  {token, user} │             │            │
     │              │◄─ ─ ─ ─ ─ ─ ─ │             │            │
     │              │                │             │            │
     │ 200 OK       │                │             │            │
     │ {token, user}│                │             │            │
     │◄─ ─ ─ ─ ─ ─ │                │             │            │
     │              │                │             │            │

6.3 ATM System — Class Diagram

┌──────────────────┐
│   <<abstract>>   │
│   Transaction    │
├──────────────────┤
│ # txnId: str     │
│ # amount: num    │
│ # timestamp: Date│
├──────────────────┤
│ + execute(): bool│ ← abstract
│ + getReceipt():  │
│   str            │
└────────▲─────────┘
         │ extends
    ┌────┼─────────────┐
    │    │             │
┌───┴────┴──┐  ┌──────┴──────┐  ┌───────────┐
│ Withdrawal│  │  Deposit    │  │ Transfer  │
├───────────┤  ├─────────────┤  ├───────────┤
│ +execute()│  │ +execute()  │  │ +execute()│
│ +getReceipt  │ +getReceipt()  │ +getReceipt
└───────────┘  └─────────────┘  │ -toAccount│
                                └───────────┘

┌──────────────┐  1    1  ┌──────────────┐
│   ATM        │─────────│  CardReader  │  composition
├──────────────┤          ├──────────────┤
│ - atmId: str │          │ +readCard()  │
│ - location   │          │ +ejectCard() │
├──────────────┤          └──────────────┘
│ +authenticate│
│ +selectTxn() │  1    1  ┌──────────────┐
│ +printReceipt│◆────────│ CashDispenser│  composition
└──────┬───────┘          ├──────────────┤
       │                  │ +dispense()  │
       │ ┄┄┄► uses        │ +getBalance()│
       │                  └──────────────┘
┌──────▼───────┐
│   Account    │
├──────────────┤
│ - accNum: str│  1    *  ┌──────────────┐
│ - balance:num│◇────────│ Transaction  │  aggregation
│ - pin: str   │          └──────────────┘
├──────────────┤
│ +getBalance()│
│ +debit()     │
│ +credit()    │
│ +verifyPin() │
└──────────────┘

7. Key Takeaways

  1. Class diagrams show WHAT exists — classes, their attributes, methods, and relationships. They are the primary LLD artifact.
  2. Sequence diagrams show HOW things happen — the step-by-step interaction between objects for a specific scenario.
  3. Visibility matters — always use + (public), - (private), # (protected) in your class boxes.
  4. Relationship arrows have distinct meanings — solid line (association), hollow diamond (aggregation), filled diamond (composition), dashed arrow (dependency), triangle (inheritance/implementation).
  5. Multiplicity (1, , 1..) communicates how many instances relate and should be on every relationship line.
  6. In interviews, start simple — draw 3-4 core classes first, then expand. Do not try to draw the perfect diagram on the first attempt.
  7. Sequence diagrams flow downward — time progresses from top to bottom. Activation bars show when an object is processing.
  8. You do not need formal UML tools in interviews — ASCII diagrams, whiteboard sketches, or even verbal descriptions of the structure are perfectly acceptable.

Explain-It Challenge

Draw a class diagram and a sequence diagram for a simple Vending Machine. The class diagram should have at least 4 classes (VendingMachine, Product, Inventory, Coin). The sequence diagram should show the flow of a user inserting coins and selecting a product. Try it on paper before looking at any reference.


Previous → 9.1.c — Class Relationships Next → 9.1.e — LLD Interview Approach