Development Patterns
Patterns and practices that emerged from building this learning project, particularly around using Claude Code effectively.
Code Organization Patterns
Test-Driven Implementation
Pattern: Write tests before implementation, always.
# 1. RED - Write failing test
def test_forward_pass():
network = Network([2, 4, 1])
output = network.forward([0, 1])
assert output.shape == (1,)
# 2. GREEN - Minimal implementation
def forward(self, x):
return np.zeros(1) # Just pass the test
# 3. REFACTOR - Proper implementation
def forward(self, x):
# Actual forward pass logic
...Why it works:
- Forces thinking about behavior before code
- Prevents over-engineering
- Provides safety net for refactoring
- Documents expected behavior
Atomic Commits
Pattern: One concept per commit, 1-3 files, < 500 lines.
Bad example:
git commit -m "Add visualizer" # 50 files, 3000 linesGood example:
git commit -m "Add Network forward pass" # 2 files: network.py, test_network.py
git commit -m "Add backward pass" # Same 2 files
git commit -m "Add visualization component" # 1 file: NetworkViz.tsxBenefits:
- Git history tells a story
- Easy to revert specific changes
- Clear what changed and why
- Reviewable by others (or future you)
Directory Structure by Feature
Pattern: Organize by what code does, not what it is.
Good structure:
src/
├── network/ # Neural network implementation
│ ├── Network.ts
│ └── functions.ts
├── components/ # UI components
│ ├── NetworkVisualization.tsx
│ └── ComputationPanel.tsx
└── hooks/ # State management
└── useTraining.tsWhy: Features evolve together; grouping them makes changes easier.
Claude Code Patterns
Commands vs Scripts
Pattern: Commands orchestrate, npm scripts execute.
Command file (commit.md):
# Commit Command
npm run commit:check && git commitPackage.json:
{
"scripts": {
"commit:check": "npm run lint:check && npm run test:check"
}
}Benefits:
- 87-91% token reduction
- Logic in version control (package.json)
- Fast execution
- Easy to test outside Claude
Socratic Interaction
Pattern: Ask Claude questions before requesting solutions.
Instead of:
"Implement backpropagation for my neural network"
Try:
"I'm implementing backprop. What do you think I need to compute first - the output error or the hidden layer error? Why?"
Benefits:
- Forces active thinking
- Identifies knowledge gaps
- Builds deeper understanding
- Claude's answer builds on your thinking
More on the Socratic approach →
Progressive Enhancement
Pattern: Build in layers, testing each before adding the next.
Example flow:
- Basic network (forward pass only) + tests ✓
- Add backprop + tests ✓
- Add training loop + tests ✓
- Add visualization + tests ✓
Anti-pattern:
- Try to build everything at once
- Debug a tangled mess
- Don't know what broke
Learning Patterns
Implement Before Reading
Pattern: Try coding a concept before reading the detailed explanation.
Flow:
- Basic understanding (e.g., "backprop uses chain rule")
- Try implementing it
- Get stuck / make mistakes
- NOW read the detailed explanation
- "Oh! That's what I was missing"
Why: Struggle creates context that makes explanations meaningful.
Visualize to Understand
Pattern: If you can't visualize it, you don't fully understand it.
Example:
- Understood gradient descent mathematically
- Built visualizer showing weight changes
- Realized weights don't change smoothly - they jump
- Deepened understanding beyond equations
Implication: Build visualization tools early.
Document While Learning
Pattern: Capture insights immediately, not at the end.
Tools:
LEARNINGS.md- Key insights- Git commit messages - Decisions made
- Code comments - Why, not what
/learncommand - Quick insight capture
Why: You'll forget the "aha moment" by tomorrow.
Testing Patterns
Test the Contract, Not the Implementation
Good test (tests behavior):
test('forward pass produces correct output shape', () => {
const net = new Network([2, 4, 1])
const output = net.forward([1, 0])
expect(output.length).toBe(1)
})Bad test (tests implementation):
test('forward pass uses sigmoid', () => {
// This couples test to implementation details
expect(net.activationFunction).toBe('sigmoid')
})Test Edge Cases Explicitly
Pattern: Explicitly test boundary conditions.
test('handles zero learning rate', ...)
test('handles very large learning rate', ...)
test('handles empty input', ...)
test('handles single training step', ...)Why: Edge cases are where bugs hide.
Workflow Patterns
Hygiene Before Commits
Pattern: Always run hygiene checks before committing.
npm run hygiene # lint + tests + markdown + git statusCatches:
- Failing tests
- Lint errors
- Broken markdown links
- Unstaged files
Benefit: Never commit broken code.
Checkpoint After Features
Pattern: After completing a feature, take a checkpoint.
git commit -m "feat: add forward pass"
npm test
npm run hygiene
git push
/retrospective # Document what you learnedWhy: Clear milestones make progress visible.
Use Todo Lists for Complex Work
Pattern: Break complex tasks into smaller steps, track progress.
Example:
- [ ] Implement forward pass
- [ ] Add tests for forward pass
- [ ] Implement backward pass
- [ ] Add tests for backward pass
- [ ] Visualize weight updatesTools: /todo command, GitHub Issues, simple markdown lists
Anti-Patterns to Avoid
Directory Navigation Chaos
Anti-pattern: Changing directories and forgetting to return.
cd web/src/components
# ... work ...
# Oops, next command runs in wrong directorySolution: Use absolute paths or return to root:
cd /path/to/root && npm run commandBulk Changes Without Testing
Anti-pattern: Making 10 changes, then testing all at once.
Problem: Can't identify which change broke things.
Solution: Test after each change:
# Make change 1
npm test
# Make change 2
npm testRetroactive Atomic Commits
Anti-pattern: Making many changes, then trying to split commits.
Problem: Hard to split logically after the fact.
Solution: Commit as you go:
# Implement feature
git add feature.py test_feature.py
git commit -m "add: feature X"
# Immediately continue
# Implement next feature
git add ...Context Overload
Anti-pattern: Long sessions without compacting context.
Problem: Lose track of earlier decisions, context window fills.
Solution:
- Compact every 20-30 interactions
- Use
/retrospectiveto save session insights - Start fresh session for new features
Validated Best Practices
TDD with Claude Code
Practice: Red-Green-Refactor cycle with AI assistance.
Validated: Implemented entire Network class this way - zero bugs on first integration.
Token-Efficient Commands
Practice: NPM script delegation for command logic.
Validated: 87-91% token reduction measured across 50+ command executions.
Progressive Complexity
Practice: Master simple before scaling to complex.
Validated: XOR network → understanding backprop → ready for transformers.
Pattern Evolution
These patterns aren't static - they evolve as the project grows:
Early: Manual testing, long command files Middle: Some automation, some commands Now: Full TDD, token-efficient commands, automated workflows
Lesson: Patterns improve through iteration. Don't try to perfect everything upfront.
Applying These Patterns
For Learning Projects
- Start with TDD from day one
- Build visualizations early
- Document insights immediately
- Commit atomically
For Production Code
- Same TDD approach
- More rigorous testing
- Stronger hygiene checks
- CI/CD automation
For Exploration
- Less strict testing
- More visualization
- Capture hypotheses and results
- Quick iteration cycles
Next Steps
Want to see these patterns in action?
These patterns continue to evolve. Check back for updates as the project grows.