Every team has a class like this. It started as twenty clean lines that emailed a receipt. Two years later it formats, routes, retries, logs and persists across four channels, and nobody wants to touch it — because touching it for one reason risks breaking the other four.
Meet the system
Here is the NotificationService we will fix — the running example for this whole
series. Read it once and note how many different reasons it has to change.
Peel it apart, one principle at a time
Flip each principle and watch the tangle resolve. Turn on all five and you have clean architecture — the same behaviour, but every reason to change now lives in exactly one place.
The five, at a glance
- S · Single Responsibility — A module should have one, and only one, reason to change. Kills the God class. Deep dive → coming soon.
- O · Open/Closed — Software entities should be open for extension, but closed for modification. Kills the edit-the-core-for-every-channel switch. Deep dive → coming soon.
- L · Liskov Substitution — Subtypes must be substitutable for their base types. Kills the subtype that breaks its parent’s promise. Deep dive → coming soon.
- I · Interface Segregation — Clients should not be forced to depend on methods they do not use. Kills the fat interface. Deep dive → coming soon.
- D · Dependency Inversion — High-level modules should not depend on
low-level modules. Both should depend on abstractions. Kills
new EmailSender()buried in policy. Deep dive → coming soon.
Check yourself
References
- Robert C. Martin — Design Principles and Design Patterns (2000), and the individual SRP / OCP / LSP / ISP / DIP articles.
- Robert C. Martin — Clean Architecture (2017), SOLID chapters.
- Robert C. Martin — Agile Software Development, Principles, Patterns, and Practices (2002).
Discussion
Loading the conversation…
Discussion
Loading the conversation…