Acing an LLD Interview

Dated Sep 10, 2026; last modified on Thu, 10 Sep 2026

Interviewing Rubric

Problem Analysis. Extract key entities and responsibilities, ask a few questions to lock down scope, and frame the problem before touching code.

Class Design. Choose the right responsibilities, shape the method signatures, define clear ownership, and keep the boundaries clean.

Code Quality. Encapsulation, well-managed state, sensible use of composition or inheritance, clear separation of concerns, naming, consistency, and dependency direction.

Extensibility and Maintainability. Can the design absorb new functionality without being rewritten? Designs should adapt easily, without anticipating every possible future.

Communication. Clear narrative, thoughtful reasoning, and ability to adjust when the interviewer probes.

Delivery Framework

Requirements (~5 min)

Go from “Design Tic Tac Toe” to a set of requirements, e.g.,

  • Two players alternate placing X and O on a \(3 \times 3\) grid.
  • A player wins by completing a row, column, or diagonal.
  • The game ends in a draw if all nine cells are filled with no winner.
  • Invalid moves, e.g., placing on an occupied cell, should be rejected.
  • The system should provide a way to query current game state and reset the game.
  • Out of scope: UI/rendering layer, AI opponent or move suggestions, networked multiplayer, variable board sizes, undo/redo functionality.

It helps to be familiar with the scenario you’re designing for. In 2019, my LiveRamp interview wanted me to design a bowling scorer. I had never been bowling, and found the scoring and turn logic rather arbitrary.

To come up with such requirements, ask:

  • What operations must this system support?
  • What conditions define success, failure, or system stoppage? What are the transitions?
  • How should the system respond to invalid inputs?
  • What areas are in scope and what areas are explicitly out of scope?

Entities and Relationships (~3 min)

Pull out meaningful nouns. If something maintains changing state or enforcing rules, it likely deserves to be its own entity. In the tic-tac-toe problem, the entities can be Game, Board, and Player.

With the entities locked down, think through their interactions, e.g., which entity orchestrates, which entities own durable state, what are their correspondences, where should specific rules logically live? For example, in tic-tac-toe, Game -> Board and Game -> Player (2x).

Class Design (~10-15 min)

Derive the state each entity needs to maintain to enforce the requirements, e.g., for Game in tic-tac-toe:

RequirementWhat Game must track
Two players alternate placing X and O on a \(3 \times 3\) grid.playerX: Player, playerO: Player, currentPlayer: Player, and the board: Board.
The game ends when a player wins or the board is full.gameState: GameState (IN_PROGRESS, WON, DRAW) and winner: Player?

Why can’t Board maintain currentPlayer? Given the initial Player, Board can compute whose turn it is given the current set of Xs and Os. However, some other component (Game) had to decide the initial Player, so why not have that component maintain currentPlayer?

Derive the behavior from the requirements. For each entity, which operations do we need to satisfy the requirements, e.g., for Game in tic-tac-toe:

Need from requirementsMethod on Game
Players need to make movesmakeMove(player, row, col) returns bool
Ask whose turn it isgetCurrentPlayer() returns Player
Check game stategetGameState() returns GameState
See who wongetWinner() returns Player?
Inspect the boardgetBoard() returns Board

Anchor on encapsulation: objects should manage their own state and expose behavior, not getters for callers to make decisions. “Can this operation run right now?” belongs in the orchestrator. Data-specific rules, e.g., is this cell already occupied, belong in the entity that owns that data.

A different perspective on the “Why can’t Board maintain currentPlayer?” thread from earlier.

UML was designed for an era when inspecting and running code was expensive. When thinking out loud and iterating, UML’s added formality slows you down without adding commensurate clarity.

I went an embarassingly long period of time in my career without knowing UML and sequence diagram. Only when I was a Senior SWE did I draw my first UML.

Implementation (~10min)

For each major (interviewer can guide you) method, start with the happy linear path. After that, handle edge cases, e.g., invalid inputs, invalid operations, etc. For instance, makeMove in tic-tac-toe:

class Game
{
  bool makeMove(Player player, int row, int col)
  {
    if (gameState != GameState.InProgress)
      return false;

    if (player != currentPlayer)
      return false;

    if (!board.canPlace(row, col))
      return false;

    board.placeMark(row, col, player.mark);

    if (board.checkWin(row, col, player.mark)):
    {
      gameState = GameState.Won;
      winner = player
    }
    else if (board.isFull())
    {
      gameState = GameState.Draw;
    }
    else
    {
      currentPlayer = (player == playerX) ? playerO : playerX;
    }

    return true;
  }
}

After implementing core methods, verify your logic by tracing through a simple but non-trivial scenario. This helps you catch logical errors before your interviewer finds them.

Extensibility (~5min)

The interviewer may was “what if we…” questions to prod whether the initial design can handle natural follow-ups without falling apart or turning into a pile of special cases. For example, what if we want to add undo functionality in tic-tac-toe? An answer might be adding a command history stack, where each successful action records the previous state before modifying anything; undo() pops the stack and reverts to that state.

chrome://downloads has an Undo method for reverting the deletion of downloads.

Whenever a user deletes downloads via chrome://downloads/, Chromium pushes those downloads to a removals_ list, hides them from chrome://downloads/, but doesn’t actually delete them from the file system. chrome://downloads/. On closing chrome://downloads/, ChromiumDownloadsDOMHandler’s destructor iterates through removals_ and actually deletes the files.

Chromium implements the Undo functionality by removing the IDs from the removals_ list, “revives” the downloads, and shows them in chrome://downloads/.

chrome://downloads/’s Undo ends up spilling into the implementation of RemoveDownloads, and the lifetime of the DownloadsDOMHandler object.

References

  1. Low Level Design in a Hurry | Hello Interview Low Level Design. www.hellointerview.com . Accessed Sep 10, 2026.
  2. Low Level Design Interview Delivery Framework | Hello Interview Low Level Design. www.hellointerview.com . Accessed Sep 10, 2026.
  3. downloads_dom_handler.cc - Chromium Code Search. source.chromium.org . Accessed Sep 10, 2026.