Skip to content

SOLID Principles#

flowchart LR
  S([S - Single Responsibility])
  O([O - Open / Closed])
  L([L - Liskov Substitution])
  I([I - Interface Segregation])
  D([D - Dependency Inversion])
  S --> O --> L --> I --> D

  classDef p fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
  class S,O,L,I,D p;

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class S,O,L,I,D service;

Five principles for object-oriented design. Follow them and your classes stay small, intent-revealing, and easy to change.

classDiagram
  direction LR
  class SRP {
    +Single Responsibility
    +A class has ONE reason to change
    +Split classes by axis of change
  }
  class OCP {
    +Open / Closed
    +Open for extension
    +Closed for modification
    +Use interfaces + polymorphism
  }
  class LSP {
    +Liskov Substitution
    +Subtypes must be usable wherever
    +base type is expected
    +preserve contracts
  }
  class ISP {
    +Interface Segregation
    +Clients shouldn't depend on
    +methods they don't use
    +Many small interfaces - one fat one
  }
  class DIP {
    +Dependency Inversion
    +Depend on abstractions
    +not concretions
    +High-level modules don't import
    +low-level details
  }
  SRP --> OCP
  OCP --> LSP
  LSP --> ISP
  ISP --> DIP

Each principle in one sentence#

Principle Tells you to... Smell when violated
S ingle Responsibility give each class one reason to change "And"-named classes; methods touch unrelated state
O pen / Closed extend behaviour by adding new types, not editing old ones sprawling if (type == ...) chains
L iskov Substitution make subclasses substitutable for their base type if (instanceof Square) workarounds; thrown UnsupportedOperationException
I nterface Segregation split fat interfaces so clients only see what they use classes implementing 20 methods to satisfy 1 caller
D ependency Inversion depend on abstractions, inject concretions from outside new HttpClient() inside a domain class

Worked example: OCP#

Before (violates OCP - every new shape needs an edit to area()):

class AreaCalculator {
  double area(Shape s) {
    if (s instanceof Circle)    return Math.PI * ((Circle)s).r * ((Circle)s).r;
    if (s instanceof Rectangle) return ((Rectangle)s).w * ((Rectangle)s).h;
    throw new IllegalArgumentException();
  }
}

After (open for extension - add a new shape, no edits to existing code):

interface Shape { double area(); }
class Circle implements Shape    { public double area() { return Math.PI * r * r; } }
class Rectangle implements Shape { public double area() { return w * h; } }
class AreaCalculator {
  double area(Shape s) { return s.area(); }
}

How SOLID shows up in this site#

Most of the LLD-flavoured designs (Parking Lot, Elevator, Vending Machine, ATM, Chess, Logger) rely on: - SRP to split state / pricing / dispatch into separate classes. - OCP + LSP to add new vehicle types / piece types / payment methods without editing the core. - DIP to inject payment gateways, storage backends, time sources.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
LLD OOP pillars encapsulation, abstraction, inheritance, polymorphism oop-pillars
LLD SOLID principles SRP / OCP / LSP / ISP / DIP solid-principles
LLD Error handling exceptions vs Result, error boundaries error-handling

Quick reference#

Why it matters#

SOLID is the canonical sanity check for OO designs. It doesn't guarantee good design - but its violations are reliable red flags.

Per-principle gotchas#

  • SRP: "responsibility" = axis of change. A User class that handles persistence and password hashing has two axes of change (DB schema vs auth policy).
  • OCP: hardest to apply preemptively. Apply it when you've actually seen the second variation, not the first.
  • LSP: contracts cover pre/post-conditions, invariants, and exceptions - not just method signatures. The classic counterexample: a Square extending Rectangle breaks the post-condition "setWidth doesn't change height".
  • ISP: in Go-style languages, interfaces are implicit and small by convention. In Java/C#, do it explicitly.
  • DIP: pair with DI. Dependencies passed in via constructor / setters / framework - never new inside business logic.

SOLID vs other acronyms#

Acronym Stands for Focus
SOLID five OO principles class-level design
DRY Don't Repeat Yourself duplication
KISS Keep It Simple, Stupid over-engineering
YAGNI You Aren't Gonna Need It speculative features
CUPID Composable, Unix-philosophy, Predictable, Idiomatic, Domain-based systems-oriented alternative to SOLID

Refs#

  • Robert C. Martin: "Clean Architecture" (2017) - full SOLID treatment.
  • Uncle Bob's original 2002 papers on each principle.
  • Dan North: "CUPID - for joyful coding" (2022) - alternative framing.

FAQ#

What does SOLID stand for?#

Single responsibility, Open-closed, Liskov substitution, Interface segregation, and Dependency inversion. Five OO design principles popularised by Robert C. Martin.

What is the single responsibility principle in plain English?#

A class should have one reason to change. If two different stakeholders would request changes to the same class, split it along that seam.

What is the open-closed principle?#

A module should be open for extension but closed for modification. You add new behaviour by introducing a new type, not by editing existing code.

What is Liskov substitution principle?#

Subtypes must be usable wherever the base type is expected without surprising callers. Violations show up as code that needs to know the concrete subclass.

Are SOLID principles still relevant?#

Yes. They are guidelines, not laws, and they map well onto modern dependency injection, hexagonal architecture, and even functional design with interface-shaped types.

Further reading#

Curated, high-credibility sources for going deeper on this topic.