Software Design Process
A repeatable design process prevents panic in timed interviews and reduces rework in production.
Introduction
A repeatable design process prevents panic in timed interviews and reduces rework in production. Whether you have forty-five minutes or four days, the same phases apply: understand, model, validate, refine.
Experienced designers spend disproportionate time on requirements because wrong assumptions propagate into every class. Junior candidates often code mentally before agreeing on scope — then redraw when the interviewer adds 'support VIP parking.'
This lesson gives you a checklist that works for parking lots, payment wallets, and library catalogs alike.
Understanding the topic
Key concepts
- Requirements gathering: functional (what) vs non-functional (how well).
- Use-case identification: actors, triggers, preconditions, postconditions.
- Domain modeling: entities, value objects, aggregates, services.
- Behavior modeling: sequence and state diagrams for critical flows.
- Pattern selection: only after pain points appear (variation, creation complexity).
- Review: naming, SOLID violations, missing edge cases, test seams.
flowchart LRRequirements --> UseCasesUseCases --> ClassModelClassModel --> PatternsPatterns --> Code
Step-by-step explanation
- Restate the problem and list actors (user, admin, external payment).
- Capture 3–5 core use cases; defer nice-to-haves unless time remains.
- Extract nouns → candidate classes; verbs → methods; eliminate synonyms.
- Draw a class diagram with cardinalities and key fields.
- Walk the primary use case as a sequence diagram; fix gaps.
- Discuss extensions: concurrency, failure, new vehicle types, new payment modes.
Informative example
Design process output often starts as interfaces before concrete classes:
public sealed interface PaymentResult permits Success, Failure {record Success(String txnId) implements PaymentResult {}record Failure(String reason) implements PaymentResult {}}public interface PaymentProcessor {PaymentResult pay(Money amount, PaymentMethod method);}public final class DesignFirstWorkflow {private final PaymentProcessor processor;public DesignFirstWorkflow(PaymentProcessor processor) {this.processor = processor;}public PaymentResult checkout(Money total, PaymentMethod method) {if (total.isNegative()) {return new PaymentResult.Failure("invalid amount");}return processor.pay(total, method);}}
Sealed results make invalid states unrepresentable — interviewers appreciate explicit success/failure modeling early in the process.
Real-world use
Real-world applications
- Whiteboard LLD rounds at product companies.
- Sprint zero design for a new microservice module.
- RFC reviews before multi-team implementation.
Best practices
- Time-box each phase in interviews — do not perfect the class diagram.
- Write assumptions on the board (single location, synchronous API).
- Validate with 'what if' questions you ask yourself aloud.
- Keep a parking lot list for out-of-scope features.
- Prefer immutable value objects for IDs and money.
- Leave extension hooks at boundaries, not in core entities.
- End with a summary of classes and one sequence walkthrough.
Common mistakes
- Silent design — interviewers cannot grade what you do not verbalize.
- Equal depth on every class instead of focusing on core flow.
- No failure paths (network down, slot full, invalid card).
- Renaming classes mid-round without updating relationships.
Advanced interview questions
Q1BeginnerWhat is the first step in LLD?
Q2BeginnerWhy list use cases before classes?
Q3IntermediateHow many use cases should you cover in an interview?
Q4IntermediateWhen do you introduce design patterns?
Q5AdvancedHow do you handle changing requirements mid-interview?
Summary
Follow: requirements → use cases → classes → behavior → patterns → review. Verbalize assumptions and scope early. Depth on core flow beats breadth on peripheral features. Interfaces and sealed types clarify contracts in Java 21. Reserve time for extensions and trade-offs.