SOLID Principles

Overview

SOLID is an acronym for five design principles intended to make software designs more understandable, flexible, and maintainable.

Core Concepts

  • S – Single Responsibility Principle (SRP): A class should have one, and only one, reason to change. It should perform only one job.
  • O – Open/Closed Principle (OCP): Software entities should be open for extension, but closed for modification.
  • L – Liskov Substitution Principle (LSP): Objects of a superclass should be replaceable with objects of its subclasses without breaking the application.
  • I – Interface Segregation Principle (ISP): No client should be forced to depend on methods it does not use. Split large interfaces into smaller, specific ones.
  • D – Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions.

Code Examples

// DIP Example: Depend on an interface, not a concrete class
interface Logger { log(msg: string): void; }

class FileLogger implements Logger { log(msg: string) { /* write to file */ } }
class ConsoleLogger implements Logger { log(msg: string) { console.log(msg); } }

class UserService {
    constructor(private logger: Logger) {} // Depends on abstraction
    create() { this.logger.log("User created"); }
}

const service = new UserService(new ConsoleLogger());

Use Cases

  • Enterprise Software: Where systems must evolve over years without requiring a total rewrite.
  • Testable Code: DIP makes it easy to swap real services for “Mocks” during unit testing.

Gotchas

  • Over-Abstraction: Applying SOLID too rigidly to a small project can lead to “Interface Soup”, where you spend more time creating interfaces than writing logic.
  • Misinterpreting LSP: Just because a Square “is a” Rectangle doesn’t mean it should inherit from it if the Rectangle’s setWidth method breaks the Square’s logic.

Related Notes