Bird
Raised Fist0
LLDsystem_design~25 mins

Program to interface not implementation in LLD - System Design Exercise

Choose your learning style10 modes available
Design: Interface-based Modular System
Focus on designing the architecture and interaction patterns that enforce programming to interfaces. Implementation details of specific components are out of scope.
Functional Requirements
FR1: Design a system where components interact only through defined interfaces, not concrete implementations
FR2: Allow easy replacement or upgrade of components without affecting others
FR3: Support multiple implementations of the same interface
FR4: Ensure components are loosely coupled and highly maintainable
Non-Functional Requirements
NFR1: System should handle up to 1000 concurrent component interactions
NFR2: Response time for component communication should be under 100ms
NFR3: System availability target is 99.9% uptime
NFR4: Design must be language-agnostic and support future technology changes
Think Before You Design
Questions to Ask
❓ Question 1
❓ Question 2
❓ Question 3
❓ Question 4
❓ Question 5
Key Components
Interface definitions or contracts
Component implementations
Dependency injection or service locator
Interface registries or repositories
Communication protocols between components
Design Patterns
Dependency Injection
Service Locator
Adapter Pattern
Facade Pattern
Strategy Pattern
Reference Architecture
  +-------------------+       +-------------------+       +-------------------+
  |   Component A     |       |   Component B     |       |   Component C     |
  |  (implements IA)  |       |  (implements IB)  |       |  (implements IA)  |
  +---------+---------+       +---------+---------+       +---------+---------+
            |                           |                           |
            |                           |                           |
            |                           |                           |
            |                           |                           |
  +---------v---------------------------v---------------------------v---------+
  |                          Interface Registry / Injector                      |
  |  - Holds interface definitions and implementations                         |
  |  - Provides components with interface references                           |
  +-----------------------------------------------------------------------------+
Components
Interface Definitions
IDL (Interface Definition Language) or abstract classes
Define contracts that components must follow without specifying implementation
Component Implementations
Any programming language or module
Concrete classes or modules that implement the interfaces
Interface Registry / Injector
Dependency Injection framework or service locator pattern
Manages interface implementations and injects them into components at runtime
Communication Layer
In-process calls, RPC, or messaging depending on deployment
Facilitates interaction between components via interfaces
Request Flow
1. 1. Component requests an interface reference from the Interface Registry.
2. 2. Interface Registry returns a reference to a concrete implementation of the requested interface.
3. 3. Component interacts with the implementation only through the interface methods.
4. 4. If a new implementation is deployed, Interface Registry updates the reference without changing the component.
5. 5. Components remain unaware of the concrete classes, relying solely on interface contracts.
Database Schema
Not applicable as this design focuses on interface-based component interaction rather than data storage.
Scaling Discussion
Bottlenecks
Interface Registry becoming a single point of failure or performance bottleneck
Complexity in managing multiple interface versions and backward compatibility
Overhead of dependency injection in large-scale systems
Difficulty in debugging due to abstraction layers
Solutions
Distribute Interface Registry or use caching to reduce load and increase availability
Implement versioning strategies and interface evolution policies
Optimize dependency injection with compile-time injection or lightweight containers
Use logging, tracing, and monitoring tools to improve observability
Interview Tips
Time: Spend 10 minutes understanding and clarifying requirements, 20 minutes designing the interface-based architecture, and 15 minutes discussing scaling and trade-offs.
Explain the importance of programming to interfaces for loose coupling and flexibility
Describe how dependency injection or service locator patterns help manage implementations
Discuss how multiple implementations can coexist and be swapped without affecting clients
Highlight how this design supports maintainability and scalability
Mention potential challenges and how to mitigate them

Practice

(1/5)
1. What is the main benefit of programming to an interface rather than a concrete implementation?
easy
A. It allows changing the implementation without affecting the code that uses it.
B. It makes the program run faster by using direct calls.
C. It reduces the number of lines of code needed.
D. It forces the use of only one implementation.

Solution

  1. Step 1: Understand interface vs implementation

    Programming to an interface means using a contract that defines what methods are available, not how they work internally.
  2. Step 2: Identify the benefit of this approach

    This allows swapping or changing the underlying implementation without changing the code that depends on the interface.
  3. Final Answer:

    It allows changing the implementation without affecting the code that uses it. -> Option A
  4. Quick Check:

    Interface abstraction = flexibility [OK]
Hint: Interfaces hide details, so implementations can change freely [OK]
Common Mistakes:
  • Thinking it improves speed directly
  • Believing it reduces code size automatically
  • Assuming only one implementation is allowed
2. Which of the following code snippets correctly shows programming to an interface in a language like Java?
easy
A. List<String> list = new ArrayList<>();
B. ArrayList<String> list = new ArrayList<>();
C. List<String> list = new List<>();
D. ArrayList<String> list = new List<>();

Solution

  1. Step 1: Identify interface and implementation

    In Java, List is an interface, and ArrayList is a concrete class implementing List.
  2. Step 2: Check which declaration uses interface type

    Declaring the variable as List and instantiating with ArrayList means programming to interface, not implementation.
  3. Final Answer:

    List<String> list = new ArrayList<>(); -> Option A
  4. Quick Check:

    Variable type = interface [OK]
Hint: Use interface type on left side, implementation on right [OK]
Common Mistakes:
  • Using concrete class on both sides
  • Trying to instantiate an interface directly
  • Mixing types incorrectly
3. Given the following code in a language supporting interfaces:
interface Vehicle { void drive(); }
class Car implements Vehicle { public void drive() { print("Car driving"); } }
class Bike implements Vehicle { public void drive() { print("Bike driving"); } }
Vehicle v = new Car();
v.drive();

What will be the output?
medium
A. Compilation error
B. Bike driving
C. Car driving
D. Vehicle driving

Solution

  1. Step 1: Identify the object type assigned to interface variable

    The variable v of type Vehicle is assigned a new Car object.
  2. Step 2: Determine which drive() method runs

    Calling v.drive() runs the Car's drive() method because the actual object is Car.
  3. Final Answer:

    Car driving -> Option C
  4. Quick Check:

    Interface variable calls actual object's method [OK]
Hint: Interface calls use actual object's method at runtime [OK]
Common Mistakes:
  • Assuming interface method runs
  • Confusing object type with variable type
  • Expecting compilation error due to interface
4. Consider this code snippet:
interface Printer { void print(); }
class LaserPrinter implements Printer { void print() { System.out.println("Laser printing"); } }
Printer p = new LaserPrinter();
p.print();

Why does this code cause a compilation error?
medium
A. Interfaces cannot be instantiated.
B. LaserPrinter does not implement print() method.
C. Printer cannot be used as a variable type.
D. The print() method in LaserPrinter is not declared public.

Solution

  1. Step 1: Check method visibility in implementation

    Interface methods are public by default, so implementing methods must be public.
  2. Step 2: Identify method declaration in LaserPrinter

    LaserPrinter's print() method lacks the public modifier, causing a visibility mismatch error.
  3. Final Answer:

    The print() method in LaserPrinter is not declared public. -> Option D
  4. Quick Check:

    Interface methods require public implementation [OK]
Hint: Implement interface methods as public to avoid errors [OK]
Common Mistakes:
  • Thinking interfaces can't be variable types
  • Believing missing method causes error instead
  • Ignoring method visibility rules
5. You are designing a payment system where multiple payment methods (CreditCard, PayPal, Crypto) can be used. To follow the principle 'Program to interface not implementation', which design is best?
hard
A. Write separate classes with no common interface and call their methods directly.
B. Create a PaymentMethod interface with a pay() method, and implement it in each payment class.
C. Use a single PaymentProcessor class with if-else to handle all payment types.
D. Make all payment classes inherit from a concrete PaymentProcessor class.

Solution

  1. Step 1: Identify the need for abstraction

    Multiple payment types require a common contract to allow flexible usage.
  2. Step 2: Choose design that uses interface

    Defining a PaymentMethod interface with pay() method lets each payment type implement its own logic while code depends only on the interface.
  3. Final Answer:

    Create a PaymentMethod interface with a pay() method, and implement it in each payment class. -> Option B
  4. Quick Check:

    Interface abstraction enables flexible, extendable design [OK]
Hint: Use interface for common behavior, implementations for details [OK]
Common Mistakes:
  • Hardcoding payment types with if-else
  • Not using interfaces for common behavior
  • Using inheritance from concrete classes
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