Bird
Raised Fist0

Requirements Gathering for LLD - What Questions to Ask the Interviewer

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
๐ŸŽฏ
Requirements Gathering for LLD - What Questions to Ask the Interviewer
40 min ยท medium
medium

Design a system to gather and clarify requirements for a Low-Level Design (LLD) interview question. The system must handle multiple levels of detail, various constraints, and evolving requirements. It should support capturing concrete facts, assumptions, and clarifications to guide the design process.

  • The system must support at least 5 levels of requirement granularity (e.g., high-level, mid-level, detailed).
  • It should allow capturing 4 distinct categories of questions: Functional, Non-Functional, Constraints, and Assumptions.
  • Each question must be tagged with priority and status (e.g., Pending, Answered, Clarified).
  • The system must support concurrent updates by multiple interviewers or interviewees.
  • It should maintain a history of changes for audit and rollback.
๐Ÿ“‹
Guided Steps
1/5
Step 1
Define Requirement Levels and Their Representation
How would you represent the multiple levels of requirement granularity in Java? What class or enum structures would you use?
๐Ÿ’ก Hint
Use enum for fixed levels to leverage Java's type safety and exhaustive switch checks.
Use enum RequirementLevel with fixed constants (HIGH_LEVEL, MID_LEVEL, DETAILED, LOW_LEVEL, VERY_DETAILED) - enums provide compile-time safety and prevent invalid values unlike Strings.
Mid: Defines enum for levels. Senior: Explains enum's ordinal and name methods for ordering and display, and how exhaustive switch on enums prevents bugs.
โš ๏ธCommon Wrong Answer
Using String constants for levels leads to runtime typos and no compile-time validation, causing bugs and poor IDE support.
Step 2
Modeling Questions with State and Behavior
How would you design the Question entity to hold state such as category, priority, and status? Should it be an interface or abstract class?
๐Ÿ’ก Hint
Java interfaces cannot hold instance fields; use abstract class if shared state is needed.
abstract class Question with fields category (enum), priority (int), status (enum), and synchronized methods to update status - abstract class needed for shared instance state; interface cannot hold fields in Java.
Mid: Chooses abstract class for shared fields. Senior: Explains why interface cannot hold instance state and how synchronized methods prevent race conditions on status updates.
โš ๏ธCommon Wrong Answer
Using interface for Question with default methods but no fields leads to duplicated state in subclasses and inconsistent status management.
Step 3
Concurrency Control for Concurrent Updates
How would you ensure thread-safe updates to question status and priority when multiple users edit concurrently?
๐Ÿ’ก Hint
Use synchronized methods or locks to atomically check and update fields.
Use synchronized boolean updateStatus(QuestionStatus newStatus) method in Question to atomically check current status and set new status, preventing lost updates due to race conditions.
Mid: Uses synchronized keyword on update methods. Senior: Traces thread interleaving where Thread 1 reads status PENDING, context switch, Thread 2 reads PENDING, both update causing inconsistent state; synchronized prevents this.
โš ๏ธCommon Wrong Answer
Not synchronizing status updates causes race conditions where multiple threads overwrite each other's changes leading to inconsistent question states.
Step 4
Capturing Question Categories and Statuses
How would you represent categories and statuses of questions to ensure type safety and extensibility?
๐Ÿ’ก Hint
Use enums for fixed sets of categories and statuses to leverage Java's compile-time checks.
Define enums QuestionCategory (FUNCTIONAL, NON_FUNCTIONAL, CONSTRAINTS, ASSUMPTIONS) and QuestionStatus (PENDING, ANSWERED, CLARIFIED) - enums prevent invalid values and support exhaustive switch statements.
Mid: Defines enums for categories and statuses. Senior: Explains how enums improve IDE support, enable switch-case exhaustiveness, and prevent runtime bugs from invalid strings.
โš ๏ธCommon Wrong Answer
Using Strings for categories/statuses leads to silent bugs from typos and no compile-time validation.
Step 5
Maintaining History and Audit Trail
How would you design the system to maintain a history of changes for each question, supporting rollback and audit?
๐Ÿ’ก Hint
Use composition to associate a list of immutable ChangeRecord objects with each Question.
Composition: Question has List<ChangeRecord> history; ChangeRecord is immutable with final fields timestamp, oldStatus, newStatus, changedBy. This ensures audit trail and rollback without exposing mutable state.
Mid: Uses composition to hold history. Senior: Explains immutability of ChangeRecord prevents concurrent modification bugs and how final fields guarantee thread-safe publication.
โš ๏ธCommon Wrong Answer
Using mutable ChangeRecord objects or exposing history list directly leads to inconsistent audit data and thread-safety issues.
๐Ÿ”Œ
API Design Challenge
Design an API for managing questions and their states in the requirements gathering system that supports concurrent updates, history tracking, and querying by level and category.
  • Consider thread-safe methods for updating question status and priority.
  • Provide endpoints or methods to retrieve questions filtered by RequirementLevel and QuestionCategory.
  • Design the API to allow rollback of question status to previous states using the history.
๐Ÿ“Š
Scoring Rubric
โ–ผ Show
Must Have - 60%
  • Use enums for fixed sets like RequirementLevel, QuestionCategory, QuestionStatus
  • abstract class Question with instance fields for shared state
  • Synchronized methods for atomic updates to mutable state
  • Composition for history tracking with immutable ChangeRecord
  • Explain concurrency issues with thread interleaving and how synchronized prevents them
Good to Have - 30%
  • Use volatile for singleton instance if applicable
  • Apply SOLID principles explicitly
  • Use final fields for immutability
  • Provide unmodifiable views for internal collections
Bonus - 10%
  • Explain Java memory model implications for concurrency
  • Discuss extensibility for adding new question categories or statuses
Using String constants for enums leads to runtime typos and no compile-time validation, causing silent bugs and poor IDE support.
Using interface instead of abstract class for entities with instance state causes duplicated state and inconsistent status management because interfaces cannot hold instance fields in Java.
Not synchronizing status updates causes race conditions where multiple threads overwrite each other's changes leading to inconsistent question states.
Using mutable ChangeRecord objects or exposing history list directly leads to inconsistent audit data and thread-safety issues due to concurrent modifications.
โœ…
Model Answer
โ–ผ Reveal

The system uses Java enums to represent fixed sets like requirement levels, question categories, and statuses to ensure type safety and prevent runtime errors. The Question entity is modeled as an abstract class holding shared mutable state with synchronized methods to ensure thread-safe updates. History tracking is implemented via composition with immutable ChangeRecord objects to maintain audit trails and support rollback. The design applies SOLID principles and concurrency best practices to ensure extensibility and correctness.

  • Use enums for all fixed sets to leverage compile-time safety and exhaustive switch-case checks.
  • Model Question as an abstract class to hold shared mutable state since interfaces cannot have instance fields.
  • Synchronize updateStatus method to prevent race conditions during concurrent updates.
  • Use composition to maintain a history list of immutable ChangeRecord objects for audit and rollback.
  • Use final fields in ChangeRecord to guarantee thread-safe publication and immutability.
  • Consider volatile keyword if implementing singleton pattern for requirements manager to avoid visibility issues.
  • Provide unmodifiable views or defensive copies for internal collections to maintain encapsulation and thread safety.
  • Use enum for RequirementLevel, QuestionCategory, and QuestionStatus to enforce type safety and prevent runtime bugs from invalid strings.
  • abstract class Question holds shared instance state (category, priority, status) because interfaces cannot hold fields in Java.
  • Synchronized methods in Question (e.g., synchronized boolean updateStatus(QuestionStatus newStatus)) ensure atomic check-and-set to prevent race conditions during concurrent updates.
  • Composition relationship: Question contains List<ChangeRecord> for history; ChangeRecord is immutable with final fields to guarantee thread safety and audit integrity.
  • Use volatile keyword for singleton instance if implementing a singleton pattern for the requirements manager to prevent partially constructed objects being visible to other threads.
  • Apply SOLID principles: Single Responsibility (Question handles question data and state), Open/Closed (enums allow adding new categories/statuses without modifying existing code), Liskov Substitution (abstract Question can be extended without breaking contracts).
  • Avoid exposing internal mutable collections directly; provide unmodifiable views or defensive copies to maintain encapsulation and thread safety.
  • Use final keyword for fields that should not change after construction to ensure thread-safe publication and immutability where applicable.

Practice

(1/5)
1. In the Meeting Scheduler system, a MeetingManager class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here, and why is this the correct choice for managing meeting schedules?
easy
A. Singleton pattern, to ensure only one instance manages all meeting schedules and avoids conflicting updates.
B. Factory pattern, because it creates different meeting types dynamically.
C. Builder pattern, to construct complex meeting objects step-by-step.
D. Prototype pattern, to clone existing meeting instances for recurring events.

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() ensures a single shared instance, matching Singleton pattern characteristics.
  2. Step 2: Reason why Singleton fits MeetingManager

    MeetingManager must coordinate all meetings centrally to avoid conflicting schedules; multiple instances could cause inconsistent state.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + synchronized getInstance() -> Singleton pattern [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
2. In the Social Media Profile System, the User class has a private constructor and a static synchronized getInstance() method to manage user sessions. Which design pattern is applied here and why is this the correct choice?
easy
A. Singleton Pattern, ensuring only one instance manages user sessions globally.
B. Factory Pattern, because it creates objects without exposing instantiation logic.
C. Builder Pattern, to construct complex User objects step-by-step.
D. Prototype Pattern, to clone existing User instances efficiently.

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method controls instance creation, which matches Singleton pattern characteristics.
  2. Step 2: Why Singleton fits user session management

    Singleton ensures a single global instance manages user sessions, avoiding multiple conflicting session managers.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + static synchronized getInstance() -> Singleton [check]
Hint: Private constructor + static getInstance() -> Singleton [check]
Common Mistakes:
3. Given a Vehicle abstraction that requires both state (e.g., speed) and behavior (e.g., accelerate()), should Vehicle be an abstract class or an interface in Java, and why?
easy
A. Vehicle should be an abstract class because interfaces cannot declare methods.
B. Vehicle should be an interface because interfaces can hold state and provide default implementations.
C. Vehicle should be an interface because abstract classes cannot have abstract methods.
D. Vehicle should be an abstract class because it can hold shared state and provide common behavior implementations.

Solution

  1. Step 1: Analyze state and behavior requirements

    Vehicle needs to hold state like speed and provide behavior like accelerate(), which requires shared fields and possibly implemented methods.
  2. Step 2: Choose between abstract class and interface

    Abstract classes can hold instance variables and provide method implementations, while interfaces (pre-Java 8) cannot hold state and only declare methods. Even with default methods, interfaces cannot hold mutable state.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    State + behavior -> abstract class fits better than interface [check]
Hint: State needs fields -> use abstract class, not interface [check]
Common Mistakes:
4. The framework currently applies a FeeStrategy interface for scoring rules. To add a WeekendBonusStrategy that modifies scoring only on weekends, what is the minimum change required to comply with SOLID principles?
medium
A. Modify the existing FeeStrategy implementations to check for weekends internally.
B. Create a combined strategy class that inherits from all existing strategies and adds weekend logic.
C. Add a boolean flag isWeekend to the base class and branch logic accordingly.
D. Add a new WeekendBonusStrategy class implementing FeeStrategy and configure it without changing existing classes.

Solution

  1. Step 1: Identify applicable SOLID principle

    The Open-Closed Principle (OCP) requires that existing classes remain unchanged when adding new functionality.
  2. Step 2: Evaluate options against OCP

    Add a new WeekendBonusStrategy class implementing FeeStrategy and configure it without changing existing classes. adds a new class implementing the interface, extending behavior without modifying existing code, thus respecting OCP.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    New class implements interface -> no existing class modified -> OCP [check]
Hint: Add new class, don't modify existing -> OCP compliance [check]
Common Mistakes:
5. To add a WeekendFeeStrategy for pricing in the current product catalog design, which change respects SOLID principles with minimum modification?
medium
A. Create a new WeekendFeeStrategy class implementing FeeStrategy interface without changing existing classes
B. Modify the existing FeeStrategy class to add weekend logic with if-else
C. Add weekend fee logic inside ProductVariant class directly
D. Add a boolean flag isWeekend in PricingEngine and handle fees there

Solution

  1. Step 1: Identify applicable SOLID principle

    The Open-Closed Principle (OCP) requires that classes be open for extension but closed for modification.
  2. Step 2: Why creating a new class is best

    Implementing a new WeekendFeeStrategy class extends functionality without modifying existing code, preserving OCP and avoiding side effects.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class -> OCP compliance, no existing class changes [check]
Hint: OCP: extend with new class, don't modify existing [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