Bird
Raised Fist0
LLDsystem_design~20 mins

Liskov Substitution Principle in LLD - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
LSP Mastery Badge
Get all challenges correct to earn this badge!
Test your skills under time pressure!
🧠 Conceptual
intermediate
1:30remaining
Understanding Liskov Substitution Principle (LSP)

Which of the following best describes the Liskov Substitution Principle in system design?

ABase classes must be replaceable by their derived classes without altering the correctness of the program.
BBase classes must never be extended by derived classes to avoid complexity.
CSubclasses should always add new methods instead of modifying existing ones.
DDerived classes can override base class methods with completely different behaviors.
Attempts:
2 left
💡 Hint

Think about substituting objects in a program without breaking it.

❓ Architecture
intermediate
2:00remaining
Applying LSP in Class Hierarchies

Consider a class hierarchy where a Rectangle class has a method setWidth and setHeight. A subclass Square overrides these methods to keep width and height equal. Which problem does this violate according to LSP?

ANo violation; LSP only applies to interfaces, not classes.
BSquare perfectly follows LSP because it inherits Rectangle methods.
CRectangle violates LSP because it allows width and height to be set separately.
DSquare cannot be substituted for Rectangle because it changes expected behavior of setting width and height independently.
Attempts:
2 left
💡 Hint

Think about whether the subclass changes the expected behavior of the base class methods.

❓ scaling
advanced
2:30remaining
Scaling Systems with LSP-Compliant Components

When designing a large-scale system with multiple service components, how does adhering to LSP help in scaling and maintaining the system?

AIt forces all components to be identical, reducing flexibility in scaling.
BIt ensures components can be replaced or extended without breaking existing integrations, easing scaling and maintenance.
CIt requires rewriting all components when scaling to maintain consistency.
DIt limits the number of components to avoid complexity.
Attempts:
2 left
💡 Hint

Consider how substitutability affects system upgrades and extensions.

❓ tradeoff
advanced
2:30remaining
Tradeoffs When Enforcing LSP Strictly

What is a common tradeoff when strictly enforcing LSP in a complex system design?

AIt forces all subclasses to have identical code, causing duplication.
BIt always increases system complexity and bugs.
CIt may limit the ability to optimize subclasses for specific cases, reducing performance gains.
DIt eliminates the need for interfaces and abstract classes.
Attempts:
2 left
💡 Hint

Think about balancing design purity and practical optimizations.

❓ component
expert
3:00remaining
Identifying LSP Violation in Component Interaction

Given a payment processing system where a PaymentProcessor interface defines a method processPayment(amount). A subclass CryptoPaymentProcessor overrides this method but throws an exception if the amount is below a minimum threshold, unlike the base implementation which accepts all amounts. What is the impact of this on LSP?

ACryptoPaymentProcessor violates LSP because it changes the expected behavior by throwing exceptions for inputs accepted by the base class.
BCryptoPaymentProcessor follows LSP because it extends the base interface and adds validation.
CThere is no impact on LSP since exceptions are allowed in subclasses.
DLSP is not applicable to interfaces, only to concrete classes.
Attempts:
2 left
💡 Hint

Consider whether the subclass can be used anywhere the base class is expected without causing errors.

Practice

(1/5)
1.

What does the Liskov Substitution Principle (LSP) primarily ensure in system design?

easy
A. Child classes can replace parent classes without affecting correctness
B. Parent classes must never be extended
C. Child classes should have fewer methods than parent classes
D. Parent classes should depend on child classes

Solution

  1. Step 1: Understand LSP definition

    LSP states that objects of a child class should be replaceable with objects of the parent class without breaking the program.
  2. Step 2: Analyze options against LSP

    Only Child classes can replace parent classes without affecting correctness correctly describes this principle. Other options contradict LSP or are unrelated.
  3. Final Answer:

    Child classes can replace parent classes without affecting correctness -> Option A
  4. Quick Check:

    Liskov Substitution Principle = Child replaces Parent [OK]
Hint: LSP means child works anywhere parent is expected [OK]
Common Mistakes:
  • Thinking LSP forbids inheritance
  • Confusing LSP with interface segregation
  • Believing child classes can change parent behavior arbitrarily
2.

Which of the following class declarations follows the Liskov Substitution Principle?

class Bird {
  fly() {}
}

class Penguin extends Bird {
  fly() {
    throw new Error('Cannot fly');
  }
}
easy
A. Yes, because Penguin is a Bird
B. No, because Penguin breaks expected behavior of Bird
C. Yes, because Penguin overrides fly method
D. No, because Bird should not have fly method

Solution

  1. Step 1: Analyze Penguin's fly method

    Penguin throws an error on fly(), but Bird expects fly() to work normally.
  2. Step 2: Check LSP compliance

    Since Penguin cannot be used where Bird is expected (fly method fails), it violates LSP.
  3. Final Answer:

    No, because Penguin breaks expected behavior of Bird -> Option B
  4. Quick Check:

    Child must not break parent behavior = No [OK]
Hint: Child must not break parent's expected methods [OK]
Common Mistakes:
  • Ignoring method behavior changes in child
  • Assuming inheritance alone guarantees LSP
  • Thinking overriding with error is allowed
3.

Consider the following code snippet. What will be the output?

class Vehicle {
  start() { return 'Vehicle started'; }
}

class Car extends Vehicle {
  start() { return 'Car started'; }
}

function startVehicle(v) {
  return v.start();
}

const myCar = new Car();
console.log(startVehicle(myCar));
medium
A. 'Vehicle started'
B. Error: start is not a function
C. 'Car started'
D. undefined

Solution

  1. Step 1: Understand method overriding

    Car overrides start() method to return 'Car started'.
  2. Step 2: Trace function call

    startVehicle(myCar) calls myCar.start(), which returns 'Car started'.
  3. Final Answer:

    'Car started' -> Option C
  4. Quick Check:

    Overridden method returns child's message [OK]
Hint: Child method overrides parent, so child's output shows [OK]
Common Mistakes:
  • Expecting parent method output instead of child's
  • Confusing method names or forgetting override
  • Assuming error due to polymorphism
4.

Identify the violation of Liskov Substitution Principle in the code below and select the fix.

class Rectangle {
  setWidth(w) { this.width = w; }
  setHeight(h) { this.height = h; }
  area() { return this.width * this.height; }
}

class Square extends Rectangle {
  setWidth(w) {
    this.width = w;
    this.height = w;
  }
  setHeight(h) {
    this.width = h;
    this.height = h;
  }
}
medium
A. Use separate classes without inheritance for Square and Rectangle
B. Square should not override setWidth and setHeight
C. Square should only override area() method
D. No violation, code is correct

Solution

  1. Step 1: Identify LSP violation

    Square changes behavior of setWidth and setHeight, breaking Rectangle's expectations.
  2. Step 2: Choose fix

    To follow LSP, Square and Rectangle should not be in inheritance relation if behaviors differ fundamentally.
  3. Final Answer:

    Use separate classes without inheritance for Square and Rectangle -> Option A
  4. Quick Check:

    Different behavior means no inheritance [OK]
Hint: If child changes parent's method meaning, avoid inheritance [OK]
Common Mistakes:
  • Ignoring behavioral changes in overridden methods
  • Trying to fix by only overriding area()
  • Assuming inheritance always fits shapes
5.

You are designing a payment system with a base class PaymentMethod and subclasses CreditCard and Bitcoin. The base class has a method processPayment(amount) that returns a success message. However, Bitcoin payments require additional confirmation steps and may fail differently. How should you design these classes to follow the Liskov Substitution Principle?

hard
A. Make processPayment abstract and force subclasses to implement their own versions ignoring base behavior
B. Make Bitcoin inherit PaymentMethod and override processPayment to throw errors on failure
C. Remove inheritance and implement separate interfaces for each payment type
D. Keep Bitcoin and CreditCard as subclasses but ensure processPayment behaves consistently and returns success/failure uniformly

Solution

  1. Step 1: Understand LSP in payment context

    Subclasses must behave so they can replace base class without breaking client code.
  2. Step 2: Design consistent behavior

    Bitcoin and CreditCard should implement processPayment so it returns success/failure in a consistent way, hiding internal differences.
  3. Final Answer:

    Keep Bitcoin and CreditCard as subclasses but ensure processPayment behaves consistently and returns success/failure uniformly -> Option D
  4. Quick Check:

    Consistent behavior across subclasses = LSP compliance [OK]
Hint: Subclasses must behave consistently to replace parent safely [OK]
Common Mistakes:
  • Throwing errors breaking expected method contracts
  • Ignoring different failure modes without abstraction
  • Removing inheritance unnecessarily
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