"Leave the campground cleaner than you found it."
Always leave code better than you found it. Make incremental improvements when you touch a file.
Constraint: Improvements must remain surgical and within blast radius.
Build systems where components are independent and changes don't ripple unexpectedly.
Orthogonal (math): Lines at right angles — changing one doesn't affect the other. In software: Components are independent and non-overlapping.
- Changes are localized (less debugging)
- Easy to test in isolation
- Components are reusable
- Less coupling = less complexity
- Easier to understand and maintain
These guidelines bias toward caution over speed. For trivial tasks, use judgment.
Don't assume. Don't hide confusion. Surface tradeoffs.
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them — don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
Minimum code that solves the problem. Nothing speculative.
- No features beyond what was asked
- No abstractions for single-use code
- No unrequested configurability
- No error handling for impossible scenarios
- If you write 200 lines and it could be 50, rewrite it
Ask:
Would a senior engineer say this is overcomplicated?
If yes, simplify.
Touch only what you must. Clean up only your own mess.
When editing existing code:
- Don't improve unrelated code
- Don't refactor things that aren't broken
- Match existing style
- If you notice unrelated dead code, mention — don't delete
✅ Boy Scout improvements are allowed ONLY within your blast radius
When your changes create orphans:
- Remove imports/variables/functions your changes made unused
- Don't remove pre-existing dead code unless asked
Traceability test:
Every changed line must trace to the user's request.
Define success criteria. Loop until verified.
Transform tasks into verifiable goals:
- "Add validation" → write failing tests → make pass
- "Fix bug" → reproduce → fix → verify
- "Refactor X" → tests pass before and after
For multi-step tasks:
- [Step] → verify: [check]
- [Step] → verify: [check]
- [Step] → verify: [check]
- Change amplification
- Shotgun surgery
- Tight coupling
- Duplicate logic
- Cascading changes
If you see these, pause and reconsider design.
Keep unrelated responsibilities separate.
Rules:
- One module → one reason to change
- Business logic separate from I/O
- UI separate from data logic
- Validation separate from persistence
Create focused, minimal interfaces.
Rules:
- Prefer small capability interfaces
- Avoid "fat" interfaces
- Consumers depend only on what they use
- Optional features → separate interfaces
Don't hardcode dependencies — inject them.
Rules:
- Services depend on abstractions
- Allow test doubles/mocks
- Avoid hidden globals
- Default deps allowed but overridable
Prefer events when multiple consumers react to one action.
Use when:
- Multiple side effects
- Cross-domain reactions
- Future extensibility expected
Avoid when: simple direct call is clearer.
Rules:
- Don't store derivable data
- Compute instead of duplicate
- Avoid sync fields
- Keep schemas normalized
Only within touched areas.
- Remove dead code (within scope)
- Fix linting issues
- Improve unclear naming
- Add type annotations
- Extract magic numbers
- Simplify complex logic
- Add realistic error handling
- Update outdated comments
- Fix formatting
- Remove unused imports caused by your change
- Consolidate duplication you introduced
❌ Massive unrelated refactors ❌ Change behavior without tests ❌ Fix everything in the file ❌ Breaking changes without tests ❌ Premature optimization ❌ Cross-module rewrites for "purity" ❌ Introduce new coupling while cleaning code
- Read file
- Note issues
- Run linter
- Implement feature/fix
- Write tests
- Within blast radius only
- Full test suite
- Type check
- Lint clean
Include boy scout improvements in commit.
- Single clear purpose
- No shared internal state
- Changes rarely cascade
- Testable in isolation
- Each endpoint does ONE thing
- Parameters independent
- Minimal return shape
- No hidden coupling
- Single source of truth
- Computed values not stored
- No duplicate information
- Schema changes localized
- Well-defined interfaces
- Events for loose coupling where appropriate
- Dependencies injected
- Components replaceable independently
Good test: can test component in isolation.
🚫 If tests require half the system → design likely non-orthogonal.
Ask yourself:
- Can I change this independently?
- Can I test this in isolation?
- Is this the only place with this logic?
- If I remove this, what breaks?
- Will this change ripple unexpectedly?
- Keep improvements in same commit
- Focus on blast radius
- Prioritize readability
- Always run full test suite
- Small improvements > perfect refactors
- Independence over cleverness
Incremental improvement, not perfection. Small improvements compound over time. Every file touched is an opportunity. Orthogonality preserves long-term velocity.
Orthogonality = Independence
Separate concerns. Minimize coupling. Maintain single source of truth. Design for isolated change.
The more orthogonal your system, the more flexible and maintainable it becomes.