The core move
Do not start with pattern names. Start with pain in your code.
A pattern is useful only when it removes repeated change, branching, coupling, or setup confusion. If the code is simple and stable, leave it simple.
What to look for
Pattern-shaped problems usually show up after you add the second or third feature. One hackathon screen is often too early. Three similar payment, login, or notification paths are better signals.
Your job in this lesson is to mark candidates, not fix them yet. Later lessons will teach specific patterns.
Scan your code
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done
A real smell
This is not bad code because it works. It is a candidate because every new provider changes the same function.
Do not jump to a solution yet. Write down the pain first.
function pay(provider, amount) {
if (provider === "upi") {
return sendUpiCollect(amount);
}
if (provider === "card") {
return chargeCard(amount);
}
if (provider === "wallet") {
return debitWallet(amount);
}
throw new Error("Unknown provider");
}
// Pain: adding netbanking means editing this function again.
// Candidate: behavior changes by provider.Name chasing
A common beginner move is to say, “I will use Factory, Strategy, Observer, Singleton,” before reading the code. That creates extra classes and weak README explanations.
Recruiters and maintainers care more about why you changed the design. Pattern names help only after the problem is clear.
Use AI carefully
You can ask an AI tool to review one file for design smells. Paste the file and ask for repeated branching, repeated setup, and tight coupling only.
Check the answer yourself. Reject suggestions that require big rewrites, paid services, or patterns that solve problems your app does not have.
Prompt:
Review this file for pattern-shaped refactor candidates.
Only list:
1. Repeated branching
2. Repeated object setup
3. Tight coupling to external services
For each item, quote the exact lines and explain the change pain.
Do not suggest a pattern name yet.Candidate note
Start a small note in your repo. It becomes proof that you made design choices, not random rewrites.
Keep each note short. One problem, one reason, one possible direction.
refactor-notes.md
Candidate 1: Payment provider branching
File: src/payments/pay.js
Pain: Adding a new provider means editing pay() and retesting all providers.
Signal: Same if-else block chooses behavior by provider.
Possible direction: Move provider-specific behavior out of this function.
Decision later: Choose a pattern only after checking the rest of the app.Do this now
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done