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
setWidthmethod breaks the Square’s logic.
