Bird
Raised Fist0
LLDsystem_design~10 mins

SOLID violations and fixes in LLD - Scalability & System Analysis

Choose your learning style10 modes available
Scalability Analysis - SOLID violations and fixes
Growth Table: SOLID Violations Impact
Users / ScaleCodebase ComplexityBug RateDevelopment SpeedSystem Stability
100 usersSmall codebase, manageable violationsLowFastStable
10K usersCodebase grows, violations cause confusionMediumSlower due to fixesOccasional bugs
1M usersLarge codebase, many violations cause tight couplingHighSlow, hard to add featuresUnstable, frequent regressions
100M usersVery large, unmaintainable codebaseVery highVery slow, costly fixesSystem failures common
First Bottleneck

The first bottleneck is the code maintainability. Violations of SOLID principles cause tightly coupled and fragile code. As users grow, adding features or fixing bugs becomes slow and error-prone. This slows development and increases bugs, affecting system stability.

Scaling Solutions
  • Single Responsibility Principle (SRP): Break classes/modules so each has one job. Easier to understand and change.
  • Open/Closed Principle (OCP): Design modules to allow extension without changing existing code. Use interfaces or abstract classes.
  • Liskov Substitution Principle (LSP): Ensure subclasses can replace base classes without errors. Avoid unexpected behavior.
  • Interface Segregation Principle (ISP): Use many small, specific interfaces instead of one big one. Clients depend only on what they use.
  • Dependency Inversion Principle (DIP): Depend on abstractions, not concrete classes. Use dependency injection to reduce coupling.
  • Refactoring: Regularly improve code structure to fix violations and keep code clean.
  • Automated Testing: Use tests to safely refactor and catch regressions early.
Back-of-Envelope Cost Analysis
  • At 1K users, code changes are quick; bugs are rare.
  • At 10K users, fixing SOLID violations costs more developer hours, slowing releases.
  • At 1M users, poor design causes frequent bugs, increasing support and downtime costs.
  • At 100M users, system instability leads to high operational costs and lost revenue.
  • Investing in SOLID principles early reduces long-term maintenance and scaling costs.
Interview Tip

When discussing scalability related to SOLID, start by explaining how code quality affects system growth. Describe how violations cause tight coupling and slow development. Then, explain each SOLID principle as a fix that improves maintainability and scalability. Use examples of how refactoring and testing help scale the codebase as users grow.

Self Check

Your database handles 1000 QPS. Traffic grows 10x. What do you do first?

Answer: First, identify if the codebase can handle new features or fixes quickly. If SOLID violations cause slow development or bugs, prioritize refactoring to improve maintainability. This ensures the system can scale reliably with increased traffic.

Key Result
SOLID violations cause code maintainability bottlenecks that slow development and increase bugs as user scale grows; applying SOLID principles early enables scalable, stable systems.

Practice

(1/5)
1. Which SOLID principle is violated if a class has too many responsibilities, making it hard to maintain?
easy
A. Single Responsibility Principle
B. Open/Closed Principle
C. Liskov Substitution Principle
D. Interface Segregation Principle

Solution

  1. Step 1: Understand the problem of multiple responsibilities

    A class with many responsibilities is hard to maintain and change because changes in one responsibility may affect others.
  2. Step 2: Identify the violated SOLID principle

    The Single Responsibility Principle states that a class should have only one reason to change, meaning one responsibility.
  3. Final Answer:

    Single Responsibility Principle -> Option A
  4. Quick Check:

    One class, one responsibility = C [OK]
Hint: One class, one job means Single Responsibility Principle [OK]
Common Mistakes:
  • Confusing Single Responsibility with Open/Closed Principle
  • Thinking Liskov Substitution relates to responsibilities
  • Mixing Interface Segregation with class responsibilities
2. Which of the following code snippets correctly applies the Open/Closed Principle by allowing extension without modification?
class Shape {
draw() { /* draw shape */ }
}
class Circle extends Shape {
draw() { /* draw circle */ }
}
easy
A. Adding new shape classes by extending Shape without changing existing code
B. Modifying the Shape class draw method to handle all shapes
C. Using a single class for all shapes with if-else inside draw
D. Changing Circle class to override Shape's draw method with new logic

Solution

  1. Step 1: Understand Open/Closed Principle

    This principle says software entities should be open for extension but closed for modification.
  2. Step 2: Analyze the code snippet

    Extending Shape with new classes like Circle adds new behavior without changing existing Shape code.
  3. Final Answer:

    Adding new shape classes by extending Shape without changing existing code -> Option A
  4. Quick Check:

    Extend without modify = A [OK]
Hint: Extend classes, don't change existing ones [OK]
Common Mistakes:
  • Modifying base class instead of extending
  • Using if-else inside methods to handle new cases
  • Overriding methods incorrectly causing side effects
3. Given the following code violating Interface Segregation Principle, what is the output when calling robot.work()?
interface Worker {
void work();
void eat();
}
class Robot implements Worker {
public void work() { System.out.println("Robot working"); }
public void eat() { throw new UnsupportedOperationException(); }
}
Robot robot = new Robot();
robot.work();
medium
A. No output
B. UnsupportedOperationException thrown
C. Compilation error
D. Robot working

Solution

  1. Step 1: Understand the code behavior

    The robot class implements work() by printing "Robot working" and eat() throws an exception.
  2. Step 2: Analyze the method called

    Only robot.work() is called, which prints the message without error.
  3. Final Answer:

    Robot working -> Option D
  4. Quick Check:

    Calling work() prints message = A [OK]
Hint: Calling only implemented methods avoids exceptions [OK]
Common Mistakes:
  • Assuming eat() is called causing exception
  • Thinking interface violation causes compile error
  • Ignoring method actually called in code
4. Identify the main problem in this code violating Liskov Substitution Principle:
class Bird {
void fly() { System.out.println("Flying"); }
}
class Ostrich extends Bird {
void fly() { throw new UnsupportedOperationException(); }
}
medium
A. Bird class should not have fly method
B. Ostrich should override fly with different signature
C. Ostrich cannot replace Bird without breaking behavior
D. No violation, code is correct

Solution

  1. Step 1: Understand Liskov Substitution Principle

    Subtypes must be replaceable for their base types without altering correctness.
  2. Step 2: Analyze Ostrich behavior

    Ostrich throws exception on fly(), breaking expected behavior of Bird.
  3. Final Answer:

    Ostrich cannot replace Bird without breaking behavior -> Option C
  4. Quick Check:

    Subtype must behave like base = B [OK]
Hint: Subtype must not break base class behavior [OK]
Common Mistakes:
  • Thinking method signature change fixes violation
  • Ignoring exception breaking substitution
  • Assuming base class design is wrong here
5. You have a payment system where the PaymentProcessor interface has methods payWithCreditCard(), payWithPayPal(), and payWithCrypto(). A new payment method is added, but many classes implementing this interface do not support all methods, causing empty or error implementations. How should you fix this design following SOLID principles?
hard
A. Remove unsupported methods from implementations silently
B. Split the interface into smaller ones for each payment method
C. Keep one interface and add flags to check supported methods
D. Add default empty implementations to the interface methods

Solution

  1. Step 1: Identify the violated principle

    Having one interface with many methods causes classes to implement unsupported methods, violating Interface Segregation Principle.
  2. Step 2: Apply the fix

    Splitting the interface into smaller, specific interfaces lets classes implement only what they support, improving design.
  3. Final Answer:

    Split the interface into smaller ones for each payment method -> Option B
  4. Quick Check:

    Small interfaces, no unused methods = D [OK]
Hint: Use many small interfaces, not one big one [OK]
Common Mistakes:
  • Adding empty default methods hides design flaws
  • Using flags complicates code and violates design
  • Removing methods silently breaks interface contract
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