SOLID Principles in Practice: Real Code Examples That Make Sense

Every SOLID explanation uses the same examples: shapes, animals, or abstract notions that have nothing to do with code you’d actually write. Let me explain SOLID with examples from a real e-commerce application.

S – Single Responsibility Principle

“A class should have one reason to change.”

# BAD - This class does too many things
class OrderService:
    def create_order(self, cart, user):
        # validates cart items
        # calculates pricing
        # processes payment
        # sends confirmation email
        # updates inventory
        pass

# GOOD - Each class handles one concern
class OrderValidator:
    def validate(self, cart): ...

class PricingCalculator:
    def calculate(self, items, discounts): ...

class PaymentProcessor:
    def charge(self, amount, payment_method): ...

class OrderNotifier:
    def send_confirmation(self, order, user): ...

class InventoryUpdater:
    def deduct_stock(self, items): ...

When the email template changes, you only modify OrderNotifier. When pricing rules change, you only touch PricingCalculator. Changes are isolated.

O – Open/Closed Principle

“Open for extension, closed for modification.”

# BAD - Adding a new discount type requires modifying existing code
class DiscountCalculator:
    def calculate(self, order, discount_type):
        if discount_type == "percentage":
            return order.total * 0.1
        elif discount_type == "fixed":
            return 10.0
        elif discount_type == "bogo":  # Had to modify this class
            return order.cheapest_item_price

# GOOD - New discount types are added without modifying existing code
class PercentageDiscount:
    def calculate(self, order):
        return order.total * self.percentage

class FixedDiscount:
    def calculate(self, order):
        return self.amount

class BOGODiscount:  # New class, nothing else changes
    def calculate(self, order):
        return order.cheapest_item_price

L – Liskov Substitution Principle

“Subtypes must be substitutable for their base types.”

# BAD - Substitution breaks behavior
class PaymentMethod:
    def pay(self, amount): ...
    def refund(self, amount): ...

class GiftCard(PaymentMethod):
    def refund(self, amount):
        raise Exception("Gift cards can't be refunded!")  # Breaks contract

# GOOD - Separate what can be refunded from what can't
class PaymentMethod:
    def pay(self, amount): ...

class RefundablePayment(PaymentMethod):
    def refund(self, amount): ...

class CreditCard(RefundablePayment):
    def refund(self, amount): ...  # This works

class GiftCard(PaymentMethod):
    pass  # No refund method - no broken contract

I – Interface Segregation Principle

“No client should be forced to depend on methods it doesn’t use.”

# BAD - Every notification channel must implement everything
class NotificationChannel:
    def send_email(self, msg): ...
    def send_sms(self, msg): ...
    def send_push(self, msg): ...

# GOOD - Separate interfaces for separate capabilities
class EmailSender:
    def send(self, msg): ...

class SMSSender:
    def send(self, msg): ...

class PushSender:
    def send(self, msg): ...

D – Dependency Inversion Principle

“Depend on abstractions, not concretions.”

# BAD - OrderService directly depends on a specific database
class OrderService:
    def __init__(self):
        self.db = PostgresDatabase()  # Tightly coupled

# GOOD - OrderService depends on an abstraction
class OrderService:
    def __init__(self, repository):
        self.repository = repository  # Could be Postgres, MongoDB, or a mock

# Easy to swap implementations
service = OrderService(PostgresRepository())  # Production
service = OrderService(InMemoryRepository())  # Testing

SOLID isn’t about following rules blindly. It’s about writing code that’s easy to change when requirements change – and requirements always change. Apply these principles where they reduce complexity. Don’t force them where they add it.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top