What if your code could change as easily as swapping LEGO blocks without breaking everything?
Why SOLID violations and fixes in LLD? - Purpose & Use Cases
Imagine building a big LEGO castle where every piece is glued together. If you want to change a tower or add a new room, you have to break the glue and risk damaging the whole castle.
When code breaks SOLID principles, it becomes like that glued LEGO castle. Making changes is slow, risky, and causes unexpected bugs because parts are tightly connected and hard to fix or replace.
SOLID principles guide us to build code like LEGO blocks that snap together but can be taken apart easily. This makes the system flexible, easier to understand, and safer to change without breaking other parts.
class OrderProcessor {
void process(Order order) {
// process payment
// update inventory
// send confirmation email
}
}interface PaymentService { void pay(Order order); }
interface InventoryService { void update(Order order); }
interface NotificationService { void notify(Order order); }
class OrderProcessor {
PaymentService payment;
InventoryService inventory;
NotificationService notification;
void process(Order order) {
payment.pay(order);
inventory.update(order);
notification.notify(order);
}
}It enables building software that adapts easily to new needs without breaking existing features.
Think of a smartphone app where you can add new features like payment methods or notifications without rewriting the whole app.
SOLID helps keep code flexible and maintainable.
It reduces bugs when making changes.
It makes teamwork easier by separating responsibilities.
Practice
Solution
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.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.Final Answer:
Single Responsibility Principle -> Option AQuick Check:
One class, one responsibility = C [OK]
- Confusing Single Responsibility with Open/Closed Principle
- Thinking Liskov Substitution relates to responsibilities
- Mixing Interface Segregation with class responsibilities
class Shape {
draw() { /* draw shape */ }
}
class Circle extends Shape {
draw() { /* draw circle */ }
}Solution
Step 1: Understand Open/Closed Principle
This principle says software entities should be open for extension but closed for modification.Step 2: Analyze the code snippet
Extending Shape with new classes like Circle adds new behavior without changing existing Shape code.Final Answer:
Adding new shape classes by extending Shape without changing existing code -> Option AQuick Check:
Extend without modify = A [OK]
- Modifying base class instead of extending
- Using if-else inside methods to handle new cases
- Overriding methods incorrectly causing side effects
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();Solution
Step 1: Understand the code behavior
The robot class implements work() by printing "Robot working" and eat() throws an exception.Step 2: Analyze the method called
Only robot.work() is called, which prints the message without error.Final Answer:
Robot working -> Option DQuick Check:
Calling work() prints message = A [OK]
- Assuming eat() is called causing exception
- Thinking interface violation causes compile error
- Ignoring method actually called in code
class Bird {
void fly() { System.out.println("Flying"); }
}
class Ostrich extends Bird {
void fly() { throw new UnsupportedOperationException(); }
}Solution
Step 1: Understand Liskov Substitution Principle
Subtypes must be replaceable for their base types without altering correctness.Step 2: Analyze Ostrich behavior
Ostrich throws exception on fly(), breaking expected behavior of Bird.Final Answer:
Ostrich cannot replace Bird without breaking behavior -> Option CQuick Check:
Subtype must behave like base = B [OK]
- Thinking method signature change fixes violation
- Ignoring exception breaking substitution
- Assuming base class design is wrong here
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?Solution
Step 1: Identify the violated principle
Having one interface with many methods causes classes to implement unsupported methods, violating Interface Segregation Principle.Step 2: Apply the fix
Splitting the interface into smaller, specific interfaces lets classes implement only what they support, improving design.Final Answer:
Split the interface into smaller ones for each payment method -> Option BQuick Check:
Small interfaces, no unused methods = D [OK]
- Adding empty default methods hides design flaws
- Using flags complicates code and violates design
- Removing methods silently breaks interface contract
Ready to prove it?
Pass the test and this pattern moves unknown
