Command Execution System
Design a system that registers named commands and runs them on demand.
1, Each command performs some work and reports a result. Every time one runs, the system appends it to a history.
2, Also model every action as an object rather than a bare function call. The system can store the command in a list, log its name, and call it again later.
3, Each command knows how to apply its effect and how to roll it back. Because both live on the same object, the system can simply walk the history backward, ask each command to undo itself, and restore the earlier state step by step.
Interfaces
A Command contract, plus an executor that runs and tracks them:
class Command:
def execute(self): ... # do the work, return a result
def undo(self): ... # reverse the effect of execute()
def name(self): ... # identifier for history/logging
class CommandExecutor:
def register(self, name, command): ... # make a command runnable by name
def run(self, name, *args): ... # execute it, record it in history
def undo(self): ... # reverse the most recent command
def redo(self): ... # re-apply the most recently undone
def history(self): ... # ordered list of what has run
Operations
- register(name, command): bind a name to a command so it can be invoked.
- run(name, ...args): execute the named command, return its result, and append it to history.
- undo(): reverse the last executed command and return what was undone.
- redo(): re-execute the last undone command.
- history(): the commands that have run, in execution order.
Requirements
- Unknown command names fail clearly rather than silently doing nothing.
undoreverses commands in LIFO order — most recent first.- Running a new command after an undo clears the redo stack (no branching history).
- A command with no meaningful inverse may declare itself non-undoable; the system must reject undoing it instead of corrupting state.
- The design should extend to new command types without changing the executor.
Examples
ex = CommandExecutor()
ex.register("add", AddToBalance(account))
ex.run("add", 100) # balance 0 -> 100, history: [add]
ex.run("add", 50) # balance 100 -> 150, history: [add, add]
ex.undo() # balance 150 -> 100 (reverses the +50)
ex.undo() # balance 100 -> 0 (reverses the +100)
ex.redo() # balance 0 -> 100 (re-applies the +100)
Think about it
A command runs "set X to 9", and later you call undo — but the old value is already gone.
Follow-ups
How would you bundle several commands into one macro that undoes as a single unit?
If you persisted the history to a log, how would you replay it to rebuild state after a restart?
And more...
Databricks Crash Course
Fullset Newest Databricks Coding/System Design Questions, Optimal Solutions and Explanations.
Step_1 Matched with a FAANG+ Senior Engineer
Step_2 Fullset Databricks Coding/System Design Questions
Step_3 Solutions + step by step Explanation
