Understanding SOLID Principles
SOLID is an acronym for five design principles that help developers write maintainable, scalable code.
S - Single Responsibility Principle
A class should have only one reason to change.
Python
# Bad
class User:
def save_to_database(self):
pass
def send_email(self):
pass
def generate_report(self):
pass
# Good
class User:
pass
class UserRepository:
def save(self, user):
pass
class EmailService:
def send(self, user, message):
passO - Open/Closed Principle
Software entities should be open for extension but closed for modification.
Python
# Using abstraction
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def process(self, amt):
pass
class CreditCardProcessor(PaymentProcessor):
def process(self, amt):
print(f"Processing credit card")
class PayPalProcessor(PaymentProcessor):
def process(self, amt):
print(f"Processing PayPal")L - Liskov Substitution Principle
Objects of a superclass should be replaceable with objects of its subclasses.
Python
class Bird:
def fly(self):
pass
# Violates LSP - Penguin can't fly
class Penguin(Bird):
def fly(self):
raise Exception("Can't fly!")
# Better design
class Bird:
pass
class FlyingBird(Bird):
def fly(self):
pass
class Penguin(Bird):
def swim(self):
passI - Interface Segregation Principle
Clients should not be forced to depend on interfaces they don't use.
Python
# Bad - Fat interface
class Worker(ABC):
@abstractmethod
def work(self):
pass
@abstractmethod
def eat(self):
pass
# Good - Segregated interfaces
class Workable(ABC):
@abstractmethod
def work(self):
pass
class Eatable(ABC):
@abstractmethod
def eat(self):
pass
class Human(Workable, Eatable):
def work(self):
pass
def eat(self):
pass
class Robot(Workable):
def work(self):
passD - Dependency Inversion Principle
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Python
# Bad
class MySQLDatabase:
def connect(self):
pass
class UserService:
def __init__(self):
self.db = MySQLDatabase() # Tight coupling
# Good
class Database(ABC):
@abstractmethod
def connect(self):
pass
class UserService:
def __init__(self, db: Database):
self.db = db # Depends on abstractionConclusion
SOLID principles are guidelines that help you write better code. Apply them thoughtfully based on your specific context.
SOLID
OOP
Design Patterns
Clean Code