The Pattern Selection Framework
Pattern selection is where engineers most often lose composure — too many patterns, too many trade-offs, too much taste.
Introduction
Pattern selection is where engineers most often lose composure — too many patterns, too many trade-offs, too much taste. This lesson gives you a five-step framework you can apply in a code review, a design doc, or an interview: Smell → Force → Candidates → Trade-offs → Decision.
When practiced, this framework turns a thirty-minute debate into a five-minute answer. It also produces the artifact every senior team needs: a documented decision with rationale, alternatives considered, and a kill-switch.
The story
In a staff-engineer panel interview, a candidate was given a 200-line file and asked: "What patterns would you apply?" Instead of naming patterns, she walked through Smell → Force → Candidates → Trade-offs → Decision in eight minutes, named only one pattern (Strategy), and explained why she rejected Factory and State. She got the offer. The framework — not the pattern name — was the signal.
The business problem
Without a shared selection framework, pattern decisions become expensive opinion battles:
- Recency bias: engineers apply whichever pattern they read about last week.
- Design review gridlock: three engineers propose three patterns; no shared vocabulary to converge.
- Undocumented decisions: ADRs name the pattern but not the alternatives rejected — future teams cannot tell if thinking was thorough.
- Over-application: multiple patterns ship in one refactor because nobody ran a structured comparison.
- Interview failure: candidates name patterns without smells, forces, or trade-offs — instant junior signal.
The problem teams faced
Teams without a selection framework hit the same dysfunction repeatedly:
- Engineers reach for patterns by name instead of by fit to a documented force.
- Design reviews become taste debates — "I don't like this" with no structured rebuttal.
- ADRs lack an "alternatives considered" section — decisions look arbitrary in hindsight.
- Junior engineers copy patterns from tutorials without diagnosing the smell first.
Understanding the topic
Five steps. Every pattern decision. No shortcuts on steps 3 and 5.
- 1. Smell — what concrete symptom triggered this? (Switch on Type, Shotgun Surgery…).
- 2. Force — what varies? What stays stable? Show git or roadmap evidence.
- 3. Candidates — list two or three patterns that fit; refuse to decide with only one option.
- 4. Trade-offs — files added, learning curve, performance, test complexity — make it explicit.
- 5. Decision — pick one, pick none, document rationale, and define a kill-switch.
Internal architecture
The framework in one view — print this for design reviews:
SMELL → Switch on Type in NotificationRouter (42 branches)FORCE → Channel varies (email/SMS/push); git: 38/47 commitsCANDIDATES → Strategy (per channel) | Observer (fan-out) | MediatorTRADE-OFFS → Strategy: 3 files, clear | Observer: 5 files, decoupled| Mediator: overkill for 3 channels todayDECISION → Strategy now; revisit Observer if channels exceed 6KILL-SWITCH → If fan-out subscribers exceed 4, re-evaluate Observer
Visual explanation
Three diagrams make the framework operational. The first is the five-step pipeline — your default for every pattern decision. The second shows what a complete ADR artifact contains. The third walks candidate comparison when two patterns both seem to fit.
Informative example
Worked example — applying all five steps to a notification router with a growing switch statement:
// SMELL: Switch on Type — 42 branches, merge conflicts every sprintfunction notify(user: User, event: Event, channel: string) {switch (channel) {case "email": return emailService.send(user, event);case "sms": return smsGateway.send(user, event);case "push": return pushProvider.send(user, event);// ... 39 more cases added over 2 years}}// FORCE: git log → 38/47 commits touched channel-specific logic// CANDIDATES: Strategy | Observer | Mediator// TRADE-OFFS:// Strategy — 3 impl files + interface; clearest for "pick one channel"// Observer — decouples publishers; worth it at 6+ subscribers, not at 3// Mediator — coordination overhead; no multi-party routing yet// DECISION: Strategy per channel; kill-switch at 6 channels or 4 subscribersinterface ChannelNotifier {send(user: User, event: Event): Promise<void>;}class NotificationRouter {constructor(private channels: Record<string, ChannelNotifier>) {}notify(user: User, event: Event, channel: string) {return this.channels[channel]?.send(user, event);}}
# ADR-014: Strategy for notification channels## Context- Smell: Switch on Type (42 branches) in NotificationRouter- Force: channel-specific delivery logic varies; 38/47 git commits confirm## Alternatives considered| Option | Pros | Cons | Verdict ||-----------|-------------------|-------------------------|-----------|| Strategy | Clear, 3 files | One interface per axis | ✅ Chosen || Observer | Decoupled fan-out | 5 files for 3 channels | Deferred || Mediator | Central routing | Overkill today | Rejected || None | Zero indirection | Merge conflicts continue| Rejected |## DecisionStrategy per channel. Revisit Observer when subscribers exceed 4.## Kill-switchRe-evaluate if: (a) channels > 6, or (b) events fan out to 4+ handlers per publish.
ADR template — paste into every pattern PR:
Execution workflow
Name the smell
Use Fowler's vocabulary — Switch on Type, Shotgun Surgery, Feature Envy. No smell, no pattern.
Real-world use
Stripe, Shopify, and Atlassian design reviews require "alternatives considered" in ADRs. Google's design doc template mandates a "decisions and trade-offs" section. Amazon's PR/FAQ process forces explicit rejection of options not chosen. The framework is not academic — it is the entry ticket to senior engineering culture. The vocabulary scales from a five-line refactor to a multi-quarter migration; only the evidence weight changes.
Production case study
A platform team rewrote their notification system. Three engineers each proposed a different pattern in standup — no convergence after two days:
- Process: tech lead ran the five-step framework in a 45-minute meeting with a shared doc.
- Smell: Switch on Type plus Shotgun Surgery across 8 files for one new channel.
- Outcome: Observer + Strategy combo chosen with documented trade-offs; ADR referenced in 3 later refactors.
- Timeline: implementation took 2 sprints; debate took 45 minutes instead of 2 days.
- Lesson: structured steps convert taste debates into decisions the whole team can defend.
Trade-offs
- Pro — Speed: structured discussion replaces open-ended debate.
- Pro — Inheritance: future engineers get rationale, not just code.
- Pro — Review quality: reviewers challenge specific steps, not personal preference.
- Con — Overhead: do not use for one-line refactors or rename-only PRs.
- Con — Mechanical use: filling templates without thought is worse than ad-hoc.
- Con — Writing culture: teams that skip ADRs will find step 5 painful at first.
Decision framework
- Always use on PRs introducing or removing a pattern in production code.
- Always use in design docs touching more than two modules.
- Always use in post-incident reviews when structure contributed to failure.
- Skip on throwaway scripts, prototypes, and one-off migrations.
- Skip when consensus exists and a current ADR already covers the case.
- Escalate to RFC when the decision spans teams or quarters — same five steps, heavier evidence.
Best practices
- Write the smell on the whiteboard before anyone is allowed to name a pattern.
- Require two candidates minimum — assign defenders so each option gets a fair hearing.
- Every ADR needs a kill-switch with a measurable trigger, not "revisit someday."
- Use a decision matrix when three candidates score close on trade-offs.
- "None for now" is a valid decision — document why and what evidence would change it.
- Link ADRs from PR descriptions so reviewers see the full framework, not just the diff.
Anti-patterns to avoid
- Jumping to step 5 (Decision) without listing alternatives — recency bias wins.
- Choosing Observer because "it's modern" without a fan-out force in git log.
- ADRs that name the pattern but skip rejected alternatives — looks thoughtful, isn't.
- Running the full framework on a variable rename — process for process's sake erodes trust.
Common mistakes
- Treating candidates as rubber-stamp options when you've already decided.
- Kill-switches without metrics — "revisit later" is not a kill-switch.
- Forgetting step 2 evidence — force without git or roadmap data is guesswork.
- Combining multiple pattern decisions in one ADR — one force, one decision per ADR.
Debugging tips
- When a past pattern decision feels wrong, re-run steps 1–2 — the force may have moved.
- If reviewers disagree, compare filled frameworks side by side — disagreement is usually on step 4.
- ADR archaeology: read rejected alternatives before deleting a pattern — context may still apply.
- Spike the disputed candidate for 2 hours when step 4 trade-offs are tied — data beats debate.
Optimization strategies
- Keep a team ADR template in the repo — reduce step 5 friction to copy-paste.
- For interviews, practice the framework on a 200-line file in under 8 minutes.
- Batch pattern ADRs in refactor sprints — one meeting, multiple forces, separate ADRs.
- Review kill-switch triggers quarterly — auto-schedule re-evaluation in the issue tracker.
Common misconceptions
- Many developers believe senior engineers just "know" the right pattern. In reality, they run a mental version of this framework in minutes — smell, force, reject alternatives.
- Many developers believe ADRs are bureaucracy. In reality, a one-page ADR saves hours of re-debate when the team turns over.
- Many developers believe more candidates means indecision. In reality, two options minimum proves you considered trade-offs.
- Related: Change-point analysis feeds step 2; code smells feed step 1; Rule of Three gates timing.
Advanced interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1AdvancedQuestionWalk through selecting a pattern for a 500-line god class.+
Answer
Follow-up
2AdvancedQuestionWhat does a good ADR contain?+
Answer
Follow-up
3AdvancedQuestionHow do you handle disagreement on pattern selection?+
Answer
Follow-up
4AdvancedQuestionWhen is 'no pattern' the correct decision?+
Answer
Follow-up
5IntermediateQuestionStrategy or State for a switch on order status?+
Answer
Follow-up
Summary
You can now select patterns with a repeatable five-step framework, write ADRs with alternatives and kill-switches, and walk an interviewer through a 200-line file in eight minutes. Tell the staff-engineer interview story — Strategy chosen, Factory and State rejected with reasons. If you can do that without notes, you own this lesson and the Foundations module.