System Design ( Day - 41 )

SOLID Principles | Revision
๐ฉ Why Problems Arise Without SOLID Principles?
Without SOLID, you'll face:
โ Poor maintainability
โ Less readability
โ Higher chances of bugs
โ Tightly coupled classes
โ Difficult testing and refactoring
๐งฑ What is SOLID?
SOLID is an acronym representing 5 principles that help build maintainable and scalable software:
Principle | Name |
S | Single Responsibility Principle (SRP) |
O | Open-Closed Principle (OCP) |
L | Liskov Substitution Principle (LSP) |
I | Interface Segregation Principle (ISP) |
D | Dependency Inversion Principle (DIP) |
๐น S โ Single Responsibility Principle (SRP)
๐ฌ Definition: A class should have only one reason to change.
๐บ Analogy: A TV remote should control only the TV โ not your AC or refrigerator!
๐ Problem: If a class does multiple things, modifying one part can unintentionally break the others.
๐ ๏ธ Solution: Separate responsibilities into their own classes.
javaCopyEdit// โ Bad
class Remote {
controlTV();
controlAC(); // Not its job
}
// โ
Good
class TVRemote {
controlTV();
}
class ACRemote {
controlAC();
}
๐น O โ Open-Closed Principle (OCP)
๐ฌ Definition: Software entities should be open for extension but closed for modification.
๐ฆ Real-world: Suppose you have a SaveToSQL()
method. Tomorrow you want to save data to MongoDB or File too. Don't touch the original logic โ just extend it!
๐ ๏ธ Solution: Use interfaces and polymorphism to extend behavior.
javaCopyEditabstract class DataSaver {
abstract void save(Data data);
}
class SaveToSQL extends DataSaver {
void save(Data data) {
// Save to SQL
}
}
class SaveToMongo extends DataSaver {
void save(Data data) {
// Save to MongoDB
}
}
๐น L โ Liskov Substitution Principle (LSP)
๐ฌ Definition: Subclasses should be substitutable for their parent classes.
๐ฆ Example:
Transaction
class hasdeposit()
andwithdraw()
.SavingsAccount
&CurrentAccount
follow both.FixedDepositAccount
supports onlydeposit()
.
โ Violating LSP:
javaCopyEditclass FixedDeposit extends Transaction {
void withdraw() {
throw new UnsupportedOperationException();
}
}
โ Solution: Break them into multiple abstract classes:
javaCopyEditabstract class NonWithdrawableAccount {
abstract void deposit();
}
abstract class WithdrawableAccount extends NonWithdrawableAccount {
abstract void withdraw();
}
Now inherit WithdrawableAccount
in SavingsAccount
& CurrentAccount
,
and NonWithdrawableAccount
in FixedDeposit
.
๐น I โ Interface Segregation Principle (ISP)
๐ฌ Definition: Clients should not be forced to depend on methods they do not use.
๐จ๏ธ Example:
โ Violating ISP:
javaCopyEditinterface Shape {
double area();
double volume(); // Not needed for 2D shapes
}
class Square implements Shape {
double area() { ... }
double volume() { throw new UnsupportedOperationException(); }
}
โ Refactor into segregated interfaces:
javaCopyEditinterface TwoDShape { double area(); }
interface ThreeDShape extends TwoDShape { double volume(); }
class Square implements TwoDShape {
double area() { ... }
}
class Cube implements ThreeDShape {
double area() { ... }
double volume() { ... }
}
๐ง Benefit: Clean, focused contracts.
๐น D โ Dependency Inversion Principle (DIP)
๐ฌ Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions.
๐ง Example:
High-level class AuthService
should not depend directly on EmailSender
.
โ Violation:
javaCopyEditclass AuthService {
EmailSender sender = new EmailSender();
void register(User user) {
sender.sendWelcomeEmail(user.email);
}
}
โ Apply DIP:
javaCopyEditinterface MessageSender {
void send(String to);
}
class EmailSender implements MessageSender {
public void send(String to) { ... }
}
class AuthService {
MessageSender sender;
AuthService(MessageSender sender) {
this.sender = sender;
}
void register(User user) {
sender.send(user.email);
}
}
๐ง Benefit: Easily switch between EmailSender
, SMSSender
, PushNotifier
, etc.
Subscribe to my newsletter
Read articles from Manoj Kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
