The five, in one line each
| Principle | Plain English | Smell when violated | |
|---|---|---|---|
| S | Single Responsibility | A module should have one reason to change, meaning one actor it serves | A "Manager" class edited by every team |
| O | Open/Closed | Add behaviour by adding code, not editing tested code | A growing switch (type) in five places |
| L | Liskov Substitution | Subtypes must honour the parent's contract | if (x instanceof Square) checks |
| I | Interface Segregation | Many small, client-specific interfaces | Implementations throwing NotImplemented |
| D | Dependency Inversion | High-level policy depends on abstractions; details implement them | Business logic imports the DB driver |
Open/Closed in practice
interface BankAdapter {
detect(text: string): boolean;
parse(text: string): Transaction[];
}
const adapters: BankAdapter[] = [new HdfcAdapter(), new SbiAdapter(), new IciciAdapter()];
export const parse = (text: string) =>
(adapters.find(a => a.detect(text)) ?? fail("Unknown bank")).parse(text);This is exactly how the bank-statement analyser is structured: one adapter per bank format behind a common interface (Open/Closed + Strategy), with the core ledger normalisation depending only on the interface (Dependency Inversion).
Don't over-apply
SOLID is a set of heuristics, not laws. An interface with exactly one implementation that will never change is just indirection. Apply the principles where change is likely, and use YAGNI everywhere else.
Sources & further learning
Videos, courses, docs and books I recommend for this topic.
Related topics
Coupling, Cohesion & Separation of Concerns
High cohesion inside a module, loose coupling between modules — the single most important property of a maintainable architecture.
Hexagonal Architecture (Ports & Adapters)
Put the business core at the centre and talk to the outside world — HTTP, DB, queues, third-party APIs — only through ports (interfaces) implemented by swappable adapters.
Clean Architecture
Concentric rings — entities, use cases, interface adapters, frameworks — with one rule: source-code dependencies only point inward.