Prefer duplication over wrong abstraction. Wait for real patterns.
When to Use
- Creating shared utilities or components.
- Deciding whether duplication is acceptable.
- Reviewing a bloated helper or facade.
- Refactoring code with many options, flags, or conditionals.
Goal
Keep code easy to change. Use abstractions only when they reduce real complexity.
Rules
- Do not abstract before 3 real uses unless there is strong domain reason.
- Similar shape is not enough; behavior must match.
- Prefer clear duplication over parameter-heavy helpers.
- Avoid abstractions that need new flags for every caller.
- Inline bad abstractions before designing new ones.
- Test concrete behavior, not abstraction cleverness.
Abstract When
- Same behavior appears in 3+ places.
- Requirements are stable.
- Callers need the same change together.
- Name and API are obvious.
- Abstraction removes more complexity than it adds.
Do Not Abstract When
- There are only 1-2 uses.
- Requirements are still changing.
- Callers need different behavior.
- API needs many optional parameters.
- Junior developers must learn the wrapper and the underlying tool.
- Manual edits across files would be simpler.
Facade Rule
Use a facade when it hides real complexity or enforces a useful constraint.
Good facade examples:
- Date picker hiding calendar, localization, keyboard, and accessibility logic.
- Button enforcing design system variants.
Skip facades for simple HTML or one-off styling.
Fixing Wrong Abstractions
- Inline the abstraction into each caller.
- Delete unused branches in each caller.
- Keep temporary duplication.
- Compare current use cases.
- Re-extract only stable shared behavior.
Review Questions
- What are the actual callers?
- Do they change for the same reason?
- Which parameters exist only to satisfy one caller?
- Would duplication be clearer?
- Can we delete the abstraction and make code easier?
Output
## Abstraction Review
- Decision: [keep/duplicate/inline/re-extract]
- Evidence: [callers and behavior]
- Risk: [coupling, churn, or none]
- Change: [smallest safe next step]