All chapters in this track
- 01Chapter 1: Why Patterns Exist — Vocabulary, Not a Checklist
- 02Chapter 2: Patterns and SOLID: How They Relate
- 03Chapter 3: Creational Patterns I: Factory Method & Abstract Factory
- 04Chapter 4: Creational Patterns II: Builder, Singleton, Prototype
- 05Chapter 5: Structural Patterns I: Adapter & Facade
- 06Chapter 6: Structural Patterns II: Decorator & Proxy
- 07Chapter 7: Structural Patterns III: Composite, Bridge & Flyweight
- 08Chapter 8: Behavioral Patterns I: Strategy & Template Method
- 09Chapter 9: Behavioral Patterns II: Observer & Mediator
- 10Chapter 10: Behavioral Patterns III: Command & Memento
- 11Chapter 11: Behavioral Patterns IV: State & Chain of Responsibility
- 12Chapter 12: Behavioral Patterns V: Iterator & Visitor
- 13Chapter 13: Anti-Patterns and Overuse: Recognizing "Pattern Fever"
- 14Chapter 14: How Dynamic and Functional Languages Solve These Problems Differently
- 15Chapter 15: Architectural Patterns I: MVC/MVVM & Layered/Hexagonal Architecture
- 16Chapter 16: Architectural Patterns II: Event-Driven Architecture & CQRS
- 17Chapter 17: Architectural Patterns III: The Repository Pattern
- 18Chapter 18: Recognizing Which Pattern Fits an Interview Design Prompt
Chapter 13 of 18
Chapter 13: Anti-Patterns and Overuse: Recognizing "Pattern Fever"
Why this matters
Every chapter in Parts 2 and 3 has repeated the same discipline: state the problem before naming the pattern, and confirm a real, current need before introducing one. This chapter exists because that discipline is easy to state and surprisingly hard to maintain — especially right after learning a new pattern, when everything starts to look like a nail for the hammer you just picked up. "Pattern fever" is common enough, and costly enough, to deserve explicit, named treatment.
What pattern fever looks like
[BEGINNER] Pattern fever is applying a design pattern because you recognize its shape or want to demonstrate knowledge of it, rather than because the problem in front of you actually has the shape that pattern solves. It's the single most common mistake among engineers who've just learned the pattern catalog — including, often, engineers reading a book exactly like this one for the first time.
A concrete example — an Abstract Factory built for a system with one, and only one, real "family":
// The codebase only ever runs against PostgreSQL. There is no second database, no plan for one.
interface DatabaseFactory {
createConnection(): Connection;
createQueryBuilder(): QueryBuilder;
}
class PostgresFactory implements DatabaseFactory {
createConnection(): Connection { return new PostgresConnection(); }
createQueryBuilder(): QueryBuilder { return new PostgresQueryBuilder(); }
}
// PostgresFactory is the only implementation that has ever existed, or is planned to exist.
// Every new engineer has to learn the DatabaseFactory abstraction to understand code that,
// in reality, only ever talks to one database.
The fix isn't a different pattern — it's recognizing there's no real problem here yet: new PostgresConnection() called directly, wherever needed, is simpler and exactly as capable for the system that actually exists today. The abstraction can be introduced when a second database is a real requirement — which, per Chapter 3, is also when it will be easiest to design correctly, informed by the actual shape of the second real case rather than a guess.
Why pattern fever happens, and why it's not really about knowledge
[SENIOR INSIGHT] It's tempting to think pattern fever is a junior-engineer problem that experience cures automatically. It's closer to the opposite: pattern fever often gets worse right after someone genuinely learns the catalog well, because recognizing a pattern's applicable shape becomes easy — and using that recognition muscle feels like exercising skill. The actual skill this book has tried to build, chapter after chapter, isn't "recognize when a pattern's shape fits" — it's "recognize when a pattern's shape fits, and then ask whether the problem is real and current, and say no when it isn't." The second half is the harder half, and it doesn't come for free with pattern knowledge — it has to be practiced deliberately, which is exactly why this book has repeated it in every single chapter rather than stating it once.
The cost side of the ledger, made concrete
[IN PRACTICE] Every pattern in this book has a real cost, even when applied correctly — extra classes, extra indirection, a steeper on-ramp for new team members. That cost is usually described in the abstract ("added complexity"), but it's worth stating concretely what it means day to day:
| Cost | What it actually looks like |
|---|---|
| Navigation overhead | A new engineer has to open 3-4 files (interface, factory, concrete implementations) to understand what, in a simpler design, would be one function |
| Onboarding friction | Explaining "why does this codebase have a WidgetFactory" to every new hire, when the honest answer is "there's only ever been one kind of widget" |
| False signal | Unjustified patterns imply future flexibility that was never actually built or tested for — the "second implementation" a Strategy interface implies might not actually work correctly if one ever gets built, because it was never exercised |
| Review friction | Reviewers spend time evaluating whether a pattern's structure is correct, instead of evaluating whether the underlying logic is correct — indirection adds surface area to review, not just to write |
None of this means patterns are bad — every one of them, applied to its real problem, pays this cost back with a genuine benefit (Chapters 3–12 showed this repeatedly). The point is that the cost is real and constant, while the benefit is conditional on the problem actually existing — which is exactly why "state the problem first" has been this book's one repeated rule.
A companion failure mode: pattern blindness
[IN PRACTICE] The opposite failure also happens, and is worth naming even though it's rarer in engineers who've just finished a patterns book: pattern blindness — not recognizing a pattern's applicable shape even when a real, current problem clearly has it, and re-solving the same recurring problem from scratch each time with ad hoc code, missing the chance to use a well-understood, well-communicated shape. The discipline from this chapter cuts both ways: check that the problem is real before applying a pattern, but also actually apply the pattern once you've confirmed it is.
Common mistakes
- Applying a pattern to demonstrate knowledge of it — in code review, in a take-home exercise, or in production code — rather than because the specific problem calls for it. Reviewers experienced with this exact tendency will (correctly) read it as a negative signal, not a positive one, echoing the OOP book's Chapter 18 point about interview design rounds.
- Confusing "this could theoretically vary" with "this needs to vary now." Nearly anything could theoretically need a second implementation someday — that's not sufficient justification; the bar is a real, current, or clearly imminent need (Chapter 1).
- Refusing to remove an unjustified pattern once recognized, out of a sense that the work already invested in it shouldn't be "wasted" — sunk cost reasoning applied to code structure. An unjustified
Factorydiscovered in review should be simplified, not preserved because it exists. - Treating this chapter as license to never use patterns. Pattern blindness is a real, if less common, failure in the opposite direction — the goal is matching the tool to the actual problem, in both directions.
Checklist: diagnosing pattern fever
- For every pattern in your own code, ask "what specific, current problem does this solve?" If you can't answer concretely, that's the signal.
- Count real implementations, not hypothetical ones. An interface with exactly one implementation and no near-term second one in sight is a pattern-fever candidate.
- Ask a colleague unfamiliar with the code to explain what a suspected over-applied pattern does. If they need several files and significant time to understand what turns out to be simple logic, that's the navigation-overhead cost made visible.
- When reviewing your own recently-learned-pattern enthusiasm specifically, apply extra scrutiny — this is precisely the period (right after learning a pattern well) when the urge to apply it everywhere is strongest and least reliable.
- Don't let sunk cost prevent simplification. An unjustified pattern found in review should be flagged and simplified, regardless of how much work went into building it.
Discussion / interview questions
-
"What is 'pattern fever,' and why is it common even among engineers who understand patterns well?" Strong answer: Applying a pattern because its shape is recognized, not because the problem needs it; common specifically right after learning the catalog well, because pattern-recognition becomes easy and satisfying to exercise, while the harder discipline of saying "no, not needed here" isn't automatic.
-
"How would you identify an over-applied pattern during a code review?" Strong answer: Look for interfaces/abstractions with exactly one real implementation and no concrete near-term second one, and ask whether removing the abstraction would make the code simpler with no loss of current capability.
-
"What's the concrete, day-to-day cost of an unjustified design pattern, beyond 'it's more complex'?" Strong answer: Names specifics — extra files to navigate for a simple operation, onboarding friction explaining unused flexibility, review overhead evaluating structure instead of logic, and false signal (an untested "extension point" that may not actually work when a real second case eventually arrives).
-
"Is it ever a mistake to not use a pattern? What would that look like?" Strong answer: Yes — "pattern blindness": re-solving a problem with genuine, current pattern-shaped complexity from scratch with ad hoc code, missing the benefit of a well-understood, well-communicated existing solution shape.
-
"You inherit a codebase with an unjustified Abstract Factory (one real implementation, no plans for a second). What would you do?" Strong answer: Confirm there's genuinely no near-term second implementation planned (check with the team/roadmap, not just the code), then propose simplifying it to direct construction — not preserving it out of sunk-cost reasoning, and not ripping it out unilaterally without checking context first.
Chapter summary / cheat sheet
- Pattern fever: applying a pattern because its shape is recognized, not because a real, current problem needs it — common and often worsens right after learning the catalog well.
- The cost of an unjustified pattern is concrete, not abstract: navigation overhead, onboarding friction, review overhead, and false signal about tested flexibility.
- Pattern blindness (the opposite failure — not recognizing a real pattern-shaped problem) is real too; the goal is matching tool to problem in both directions.
- The one-question test repeated throughout this book: "what specific, current problem does this pattern solve here?" — if you can't answer concretely, that's pattern fever.