SOLID

is a set of five design principles introduced by Robert C. Martin (Uncle Bob) to make software designs more maintainable, scalable, and robust. It stands for:

  1. Single Responsibility Principle (SRP)

  2. Open/Closed Principle (OCP)

  3. Liskov Substitution Principle (LSP)

  4. Interface Segregation Principle (ISP)

  5. Dependency Inversion Principle (DIP)

Single Responsibility Principle (SRP)

Definition: A class (or struct) should have one and only one reason to change.

Before applying SRP:

type Report struct{}

func (r Report) GenerateReport() {
    fmt.Println("Generating report...")
}

func (r Report) SaveToFile(filename string) {
    fmt.Println("Saving report to file:", filename)
}

After applying SRP:

Explanation: Each struct has a single responsibility now: one generates the report, and another saves it.

Open/Closed Principle (OCP)

Definition: Software entities should be open for extension but closed for modification.

Before OCP:

After OCP (Extensible with interfaces):

Explanation: New shapes can be added by implementing the Shape interface without modifying AreaCalculator.

Liskov Substitution Principle (LSP)

Definition: Subtypes must be substitutable for their base types without altering the correctness of the program.

Before LSP:

After LSP:

Explanation: The Bird interface represents general behavior, and specific birds implement it in ways that don't break substitutability.

Interface Segregation Principle (ISP)

Definition: Clients should not be forced to depend on methods they do not use.

Before ISP:

After ISP:

Explanation: Interfaces are split based on specific needs, so RobotWorker doesn’t need to implement Eat().

Dependency Inversion Principle (DIP)

Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions.

Before DIP:

After DIP:

Explanation: The Service depends on the Database interface, not specific implementations. This makes it easy to switch databases.

Summary

Principle
Description
Example

SRP

One responsibility per class/module

Separate report generation and saving logic

OCP

Open for extension, closed for modification

Add new shapes without changing the calculator

LSP

Subtypes replace base types without breaking behavior

Penguins swim instead of fly

ISP

Split interfaces to avoid unused methods

Separate Work and Eat interfaces

DIP

Depend on abstractions, not concretions

Service uses Database interface, not specific DB

These principles make code cleaner, more maintainable, and easier to test.

Last updated