SOLID principles lead to maintainable, extensible code. Not dogma, but useful guidelines.
S — Single Responsibility¶
SOLID Principles in Practice¶
class UserManager: def create_user(self, data): … def send_email(self, user): … def generate_report(self, users): …
✅ Correct — separated responsibilities¶
class UserService: def create_user(self, data): … class EmailService: def send_welcome(self, user): … class ReportService: def generate(self, users): …
O — Open/Closed¶
Open for extension, closed for modification¶
class PaymentProcessor(Protocol): def process(self, amount: float) -> bool: … class StripePayment: def process(self, amount: float) -> bool: … class PayPalPayment: def process(self, amount: float) -> bool: …
Adding a new type = new class, not modifying an existing one¶
D — Dependency Inversion¶
❌ High-level module depends on low-level module¶
class OrderService: def __init__(self): self.db = PostgresDB() # Hard dependency
✅ Depends on abstraction¶
class OrderService: def __init__(self, db: DatabasePort): self.db = db # Injected, testable
L — Liskov Substitution & I — Interface Segregation¶
- Liskov: A subclass must be substitutable for its parent class
- Interface Segregation: Small, specific interfaces instead of one large one
Key Takeaway¶
SRP: one class = one responsibility. DIP: depend on abstractions. SOLID as guidelines, not dogma.