Fix Claude Code Wrong Abstraction Level (2026)
Claude Code either over-abstracts simple things (factory pattern for a function) or under-abstracts reusable things (copy-pasting instead of extracting). Here’s how to calibrate it.
The Problem
Over-abstraction:
- Interface + abstract class + factory for a single implementation
- Generic type system for 2 concrete types
- Plugin architecture for 1 plugin
Under-abstraction:
- Copy-pasting the same 20 lines across 5 files
- Inline logic that’s used in 4 places
- No shared types for data used across modules
Root Cause
Claude Code doesn’t reason about usage frequency. It abstracts based on pattern recognition (“this looks like it should be a factory”) rather than actual reuse needs (“how many callers will there be?”).
The Fix
## Abstraction Calibration
### When to Abstract (create shared code)
- The same logic appears in 3+ places
- A function has 5+ callers
- A data shape is used in 3+ files
- An external service is called from 3+ places
### When NOT to Abstract
- Code is used in 1-2 places (inline it or keep it local)
- The "abstraction" would be a thin wrapper around an existing API
- The only reason to abstract is "it might be reused later"
### Abstraction Decision Framework
Before creating an abstraction, answer:
1. How many callers exist RIGHT NOW? (not "might exist")
2. Would the callers be simplified by the abstraction?
3. Is the abstraction more complex than the inlined version?
If <3 callers, or the abstraction is more complex, don't abstract.
CLAUDE.md Rule to Add
## Abstraction Level Rule
- ≤2 uses: inline or keep local to the file
- 3+ uses: extract to a shared utility with a clear interface
- NEVER abstract "for future flexibility" — abstract when you have evidence of reuse
- When you see copy-pasted code in the codebase, suggest extraction but don't do it unless asked
Verification
Task 1: “Add date formatting to the orders page”
- Over-abstracted: creates DateFormatter class, FormatStrategy, locale registry
- Correct: uses inline
date.toLocaleDateString()if it’s used once
Task 2: “The same validation logic is copied in 5 endpoints”
- Under-abstracted: adds it inline again in a 6th place
- Correct: suggests extracting to
src/utils/validation.tsand refactoring the 5 existing uses
| Related: Karpathy Simplicity First | Fix Overcomplicating | Claude Code Best Practices |
See Also
Try it: Browse 155+ skills in our Skill Finder.
Implementation Details
When working with this in Claude Code, pay attention to these practical details:
Project configuration. Add specific instructions to your CLAUDE.md file describing how your project handles this area. Include file paths, naming conventions, and any patterns that differ from common defaults. Claude Code reads CLAUDE.md at the start of every session and uses it to guide all operations.
Testing the setup. After configuration, verify everything works by running a simple test task. Ask Claude Code to perform a read-only operation first (like listing files or reading a config) before moving to write operations. This confirms that permissions, paths, and tools are all correctly configured.
Monitoring and iteration. Track your results over several sessions. If Claude Code consistently makes the same mistake, the fix is usually a more specific CLAUDE.md instruction. If it makes different mistakes each time, the issue is likely in the project setup or toolchain configuration.
Troubleshooting Checklist
When something does not work as expected, check these items in order:
- CLAUDE.md exists at the project root — run
ls -la CLAUDE.mdto verify - Node.js version is 18+ — run
node --versionto check - API key is set — run
echo $ANTHROPIC_API_KEY | head -c 10to verify (shows first 10 characters only) - Disk space is available — run
df -h .to check - Network can reach the API — run
curl -s -o /dev/null -w "%{http_code}" https://api.anthropic.com(should return 401 without auth, meaning the server is reachable) - No conflicting processes — run
ps aux | grep claude | grep -v grepto check for stale sessions