SOLID Principles: Documented Failure Modes and Decision Rules
Named, sourced critiques of SOLID in production - the Ousterhout/Martin method-length debate, the 'interface hell' failure signature for over-applied ISP, canonical real-world over-abstraction cases (Spring's AbstractSingletonProxyFactoryBean, FizzBuzzEnterpriseEdition), and the performance cost of default indirection.
Assume the reader knows what each SOLID letter stands for. This document is the part that isn't in the textbook explanation: where each principle documentedly goes wrong in production, the concrete signature that identifies it, and canonical, citable real-world examples - not hypothetical ones.
SRP / method-decomposition: the same failure as Clean Code's function-length dispute
SOLID's Single Responsibility Principle and Clean Code's "keep functions small" advice come from the same intellectual lineage and share the same documented failure mode: John Ousterhout's direct, archived debate with Robert Martin (github.com/johnousterhout/aposd-vs-clean-code) argues that decomposing a class/function past the point where each piece has independent meaning does not reduce complexity - it relocates it into a larger number of interfaces the reader must now learn and trace between. Ousterhout's rule: make the unit deep (small interface, real functionality behind it) before making it short. Applied to SRP specifically: "one reason to change" is not a license to fragment a cohesive concept into a class per verb. See Clean Code Principles for the full sourced debate.
Failure signature: a change to one piece of business behavior now requires touching 4+ classes that only ever collaborate with each other, in a fixed order, with no independent reuse. That's over-fragmented SRP, not correctly-scoped SRP.
ISP: "interface hell" is a real, named failure mode, not a hypothetical
The common over-application of Interface Segregation is mechanical splitting: dividing an interface by method regardless of whether the split reflects a real difference between callers. The documented distinction (lindbakk.com, "Interface hell: The Interface Segregation Principle doesn't mean 'Add interfaces everywhere'"): two methods that every single caller always uses together are a cohesive unit, not a fat interface. Splitting them produces two interfaces that only ever appear together at every call site - that isn't segregation, it's fragmentation with extra ceremony. ISP applies only when the honest answer to "does every client need every method" is no.
The same source reports the concrete, recognizable cost of this failure: new engineers on an over-segregated codebase spending on the order of a week tracing through interface indirection before finding the line of code that actually does something. That is the tell - if onboarding time is dominated by interface-hopping rather than reading logic, ISP has been over-applied.
Decision rule: Before splitting an interface, name the two (or more) distinct client populations that need different subsets. If you cannot name them - if it's "in case someone someday needs less" - you are fragmenting, not segregating.
DIP / OCP: the cost of default indirection is measurable, not just aesthetic
"Program to an interface" as a default, applied uniformly rather than at genuine architectural seams, has the same performance failure mode documented for polymorphism in Clean Code's dispute with Casey Muratori (see Clean Code Principles): virtual dispatch through an interface blocks compiler optimizations that require knowing the concrete type, and the cost compounds in hot paths, independent of the dispatch call itself. This is the same mechanism, applied to DIP-style seams instead of Clean Code's class hierarchies. Dependency-injection frameworks add their own separate, measurable cost: container/reflection-based wiring increases process startup time, which matters for cold-start-sensitive deployments (serverless, CLI tools invoked per-request) in a way "clean architecture" advice rarely accounts for.
Decision rule: Reserve interface-based indirection for boundaries that are (a) genuinely swappable in practice - not hypothetically - or (b) needed to fake the dependency in a test. Do not apply it as a default style choice inside a single implementation's internals, and do not put it on a profiler-verified hot path without a measurement justifying the cost.
Canonical, citable examples of SOLID/pattern over-application
Use these when a design review needs a concrete reference point instead of an abstract warning:
AbstractSingletonProxyFactoryBean- a real, shipped Spring Framework class (not satire), frequently cited in engineering discussion (Hacker News threads on "everything wrong with Java in one class name") as the observable end state of unrestrained DIP/OCP layering in a widely used production framework: proxies wrapping factories wrapping singletons wrapping abstractions, each layer individually justified by a principle, the composition understandable by almost no one on first read.- FizzBuzzEnterpriseEdition (
github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition) - a runnable, widely-referenced satirical codebase that implements FizzBuzz using the full SOLID + Gang-of-Four pattern stack simultaneously (factories, strategies, visitors, dependency injection, interfaces for everything). Used in real code reviews as the reference point for "this is what applying every principle at once, regardless of whether the problem needs it, looks like." Point to it directly when a PR is over-abstracting a genuinely small problem. - Steve Yegge, "Execution in the Kingdom of Nouns" (2006,
steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html) - the canonical, widely cited essay naming the cultural pattern of turning every verb into a noun-plus-interface (Factory,Proxy,Enabler,Strategy) to satisfy OOP orthodoxy, "littering the landscape with verbal garbage" even when a plain function would do. Predates SOLID's current popularity but describes exactly the DIP/OCP-driven over-noun-ing that produces the two examples above.
Decision Table: SOLID Rigor by Context
| Situation | Rigor | Rationale |
|---|---|---|
| Core business domain logic, changes frequently | High | Highest ratio of benefit to indirection cost |
| Infrastructure/adapters (HTTP clients, DB drivers) | Medium | More stable; framework conventions often already provide the seam |
| One-off scripts / data pipelines | Low | Short lifespan; indirection cost is pure loss |
| Public SDKs / libraries | Very high | Breaking changes are the most expensive failure mode there is |
| Hot path confirmed by profiler | Low - flatten it | Virtual dispatch cost is measured, not assumed; see DIP/OCP section above |
| Interface with exactly one real implementation and no test-double need | Low - skip the interface | Speculative seam; see YAGNI guidance |
Related Documentation
- Clean Code Principles - the Ousterhout/Martin debate and the Muratori/Martin performance debate this document builds on.
- DRY, KISS, and YAGNI - when a DIP-style seam is a real boundary versus speculative generality.
- Clean Architecture
- Design Patterns - Creational
Sources
- Ousterhout/Martin debate transcript -
github.com/johnousterhout/aposd-vs-clean-code- deep-vs-shallow decomposition argument, applied here to SRP. - Lindbakk, "Interface hell: The Interface Segregation Principle doesn't mean 'Add interfaces everywhere'" -
lindbakk.com/blog/interface-hell-interface-segregation-principle-doesnt-mean-adding-interfaces-everywhere- the cohesive-unit-vs-fat-interface distinction and the onboarding-cost anecdote. - Casey Muratori, "'Clean' Code, Horrible Performance" -
computerenhance.com/p/clean-code-horrible-performance- virtual-dispatch/compiler-optimization cost mechanism, applied here to DIP/OCP. - Hacker News discussion, "AbstractSingletonProxyFactoryBean is abstract" -
news.ycombinator.com/item?id=2807908- real Spring Framework class used as citable over-abstraction example. - FizzBuzzEnterpriseEdition -
github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition- runnable reference example of full-stack SOLID/GoF over-application. - Steve Yegge, "Execution in the Kingdom of Nouns" -
steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html- the noun-oriented-design critique underlying both examples above.