Phase 1: Requirements & Use Cases
Interviewer: "Design a distributed lock service."
Candidate: "Let me confirm scope. We're designing the OOD model for a lock service that coordinates mutual exclusion across multiple processes or nodes — something like what ZooKeeper or Redis SETNX provides. The core concern is the class design: Lock, LockManager, client API, TTL handling. We are NOT designing the replication, consensus algorithm (Paxos/Raft), or network transport — those are distributed systems concerns. Does that match?"
Interviewer: "Yes. What use cases do you need to support?"
Candidate: "The core use cases are:
acquire(lockName, clientId, ttl)— attempt to acquire a named lock; block or return failure if already heldtryAcquire(lockName, clientId, ttl)— non-blocking acquire attempt; return immediately with success/failurerelease(lockName, clientId)— release a lock; only the holder can releaserenew(lockName, clientId, ttl)— extend the TTL of a held lock to prevent expiry during long operations- TTL-based auto-expiry — locks automatically expire after their TTL to handle crashed/partitioned clients
isLocked(lockName)— check if a lock is currently heldgetLockInfo(lockName)— return holder, acquisition time, TTL"Interviewer: "What happens when a client dies while holding a lock?"
Candidate: "That's why TTL is mandatory. Every lock has a maximum lifetime. If the holder crashes, the lock expires automatically after TTL elapses. The lock service needs a background thread (or lazy-expiry on each operation) that reaps expired locks. I'll design for lazy expiry on acquire/check operations plus an optional background sweeper."
WHY:…
In the full tutorial
- Phase 2: Object Modeling
- Phase 3: Class Design & Relationships
- Phase 4: Design Patterns Application
- Phase 5: Key Implementation
- Phase 6: Extensibility & Trade-offs