Speculative Abstraction
also called Premature Abstraction, Anticipatory Design
Structure added for variation that has not occurred - paying certain indirection now for a benefit that depends on a guess about the future.
Speculative abstraction is an interface with one implementation, a configuration option nobody sets, a plugin point nobody uses, a factory for a single type. Each was added because the author anticipated variation.
The cost is immediate and certain: an extra layer to trace, more types to understand, a longer path from a request to the code doing the work. The benefit is contingent on a prediction, and predictions about which axis will vary are usually wrong — code typically varies along an axis nobody anticipated, so the abstraction must be reworked anyway and the indirection was pure cost.
Why it is so common
It resembles good practice. The principles that describe well-factored code — depend on abstractions, be open to extension — read as instructions to abstract, and applying them in advance feels like foresight rather than speculation.
It is also asymmetric in visibility: the cost is spread thinly across everyone who reads the code afterwards, while the perceived benefit accrues to the person adding it.
The discipline
Introduce the abstraction when the second case arrives. Two implementations tell you where the seam belongs; one implementation and an imagination do not.
This is not an argument against abstraction — it is an argument about timing. The same interface, added when the second case exists, is well-placed and clearly justified. Added before, it is a guess.
Implementation patterns
- The removal test. For each layer: if the business problem stayed identical but we rebuilt today, would this exist? No means it is accidental complexity.
- The change test. What change does this indirection make cheaper, and how likely is that change? A hypothetical change means certain cost and uncertain benefit.
- Prefer duplication over the wrong abstraction. Two similar implementations are easy to unify once the real commonality is visible; a wrong abstraction is hard to unpick and tends to accumulate special cases.
- Delete unused extension points as routine maintenance, rather than preserving them because someone might need them.
Industry example
Codebases that use many design patterns and are harder to understand than simpler equivalents are the visible form of this. The symptom is that following one operation means opening nine files, most of which delegate: factories where construction is trivial, strategies with one implementation, observers where a direct call would do.
The same failure appears at architectural scale — a message broker introduced for a workflow a database table would serve, a service boundary drawn for a scaling requirement nobody has measured, event sourcing adopted for a history requirement nobody has stated.
The tell in every case is what happens when you propose deletion. Proposing to remove genuine essential complexity produces a regulator or a customer requirement; proposing to remove speculative abstraction produces an argument about best practice.
Failure scenarios
- Interfaces with one implementation maintained for years.
- Configuration for variation that never occurs, which still must be tested and documented.
- Plugin architectures with no plugins.
- Generalising from one example, producing an abstraction shaped entirely by the first case.
- Over-correcting into refusing all abstraction, which produces duplication that genuinely does need unifying.
Trade-offs
Some anticipation is correct. Where the second case is committed — a signed contract with a second provider, a regulatory requirement taking effect next year — designing for it is planning rather than speculation.
The distinction is evidence: a named, dated, committed second case justifies the abstraction; a plausible future does not. Asking "what would tell me this is necessary, and do I have it?" is the question that separates the two.
Interview question
"A colleague adds an interface with one implementation, arguing we will need a second provider eventually. How do you respond — and what would change your answer?"