0
0
LLDsystem_design~7 mins

Object-oriented design principles in LLD - System Design Guide

Choose your learning style9 modes available
Problem Statement
When software classes are tightly coupled, hard to change, or have unclear responsibilities, the code becomes fragile and difficult to maintain. This leads to bugs, slow development, and poor scalability as the system grows.
Solution
Object-oriented design principles guide how to organize classes and objects so they are easy to understand, extend, and maintain. They promote clear responsibilities, loose coupling, and reusable code by following simple rules during design.
Architecture
Class A
(Single Resp)
Class B
Interface I
(Interface Seg)

This diagram shows how different object-oriented design principles relate: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion, connected through class and interface relationships.

Trade-offs
✓ Pros
Improves code maintainability by clearly defining class responsibilities.
Enables easier extension of features without modifying existing code.
Reduces bugs by promoting loose coupling and clear interfaces.
Facilitates teamwork by making code easier to understand and modify.
✗ Cons
Requires upfront design effort and understanding of principles.
May introduce more classes and interfaces, increasing initial complexity.
Over-applying principles can lead to over-engineering and unnecessary abstraction.
Use when building systems expected to grow in size or complexity, or when multiple developers work on the codebase to ensure maintainability and scalability.
Avoid strict application in small, simple scripts or prototypes where speed of development is more important than long-term maintainability.
Real World Examples
Amazon
Uses Single Responsibility and Dependency Inversion principles to build modular microservices that can evolve independently without breaking others.
Netflix
Applies Open/Closed and Interface Segregation principles to add new streaming features without changing existing stable code.
Uber
Employs Liskov Substitution to ensure different vehicle types can be used interchangeably in ride dispatch logic.
Code Example
The before code mixes data processing and file saving in one class, violating Single Responsibility. The after code separates these concerns into different classes and uses abstract base classes to invert dependencies, making the design more modular and testable.
LLD
### Before applying principles (violating Single Responsibility and Dependency Inversion):

class Report:
    def __init__(self, data):
        self.data = data

    def calculate_statistics(self):
        # complex calculation logic
        pass

    def save_to_file(self, filename):
        with open(filename, 'w') as f:
            f.write(str(self.data))


### After applying principles:

from abc import ABC, abstractmethod

class DataProcessor(ABC):
    @abstractmethod
    def calculate_statistics(self):
        pass

class Report(DataProcessor):
    def __init__(self, data):
        self.data = data

    def calculate_statistics(self):
        # complex calculation logic
        pass

class FileSaver(ABC):
    @abstractmethod
    def save(self, filename):
        pass

class ReportFileSaver(FileSaver):
    def __init__(self, report):
        self.report = report

    def save(self, filename):
        with open(filename, 'w') as f:
            f.write(str(self.report.data))
OutputSuccess
Alternatives
Procedural Programming
Focuses on functions and procedures rather than objects and classes.
Use when: Choose when the problem domain is simple and does not require complex state management or extensibility.
Functional Programming
Emphasizes pure functions and immutable data instead of mutable objects and inheritance.
Use when: Choose when you want to avoid side effects and improve concurrency safety.
Summary
Object-oriented design principles help create code that is easier to maintain, extend, and understand.
They promote clear responsibilities, loose coupling, and reliance on abstractions rather than concrete implementations.
Applying these principles thoughtfully improves software quality and team productivity over time.