Lab 2.4: Incremental Improvement
Module: 2.4 - Safe Refactoring | ← SlidesDuration: 1 hour Sample Project: node-express-mongoose-demo
Learning Objectives
By the end of this lab, you will be able to:
- Refactor code safely with test verification
- Make incremental changes (small steps)
- Improve readability without changing behavior
- Use tests as a safety net
Prerequisites
- Completed Labs 2.2 and 2.3
- Tests in place for the code you'll refactor
- Confidence in running the test suite
The Safe Refactoring Workflow
1. Verify tests pass (baseline)
2. Make one small change
3. Run tests
4. If green: commit and continue
5. If red: revert and try againSetup
# Navigate to the sample project
cd sample-projects/node-express-mongoose-demo
# Verify tests pass BEFORE starting
npm test
# Start Claude Code
claudeTask 1: Identify Code Smells
Time: 10 minutes
Find code that needs improvement.
Prompts to try:
What code smells exist in app/controllers/articles.js?Are there any functions with too many responsibilities?Find examples of duplicated code in this project.Common code smells:
- Long methods (>20 lines)
- Duplicated code
- Poor naming
- Deep nesting
- Magic numbers/strings
Success criteria:
- [ ] Identified 2-3 code smells
- [ ] Selected one to fix
Task 2: Refactor for Readability
Time: 15 minutes
Improve variable and function names.
Step 1: Run tests (baseline)
npm testStep 2: Improve naming
Rename the variables in this function to be more descriptive. Don't change any behavior.The function name 'proc' is unclear. Suggest a better name and rename it throughout the codebase.Step 3: Verify tests pass
npm testSuccess criteria:
- [ ] Names are clearer
- [ ] Tests still pass
- [ ] Behavior unchanged
Task 3: Extract Helper Functions
Time: 20 minutes
Break down complex functions.
Step 1: Identify extraction opportunities
This function is too long. What parts could be extracted into separate functions?Step 2: Extract one piece
Extract the [specific logic] into a separate helper function.Step 3: Run tests
npm testStep 4: Repeat for other pieces
Success criteria:
- [ ] At least one function extracted
- [ ] Tests pass after each extraction
- [ ] Main function is now shorter
Task 4: Remove Duplication
Time: 15 minutes
DRY up the codebase.
Step 1: Find duplication
Find duplicated code between the create and update functions.Step 2: Extract shared logic
Extract the common validation logic into a shared function used by both create and update.Step 3: Verify
npm testSuccess criteria:
- [ ] Duplication removed
- [ ] Shared function created
- [ ] Tests pass
Refactoring Techniques
| Technique | When to Use | Example |
|---|---|---|
| Rename | Unclear names | x → userId |
| Extract Function | Long methods | Pull out 10 lines into helper |
| Inline | Over-abstraction | Remove unnecessary wrapper |
| Move | Wrong location | Move util from controller to utils/ |
| Replace Magic | Hard-coded values | 86400 → SECONDS_PER_DAY |
The Golden Rule
Remember
"Refactoring is changing code without changing behavior."
After every change:
- Run tests
- If they pass, you're safe
- If they fail, you changed behavior (revert!)
Commit Strategy
Commit after each successful refactoring:
# After each green test run
git add .
git commit -m "Refactor: Extract validation helper from article controller"Small commits = easy rollback if something goes wrong.
Tips for Success
- One change at a time - Don't combine refactorings
- Run tests constantly - After every single change
- Commit frequently - Save your progress
- Keep behavior identical - If tests fail, you went too far
Common Refactoring Prompts
Rename this variable to something more descriptive.Extract the loop body into a separate function.Replace this magic number with a named constant.Simplify this nested if-else into an early return pattern.Red Flags (Stop Refactoring)
- Tests start failing unexpectedly
- You're adding new features (that's not refactoring)
- Changes are getting too large to track
- You've been refactoring for >30 min without committing
Stretch Goals
If you finish early:
- Refactor deeply nested conditionals into guard clauses
- Extract a configuration object from scattered magic values
- Improve error handling consistency
Deliverables
At the end of this lab, you should have:
- Cleaner, more readable code
- Smaller, focused functions
- Reduced duplication
- All tests still passing
- Clean commit history showing incremental changes
Next Steps
After completing this lab, move on to Lab 2.7: Modernization Mini-Project - the Day 2 capstone.