Time to Master : ~30 minutes | Difficulty : Beginner-friendly | Prerequisite : Basic OOP understanding
🏗️ What are SOLID Principles?
Imagine building with LEGO blocks:
Good LEGO sets : Pieces fit together nicely, easy to change, fun to build
Bad LEGO sets : Pieces stuck together with glue, can’t change anything without breaking
SOLID principles are five rules that help you write code like good LEGO sets - modular, flexible, and maintainable!
🎯 Why Learn SOLID?
🔧 Easy to Change Modify one thing without breaking everything else
🐛 Fewer Bugs Simpler classes = fewer places for bugs to hide
🧪 Easy to Test Small, focused classes are easy to test
👥 Team Friendly Others can understand and work with your code
Interview Alert : SOLID principles are asked in almost every LLD interview! “Does your design follow SOLID?” is a common follow-up question.
📚 The Five Principles at a Glance
S - Single Responsibility Principle (SRP)
“Do ONE thing, and do it well!”
Like how a chef COOKS, a waiter SERVES, and a cashier handles PAYMENT - each has one job.
# ❌ BAD: UserManager does EVERYTHING
class UserManager :
def create_user ( self ): pass
def send_email ( self ): pass # Email is a different job!
def generate_report ( self ): pass # Reporting is different too!
# ✅ GOOD: Each class has ONE job
class UserService :
def create_user ( self ): pass
class EmailService :
def send_email ( self ): pass
class ReportService :
def generate_report ( self ): pass
O - Open/Closed Principle (OCP)
“Open for extension, closed for modification!”
Like adding new apps to your phone without rewriting the operating system.
# ❌ BAD: Must modify when adding new shapes
class AreaCalculator :
def calculate ( self , shape ):
if shape.type == "circle" :
return 3.14 * shape.radius ** 2
elif shape.type == "rectangle" : # Must keep adding elif!
return shape.width * shape.height
# ✅ GOOD: Add new shapes without changing existing code
class Shape :
def area ( self ): pass
class Circle ( Shape ):
def area ( self ):
return 3.14 * self .radius ** 2
class Rectangle ( Shape ):
def area ( self ):
return self .width * self .height
# Adding Triangle? Just create new class, don't touch existing!
L - Liskov Substitution Principle (LSP)
“Children should be able to replace their parents!”
If you expect an Animal, a Dog should work perfectly - without surprises.
# ❌ BAD: Penguin breaks the Bird contract
class Bird :
def fly ( self ): pass
class Penguin ( Bird ): # But penguins can't fly! 🐧
def fly ( self ):
raise Exception ( "I can't fly!" ) # Surprise!
# ✅ GOOD: Separate flying and non-flying birds
class Bird :
def eat ( self ): pass
class FlyingBird ( Bird ):
def fly ( self ): pass
class Penguin ( Bird ): # No fly() method to break
def swim ( self ): pass
I - Interface Segregation Principle (ISP)
“Don’t force me to implement things I don’t need!”
Like a printer that only prints - it shouldn’t need a fax feature if you don’t use fax.
# ❌ BAD: Forces all workers to implement every method
class Worker :
def work ( self ): pass
def eat ( self ): pass
def sleep ( self ): pass
class Robot ( Worker ): # Robots don't eat or sleep!
def eat ( self ): raise Exception ( "I don't eat!" )
def sleep ( self ): raise Exception ( "I don't sleep!" )
# ✅ GOOD: Separate interfaces
class Workable :
def work ( self ): pass
class Eatable :
def eat ( self ): pass
class Robot ( Workable ): # Only implements what it needs
def work ( self ): pass
D - Dependency Inversion Principle (DIP)
“Depend on abstractions, not concrete things!”
Like a phone charger - you plug into the WALL SOCKET (abstraction), not directly into power lines!
# ❌ BAD: High-level depends on low-level details
class PaymentProcessor :
def __init__ ( self ):
self .stripe = StripeAPI() # Directly tied to Stripe!
def pay ( self , amount ):
self .stripe.charge(amount) # What if we switch to PayPal?
# ✅ GOOD: Depend on abstraction
class PaymentGateway : # Abstract
def charge ( self , amount ): pass
class PaymentProcessor :
def __init__ ( self , gateway : PaymentGateway): # Accept ANY gateway
self .gateway = gateway
def pay ( self , amount ):
self .gateway.charge(amount) # Works with Stripe, PayPal, anything!
🎮 Interactive Memory Aid
Remember SOLID with this story:
S is for Single Chef 👨🍳
The chef only COOKS - doesn’t clean, serve, or manage money
O is for Open Restaurant 🏪
Add new dishes to the menu WITHOUT rewriting the kitchen
L is for Like Parent, Like Child 👨👧
If menu says “pasta”, any pasta type should work the same
I is for I Only Take Orders 📝
Waiter takes orders - doesn’t need to know cooking
D is for Depend on Rules 📋
Kitchen depends on RECIPE standards, not specific ingredients
🧪 Quick Self-Test
Q1: Which principle does this violate? class Report :
def generate_data ( self ): pass
def format_as_pdf ( self ): pass
def send_email ( self ): pass
Q2: Which principle does this violate? class Calculator :
def calculate ( self , operation , a , b ):
if operation == "add" : return a + b
elif operation == "subtract" : return a - b
# Must modify here for each new operation!
Q3: Which principle does this violate? class Machine :
def print_doc ( self ): pass
def scan_doc ( self ): pass
def fax_doc ( self ): pass
def copy_doc ( self ): pass
class SimplePrinter ( Machine ): # Only prints!
def scan_doc ( self ): raise NotImplementedError
def fax_doc ( self ): raise NotImplementedError
def copy_doc ( self ): raise NotImplementedError
📚 The SOLID Journey
Now let’s dive deep into each principle with fun examples and exercises!
🏃 Start Your Journey!
Begin with Single Responsibility Principle → Learn the first and most important SOLID principle - keeping your classes focused!