SOLID, Critically
Each principle by the problem it addresses, a real example, a real misuse and a counterexample. Useful heuristics, not laws, and the difference matters.
Five heuristics about the cost of change, collected over two decades, of genuinely unequal quality — and none of them a law.
"A coherent reason to change" is the useful reading. "One thing" is the one that produces a hundred classes that each do nothing.
Prefer designs where common, observed variation can be added without rewriting stable core logic. Not "never modify existing code" — that reading builds plugin machinery for variation that never arrives.
A subtype must keep every promise callers rely on from the abstraction. It is a behavioural contract, not a fact about inheritance syntax — and it is the sharpest of the five.
A consumer should depend on the smallest contract that serves it. That is a statement about coupling, not a rule that interfaces must be small.
The idea is which module declares the interface. The cargo cult is a container, an interface per class, and the same dependency graph as before.
An interface per class, layers that pass data unchanged, abstractions with one implementation — and the critiques of SOLID that are strong enough to deserve a straight answer.