Architecture / SOLID Principles Simulator
"Interactive simulations demonstrating the architectural shift from fragile, tightly-coupled code to resilient, extensible systems."
class UserDashboard
UserRepository
UserMetricsService
UserController
Single Responsibility Violated
The Problem: The `UserDashboard` class handles database access, business logic, and UI rendering.
Move the slider below to simulate changing the "Business Logic" requirements. Notice how modifying the logic risks breaking the database and UI components because they are entangled in the same file.
The Solution: The class is split into Repository (Data), Service (Logic), and Controller (UI).
Move the slider now. Modifying the business requirements only affects the `UserMetricsService`. The database and UI layers remain perfectly isolated and safe from unintended side effects.
Drag to inject new requirement complexity.
class AIChatEngine
return init_gemini(text)
Open/Closed Violated
The Problem: The core engine uses a massive `if/else` statement. Every time we add a new AI model, we have to physically open and modify the `AIChatEngine` source code. This risks breaking the existing Gemini integration.
The Solution: The `AIChatEngine` is closed for modification. It relies on a generic `IAIPlugin` interface. New models are added as standalone plugins that hook into the system without touching the core code.
Liskov Substitution Violated
The Problem: We have a function expecting a `Vehicle` base class. It calls `start_engine()` and checks `fuel_level`. We substitute a subclass `ToyCar`. Because `ToyCar` doesn't have fuel, it breaks the expected semantic behavior of the base class, causing a crash.
The Solution: `ToyCar` should not inherit from `Vehicle` if it cannot substitute it completely. Instead, we redesign the hierarchy so the execution context relies on a proper interface (e.g., `IMovable`), ensuring safe substitutions.
interface IMultiMachine
Interface Segregation Violated
The Problem: Both devices are forced to implement a fat `IMultiMachine` interface. If we change the signature of `scan_document()`, the Basic Printer (which doesn't even use scanning) gets recompiled or throws an error due to the changed contract.
The Solution: The fat interface is segregated into `IPrinter`, `IScanner`, etc. Now, changing the scanner interface only affects the Scanner client. The Printer is blissfully unaware.
Simulates adding a new parameter to the scan method.
OrderProcessor
High-Level Business Logic
MySQLConnection
Low-Level Details
Dependency Inversion Violated
The Problem: The high-level `OrderProcessor` directly imports and instantiates the concrete `MySQLConnection`. If we want to switch to PostgreSQL, we have to rewrite the high-level business logic, which is risky.
The Solution: Both layers now depend on an abstraction (`IDatabase`). The high-level module just talks to the interface. We can swap the underlying database seamlessly via Dependency Injection without touching the business logic.