Bird
0
0
LLDsystem_design~7 mins

Why more behavioral patterns solve communication in LLD - Why This Architecture

Choose your learning style9 modes available
Problem Statement
When components or objects in a system communicate directly without clear protocols, the code becomes tightly coupled and hard to maintain. Changes in one part can cause unexpected failures elsewhere, making debugging and extending the system difficult.
Solution
Behavioral patterns define clear communication protocols between objects, organizing how they interact and share responsibilities. By encapsulating communication logic, these patterns reduce dependencies and improve flexibility, making the system easier to modify and extend.
Architecture
┌─────────────┐       ┌─────────────┐       ┌─────────────┐
│  Component 1│──────▶│  Mediator   │──────▶│  Component 2│
└─────────────┘       └─────────────┘       └─────────────┘
       ▲                                         │
       │─────────────────────────────────────────┘

This diagram shows how the Mediator pattern centralizes communication between components, preventing direct dependencies between them.

Trade-offs
✓ Pros
Reduces tight coupling between communicating objects by centralizing interaction logic.
Improves code maintainability and readability by defining clear communication protocols.
Facilitates easier extension and modification of communication behavior without affecting other components.
✗ Cons
Introduces an additional layer which can add complexity and potential performance overhead.
Overuse can lead to a large mediator or controller class that becomes difficult to manage.
May obscure the flow of communication if not well documented or designed.
Use when multiple objects interact in complex ways and direct communication causes tight coupling or maintenance issues, especially in systems with many interdependent components.
Avoid when interactions are simple and direct communication is clear and unlikely to change, or when performance is critical and added indirection is unacceptable.
Real World Examples
Airbnb
Uses the Mediator pattern in their booking system to coordinate communication between availability, pricing, and payment components without tight coupling.
Uber
Applies Observer and Mediator patterns to manage real-time updates between drivers, riders, and dispatch systems, ensuring scalable and maintainable communication.
LinkedIn
Employs behavioral patterns like Observer to handle notifications and feed updates, decoupling event producers from consumers.
Code Example
Before, ComponentA directly calls ComponentB, creating tight coupling. After applying the Mediator pattern, both components communicate through the Mediator, which controls interactions and reduces dependencies.
LLD
### Before: Direct communication causing tight coupling
class ComponentA:
    def __init__(self, component_b):
        self.component_b = component_b

    def do_action(self):
        print("ComponentA does action")
        self.component_b.notify()

class ComponentB:
    def notify(self):
        print("ComponentB notified")

b = ComponentB()
a = ComponentA(b)
a.do_action()


### After: Using Mediator pattern to centralize communication
class Mediator:
    def __init__(self):
        self.component_a = ComponentA(self)
        self.component_b = ComponentB(self)

    def notify(self, sender, event):
        if sender == self.component_a and event == "action_done":
            self.component_b.handle()

class ComponentA:
    def __init__(self, mediator):
        self.mediator = mediator

    def do_action(self):
        print("ComponentA does action")
        self.mediator.notify(self, "action_done")

class ComponentB:
    def __init__(self, mediator):
        self.mediator = mediator

    def handle(self):
        print("ComponentB handles event")

mediator = Mediator()
mediator.component_a.do_action()
OutputSuccess
Alternatives
Direct Communication
Objects communicate directly without intermediaries, leading to tight coupling.
Use when: Use when the system is simple with few components and minimal interaction complexity.
Event-Driven Architecture
Uses asynchronous events and message queues for communication instead of synchronous behavioral patterns.
Use when: Choose when decoupling and scalability across distributed systems are priorities.
Summary
Direct communication between components can cause tight coupling and maintenance challenges.
Behavioral patterns organize communication, reducing dependencies and improving flexibility.
Using these patterns helps build scalable, maintainable systems with clear interaction protocols.