Chapter 06
SOLID principles
The five principles behind maintainable object-oriented code, each with the smell that tells you it is being broken.
Single Responsibility Principle
Also called SRP
- What
- A class or module should have one reason to change: it answers to one actor or concern.
- Why
- Changes stay local; a tax rule change should not risk the PDF layout.
- Example
- Smell: an
Invoiceclass that calculates totals, renders HTML and emails itself. Split into calculator, renderer and sender.
Open/Closed Principle
Also called OCP
- What
- Code should be open for extension but closed for modification: add behaviour by adding new code, not by editing working code.
- Why
- Every edit to a tested class risks breaking existing behaviour.
- Example
- Smell: a
switchon payment type that grows with each new method. Fix: aPaymentinterface with one class per method.
Liskov Substitution Principle
Also called LSP
- What
- Any subtype must be usable wherever its base type is expected, without surprising the caller.
- Why
- Polymorphism only works if subclasses keep the promises of their parent.
- Example
- Smell: a
Squaresubclass ofRectanglewhosesetWidthalso changes the height, breaking code that sets both.
Interface Segregation Principle
Also called ISP
- What
- Many small, focused interfaces beat one large one; no class should be forced to implement methods it does not use.
- Why
- Fat interfaces create empty or throwing methods and couple clients to things they never call.
- Example
- Smell: a
Workerinterface withcode(),test()anddeploy(), where a tester implementsdeploy()by throwing.
Dependency Inversion Principle
Also called DIP
- What
- High-level policy should depend on abstractions, and low-level details should implement them; neither depends directly on the other.
- Why
- Business logic can then be tested with fakes and moved to a new database or vendor without rewrites.
// Policy owns the interface
interface OrderRepo { save(o: Order): Promise<void>; }
class PlaceOrder {
constructor(private repo: OrderRepo) {}
}
// Details implement it
class MongoOrderRepo implements OrderRepo { /* ... */ }