# SOLID Principles — Overview The SOLID principles are five design guidelines that make object-oriented software easier to understand, maintain, and extend. They were promoted by Robert C. Martin (Uncle Bob) and have become foundational to professional software engineering. ## Quick-Reference Table | Principle | Abbr. | One-Liner | Key Question | |---|---|---|---| | **Single Responsibility** | SRP | A class should have only one reason to change. | "Does this class do more than one job?" | | **Open/Closed** | OCP | Open for extension, closed for modification. | "Can I add behavior without editing existing code?" | | **Liskov Substitution** | LSP | Subtypes must be substitutable for their base types. | "Can I swap in a subclass without breaking anything?" | | **Interface Segregation** | ISP | No client should depend on methods it does not use. | "Is any implementer forced to stub out unused methods?" | | **Dependency Inversion** | DIP | Depend on abstractions, not concretions. | "Does my high-level logic import low-level details?" | ## Decision Tree Use the following decision tree when reviewing or designing code: ``` START: You are looking at a class / module / struct │ ├─ Does it have more than one reason to change? │ YES → Apply SRP. Split into focused units. │ NO ↓ │ ├─ To add a new variant / behavior, must you edit existing code? │ YES → Apply OCP. Introduce polymorphism or strategy. │ NO ↓ │ ├─ Can every subtype replace its parent without breaking callers? │ NO → Apply LSP. Fix the inheritance hierarchy or use composition. │ YES ↓ │ ├─ Are implementers forced to depend on methods they don't use? │ YES → Apply ISP. Break the interface into smaller, focused ones. │ NO ↓ │ ├─ Do high-level modules import / instantiate low-level concretions? │ YES → Apply DIP. Introduce an abstraction and inject dependencies. │ NO ↓ │ └─ Design looks solid. Review for other concerns (DRY, KISS, etc.) ``` ## How the Principles Relate ``` SRP ──► keeps units small and focused │ OCP ──► lets you extend those units safely │ LSP ──► guarantees substitutability in those extensions │ ISP ──► prevents bloated contracts between units │ DIP ──► decouples the wiring so everything stays flexible ``` - **SRP + ISP** often work together: splitting a fat class (SRP) usually means splitting its interface too (ISP). - **OCP + DIP** are natural partners: depending on abstractions (DIP) is *how* you achieve extension without modification (OCP). - **LSP** is the safety net: it ensures that the polymorphism you rely on for OCP actually works correctly. ## When to Apply SOLID **Apply aggressively when:** - The codebase is long-lived and maintained by a team - Requirements change frequently - You are building libraries or frameworks consumed by others - Testability is a priority **Apply with restraint when:** - Writing a one-off script or prototype - The domain is tiny and unlikely to change - Over-abstraction would add complexity without benefit - You are in the earliest exploratory phase of a project ## Files in This Directory | File | Principle | |---|---| | [single-responsibility.md](single-responsibility.md) | Single Responsibility Principle | | [open-closed.md](open-closed.md) | Open/Closed Principle | | [liskov-substitution.md](liskov-substitution.md) | Liskov Substitution Principle | | [interface-segregation.md](interface-segregation.md) | Interface Segregation Principle | | [dependency-inversion.md](dependency-inversion.md) | Dependency Inversion Principle |