0
0
LLDsystem_design~7 mins

Open/Closed Principle in LLD - System Design Guide

Choose your learning style9 modes available
Problem Statement
When software modules are changed directly to add new features, existing code can break and cause bugs. This makes the system fragile and hard to maintain as it grows.
Solution
The Open/Closed Principle solves this by designing modules that are open for extension but closed for modification. This means you add new behavior by adding new code, not by changing existing code, keeping the system stable and easier to grow.
Architecture
┌───────────────┐       ┌───────────────┐
│  Existing     │       │  New Feature  │
│  Module       │──────▶│  Module       │
│  (Closed)     │       │  (Extension)  │
└───────────────┘       └───────────────┘
        ▲                      │
        │                      │
        └──────────────────────┘

This diagram shows the existing module that is closed for changes but open to extensions through new modules that add features.

Trade-offs
✓ Pros
Reduces bugs by avoiding changes to tested, stable code.
Makes adding new features safer and faster.
Improves code maintainability and readability.
Supports easier testing by isolating new behavior.
✗ Cons
Can increase initial design complexity.
May lead to more classes or modules, increasing codebase size.
Requires developers to plan for extension points upfront.
Use when the system expects frequent feature additions or changes, especially in medium to large codebases with multiple developers.
Avoid when the project is very small or unlikely to change, as the added abstraction may be unnecessary overhead.
Real World Examples
Netflix
Netflix uses the Open/Closed Principle in their streaming service to add new content recommendation algorithms without changing the core playback system.
Amazon
Amazon applies this principle in their payment processing modules to support new payment methods by adding new modules instead of modifying existing ones.
Uber
Uber designs their ride pricing system to be open for extension to add new pricing strategies without modifying the existing calculation logic.
Code Example
The before code mixes all discount rules in one method, so adding new types means changing existing code. The after code uses separate classes for each discount type, so new discounts can be added by creating new classes without modifying existing ones.
LLD
### Before (violates Open/Closed Principle):
class DiscountCalculator:
    def calculate(self, customer_type, amount):
        if customer_type == 'regular':
            return amount * 0.9
        elif customer_type == 'vip':
            return amount * 0.8
        # Adding new customer types requires modifying this method

### After (applies Open/Closed Principle):
from abc import ABC, abstractmethod

class DiscountStrategy(ABC):
    @abstractmethod
    def calculate(self, amount):
        pass

class RegularDiscount(DiscountStrategy):
    def calculate(self, amount):
        return amount * 0.9

class VIPDiscount(DiscountStrategy):
    def calculate(self, amount):
        return amount * 0.8

class DiscountCalculator:
    def __init__(self, strategy: DiscountStrategy):
        self.strategy = strategy

    def calculate(self, amount):
        return self.strategy.calculate(amount)

# To add a new discount, create a new class without changing DiscountCalculator
OutputSuccess
Alternatives
Modifying Existing Code Directly
Changes are made inside existing modules instead of adding new ones.
Use when: Only when the system is very small and unlikely to change, to keep things simple.
Feature Flags
Uses runtime switches to enable or disable features instead of extending code via new modules.
Use when: When you need to toggle features quickly without deploying new code.
Summary
The Open/Closed Principle helps keep software stable by avoiding changes to existing code.
It encourages adding new features through extensions rather than modifications.
This principle improves maintainability and reduces bugs in growing systems.