Skip to content

SOLID Principle

SOLID Principle

The Five Principles of Object-Oriented Design

1. Overview of SOLID, the Five Core Principles of Object-Oriented Design for Software Resilient to Change

    flowchart LR
    A["Highly coupled design<br/>vulnerable to change<br/>spaghetti code"] --"Applying the<br/>5 SOLID principles"--> B["Separation of responsibilities,<br/>extensibility, substitutable structure"] --"Improved<br/>maintainability & reusability"--> C["Software architecture<br/>resilient to change"]

    style A fill:#FFEBEE,stroke:#D32F2F,color:#000
    style B fill:#E3F2FD,stroke:#1976D2,color:#000
    style C fill:#E8F5E9,stroke:#388E3C,color:#000
  

Definition: Five core principles of object-oriented design established by Robert C. Martin — Single Responsibility (SRP), Open/Closed (OCP), Liskov Substitution (LSP), Interface Segregation (ISP), and Dependency Inversion (DIP) — that guide the design of software that is easy to maintain and extend by lowering coupling and increasing cohesion.

Characteristics: (Mutually reinforcing principles) Each principle is independent yet mutually reinforcing, forming the foundation of clean architecture, DDD, and design patterns. (Indicator of code smell) Violations of these principles manifest as code smells and lead to technical debt. (Cost-benefit judgment) Excessive application can increase complexity, so a cost-benefit judgment is required.


2. Core Structure of the Five SOLID Principles

A. SRP, OCP, LSP

    flowchart TD
    subgraph R1[" "]
        direction LR
        SRP["SRP<br/>Single Responsibility Principle<br/>A class should have<br/>only one reason to change"]
        OCP["OCP<br/>Open/Closed Principle<br/>Open for extension,<br/>closed for modification"]
        LSP["LSP<br/>Liskov Substitution Principle<br/>A subclass must be fully<br/>substitutable for its parent class"]
    end

    style SRP fill:#E3F2FD,stroke:#1976D2,color:#000
    style OCP fill:#F3E5F5,stroke:#7B1FA2,color:#000
    style LSP fill:#FFF3E0,stroke:#F57C00,color:#000
    style R1  fill:none,stroke:none
  

SRP — Single Responsibility Principle

CategoryContent
PrincipleA class should have only one responsibility (one reason to change)
Violation exampleUserService handles authentication, email sending, and DB storage all at once
Compliance approachSplit into AuthService, EmailService, and UserRepository
EffectMinimizes the scope of change impact, clarifies test units

OCP — Open/Closed Principle

CategoryContent
PrincipleNew functionality should be addable (extensible) without modifying existing code
Violation exampleRepeated conditional branching such as if (type == "A") ... else if (type == "B") ...
Compliance approachApply the Strategy or Template Method pattern based on interfaces/abstract classes
EffectAdding new requirements doesn’t require modifying existing code, preventing regression bugs

LSP — Liskov Substitution Principle

CategoryContent
PrincipleA subclass must honor the contract (preconditions/postconditions) of its parent class
Violation exampleA Square subclassing Rectangle cannot independently change width and height (behavioral change)
Compliance approachVerify the IS-A relationship, design inheritance without behavioral distortion
EffectEnables safe use of polymorphism, prevents unexpected runtime errors

B. Technical Characteristics of ISP and DIP

    flowchart TD
    subgraph R1[" "]
        direction LR
        ISP["ISP<br/>Interface Segregation Principle<br/>Clients should not depend<br/>on methods they don't use"]
        DIP["DIP<br/>Dependency Inversion Principle<br/>High-level modules should not<br/>depend directly on low-level modules"]
    end

    style ISP fill:#FFEBEE,stroke:#D32F2F,color:#000
    style DIP fill:#E8F5E9,stroke:#388E3C,color:#000
    style R1  fill:none,stroke:none
  

ISP — Interface Segregation Principle

    flowchart LR
    subgraph BAD["ISP Violation (Fat Interface)"]
        direction TB
        FI["IWorker<br/>work / eat / sleep"]
        R["Robot"] --> FI
        H["Human"] --> FI
    end

    subgraph GOOD["ISP Compliance (Segregated Interfaces)"]
        direction TB
        IW["IWorkable<br/>work"]
        IE["IEatable<br/>eat"]
        IS["ISleepable<br/>sleep"]
        R2["Robot"] --> IW
        H2["Human"] --> IW
        H2 --> IE
        H2 --> IS
    end

    style BAD  fill:#FFEBEE,stroke:#D32F2F,color:#B71C1C
    style GOOD fill:#E8F5E9,stroke:#388E3C,color:#1B5E20
  
CategoryContent
PrincipleDon’t force clients to depend on methods they don’t use
Violation exampleIWorker includes work(), eat(), and sleep() together, forcing Robot to implement eat()
Compliance approachSegregate into IWorkable, IEatable, and ISleepable interfaces
EffectRemoves unnecessary dependencies, minimizes the scope of interface-change impact

DIP — Dependency Inversion Principle

    flowchart LR
    subgraph DIP_GOOD["DIP Compliance (Depending on Interfaces)"]
        direction TB
        UC["UseCase<br/>high-level module"] --> RI["Repository Interface<br/>abstraction"]
        IMPL["JpaRepositoryImpl<br/>low-level implementation"] --> RI
    end

    style UC   fill:#1E3A5F,stroke:#1E3A5F,color:#fff
    style RI   fill:#E3F2FD,stroke:#1976D2,color:#000
    style IMPL fill:#E8F5E9,stroke:#388E3C,color:#000
  
CategoryContent
PrincipleBoth high-level and low-level modules should depend on abstractions (interfaces)
Violation exampleOrderService directly creates and invokes MySQLOrderRepository
Compliance approachDefine an OrderRepository interface, swap implementations via dependency injection (DI)
EffectNo changes to business logic when switching technology stacks (MySQL → MongoDB), easy to swap in mocks for testing

3. Expected Benefits and Application of the SOLID Principles

PrincipleKey Expected BenefitPractical Application
SRPMinimizes scope of change impact, improves testabilityLimit class size, check responsibility separation based on method count
OCPExtends functionality without modifying existing codeUse Strategy/Decorator patterns, design plugin architectures
LSPEnsures safe polymorphism, prevents runtime errorsVerify IS-A relationships, favor composition over inheritance
ISPRemoves unnecessary dependencies, improves interface cohesionSeparate interfaces by role when designing APIs
DIPEases technology changes and swapping in test mocksUse a dependency injection (DI) container such as Spring