Bird
Raised Fist0

Requirements Gathering for LLD - What Questions to Ask the Interviewer

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/3
User and Request inheritance and composition

User is an abstract class holding shared state userId and name, which Request extends adding request-specific fields. Request composes SystemConfig to access configuration.

🎯 Tests whether candidate knows abstract class is needed because User holds instance state (userId, name) which interfaces cannot hold in Java. Also tests understanding of composition lifecycle ownership between Request and SystemConfig.
public abstract class User {
    protected String userId;
    protected String name;
    public String getUserId() { return userId; }
    public String getName() { return name; }
}
public class Request extends User {
    private String requestId;
    private String details;
    private final SystemConfig config; // composition
    public Request(SystemConfig config) {
        this.config = config;
    }
    public String getRequestId() { return requestId; }
    public String getDetails() { return details; }
}
SystemConfig Singleton with volatile instance

SystemConfig is a singleton class with a private volatile static instance and a public static getInstance() method implementing double-checked locking.

🎯 Tests whether candidate knows volatile is required on singleton instance to prevent JVM reordering and partially constructed object visibility in multithreaded access.
public class SystemConfig {
    private static volatile SystemConfig instance;
    private Map<String, String> configMap;
    private SystemConfig() {
        configMap = new HashMap<>();
    }
    public static SystemConfig getInstance() {
        if (instance == null) {
            synchronized(SystemConfig.class) {
                if (instance == null) {
                    instance = new SystemConfig();
                }
            }
        }
        return instance;
    }
    public String getConfig(String key) {
        return configMap.get(key);
    }
}
PricingPolicy interface and AuditLog association

PricingPolicy is an interface defining calculateFee(), realized by concrete classes (not shown). AuditLog is associated with Request and has synchronized logAction() to ensure thread-safe logging.

🎯 Tests whether candidate understands interface is used here for OCP to allow multiple pricing strategies without modifying existing code. Also tests synchronized method usage to prevent race conditions in AuditLog.
public interface PricingPolicy {
    double calculateFee(Request request);
}
public class AuditLog {
    public synchronized void logAction(String action) {
        // thread-safe logging implementation
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       | <<Abstract>>   |
       |    User        |
       +----------------+
       | -userId: String|
       | -name: String  |
       +----------------+
       | +getUserId():  |
       |   String       |
       | +getName():    |
       |   String       |
       +----------------+
              │
              │
       +----------------+
       | Request        |
       +----------------+
       | -requestId:    |
       |   String       |
       | -details: String|
       +----------------+
       | +getRequestId():|
       |   String       |
       | +getDetails(): |
       |   String       |
       +----------------+
              │
              │ composition
              │
       +----------------+
       | SystemConfig   |
       +----------------+
       | -configMap:    |
       |   Map<String,  |
       |   String>      |
       +----------------+
       | +getInstance():|
       |   SystemConfig |
       | +getConfig(key):|
       |   String       |
       +----------------+
              │
              │ association
              │
       +----------------+
       | PricingPolicy  |
       +----------------+
       | +calculateFee():|
       |   double       |
       +----------------+
              │
              │ association
              │
       +----------------+
       | AuditLog       |
       +----------------+
       | +logAction():  |
       |   void [sync]  |
       +----------------+

This class diagram illustrates four key classes in the requirements gathering system. User is an abstract class holding shared state such as userId and name, which Request extends adding request-specific data. Request composes SystemConfig, a singleton class implemented with a volatile instance and double-checked locking to ensure thread-safe lazy initialization. PricingPolicy is an interface representing the strategy pattern for fee calculation, enabling open-closed principle compliance by allowing new policies without modifying existing code. AuditLog is associated with Request and uses a synchronized method to guarantee thread-safe logging. These design decisions emphasize Java-specific mechanisms like volatile for singleton safety, abstract classes for shared state, interface for behavior abstraction, and synchronized for concurrency control.

Primary Focus

✓ Abstract class state vs interface + Composition lifecycle + Singleton volatile + Realization

Practice

(1/5)
1. In designing a Vehicle abstraction, should it be an abstract class or an interface if it needs to hold common state like speed and fuelLevel? Why?
easy
A. Use an interface, because interfaces can hold state and provide default implementations.
B. Use an abstract class, because it can hold instance variables and provide shared behavior.
C. Use an interface, because it enforces implementation without sharing any code or state.
D. Use an abstract class, because interfaces cannot declare methods.

Solution

  1. Step 1: Analyze state and behavior requirements

    Since Vehicle needs to hold common state like speed and fuelLevel, it requires instance variables.
  2. Step 2: Choose abstraction supporting state

    Abstract classes can have instance variables and shared method implementations, whereas interfaces cannot hold instance state (only constants and default methods without state).
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    State requires instance variables -> abstract class [check]
Hint: State needs fields -> abstract class; interfaces only declare behavior [check]
Common Mistakes:
2. In a Java system, a Subject class maintains a list of Observer interfaces and notifies them on state changes. Which design pattern is this an example of, and why is it the correct choice for decoupling components?
easy
A. Observer pattern, because it allows subjects to notify multiple observers without knowing their concrete classes.
B. Mediator pattern, because it centralizes communication between objects to reduce dependencies.
C. Decorator pattern, because it dynamically adds responsibilities to objects without affecting others.
D. Strategy pattern, because it encapsulates interchangeable algorithms for flexible behavior.

Solution

  1. Step 1: Identify the pattern based on roles

    The Subject maintains a list of Observer interfaces and notifies them on state changes, which matches the Observer pattern's intent to decouple the subject from its observers.
  2. Step 2: Eliminate other patterns

    Mediator centralizes communication but does not involve a subject notifying observers; Decorator adds behavior dynamically but does not handle notification; Strategy encapsulates algorithms but does not manage dependent objects.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Subject notifying observers without knowing concrete classes -> Observer pattern [check]
Hint: Subject notifies observers, decoupling sender and receivers [check]
Common Mistakes:
3. The brokerage system currently calculates fees using a FeeCalculator class. To add a new WeekendFeeStrategy without modifying existing code, which SOLID principle applies and what is the minimum change required?
medium
A. Open/Closed Principle: Create a new WeekendFeeStrategy class implementing FeeStrategy interface; FeeCalculator uses polymorphism.
B. Single Responsibility Principle: Modify FeeCalculator to handle weekend fees explicitly.
C. Dependency Inversion Principle: Inject concrete WeekendFeeStrategy directly into FeeCalculator constructor.
D. Liskov Substitution Principle: Replace FeeCalculator with WeekendFeeCalculator subclass overriding fee logic.

Solution

  1. Step 1: Identify the SOLID principle for extensibility

    Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: How to apply OCP here

    Create a new class WeekendFeeStrategy implementing FeeStrategy interface; FeeCalculator uses polymorphism to apply different strategies without modification.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class + polymorphism -> OCP compliance [check]
Hint: Add new fee strategy class, no FeeCalculator changes [check]
Common Mistakes:
4. In a vending machine using the State pattern, if the method selectItem() is not synchronized, which exact thread interleaving causes dispensing the same item twice?
medium
A. Thread 1 checks item availability -> true, context switch, Thread 2 checks availability -> true, both dispense item
B. Thread 1 and Thread 2 both wait on a lock, causing deadlock
C. Thread 1 updates inventory, Thread 2 reads old inventory before update
D. Thread 1 calls selectItem(), Thread 2 calls cancel(), both proceed concurrently

Solution

  1. Step 1: Identify the check-then-act race

    Without synchronization, both threads can read item availability as true before either decrements inventory.
  2. Step 2: Trace the interleaving

    Thread 1 checks availability -> true, context switch; Thread 2 checks availability -> true; both proceed to dispense, causing double dispense.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Unsynchronized check-then-act -> double dispense [check]
Hint: Check-then-act without sync -> double dispense race [check]
Common Mistakes:
5. ElectricCar vehicles require ChargingSpots in the parking module. What is the minimum change to the current Java design to support this without modifying existing classes?
hard
A. Create a new ElectricCar class and a ChargingSpot class, then modify ParkingLot to handle both types explicitly.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility.COMPATIBILITY_MAP.
C. Modify Vehicle class to include a boolean isElectric field and add logic in existing parking methods.
D. Add a new interface Chargeable and make ElectricCar implement it, modifying existing Vehicle and Spot classes.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Minimal change means no modification to existing classes; adding new enums or modifying compatibility map violates this.
  2. Step 2: Use composition or flags to extend behavior

    Adding an isElectric boolean field to Vehicle and handling charging logic externally avoids class explosion and preserves OCP.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Flag in Vehicle + external logic -> minimal change, no class modification [check]
Hint: Add flag + external logic -> minimal change, no class edits [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard