Lesson 11: Common Workflows
Learning Objectives
After completing this lesson, you will be able to:
- Execute a complete feature development workflow
- Apply systematic bug fixing strategies
- Conduct effective code reviews with Claude
- Perform safe refactoring operations
- Quickly learn new codebases
- Practice test-driven development
Prerequisites
- Completed Lessons 1-10 - All previous tutorial content
- Real project - Apply workflows to your own code
- Git experience - Basic version control knowledge
Estimated Time: 35 minutes
Workflow 1: Feature Development
Developing new features is a common task. Here's how to do it efficiently with Claude.
Step-by-Step Process
1. Understand Requirements
You> I need to add user profile functionality. Users should be able to:
- View their profile
- Edit their information
- Upload a profile picture
- Change their password
Help me plan this feature.
Claude: [Enters plan mode, explores codebase, creates plan]
2. Explore Existing Code
You> Show me how other CRUD operations are implemented in this codebase.
Claude: [Uses Explore agent]
Found examples:
- src/api/products.py - Product CRUD
- src/models/user.py - User model
- Following this pattern for consistency
3. Design the Implementation
You> Based on the existing patterns, design the profile feature.
Claude: Architecture:
- Endpoint: GET/PUT /api/user/profile
- Controller: ProfileController
- Service: ProfileService
- Validation: ProfileSchema
- Storage: Update User model
4. Implement Incrementally
4a. Start with backend:
You> Create the profile endpoint following the product CRUD pattern.
Claude: [Creates src/api/profile.py]
✓ Created profile API endpoint
4b. Add validation:
You> Add validation for profile updates.
Claude: [Creates validation schemas]
✓ Added input validation
4c. Implement frontend:
You> Create a profile page component.
Claude: [Creates components/Profile.jsx]
✓ Created profile UI
4d. Add tests:
You> Write tests for the profile functionality.
Claude: [Creates tests/profile.test.js]
✓ Added comprehensive tests
5. Test and Refine
You> Run the tests and fix any issues.
Claude: [Uses Bash agent to run tests]
All tests passing. Found 3 edge cases to handle.
[Fixes edge cases]
6. Document
You> Document the new profile API endpoint.
Claude: [Updates docs/api.md]
✓ API documentation updated
7. Commit
You> /commit
Claude: feat(user): add user profile functionality
Implemented complete user profile management:
- Profile view and edit endpoints
- Profile picture upload
- Password change functionality
- Comprehensive validation and tests
✓ Committed
Feature Development Tips
✅ Break into small chunks
- Don't implement everything at once
- Test each piece before moving on
✅ Follow existing patterns
- Use Claude to find similar code
- Maintain consistency
✅ Test continuously
- Run tests after each change
- Use background tasks for long test runs
❌ Avoid:
- Implementing without planning
- Skipping tests
- Not following project conventions
Workflow 2: Bug Fixing
Bugs are inevitable. Claude helps you fix them systematically.
Bug Fixing Process
1. Understand the Bug
You> I'm getting this error:
"TypeError: Cannot read property 'map' of undefined"
in the dashboard component when it loads.
Claude: Let me investigate.
[Reads the component]
[Checks data flow]
[Identifies issue]
2. Reproduce the Bug
You> Help me reproduce this bug locally.
Claude: [Provides reproduction steps]
1. Navigate to /dashboard
2. Check browser console
3. Observe error when data is loading
3. Find Root Cause
You> What's causing this error?
Claude: Root cause analysis:
The useEffect fetches user data, but the component
renders before data arrives. The stats array is
undefined during initial render.
Fix: Add a loading state or default value.
4. Implement Fix
You> Fix this bug by adding a loading state.
Claude: [Edits Dashboard.jsx]
Added isLoading state and conditional render.
5. Verify Fix
You> Test the fix by running the app.
Claude: [Runs app, tests dashboard]
✓ Bug fixed. Dashboard now handles loading state.
6. Add Tests
You> Add tests to prevent regression.
Claude: [Adds test cases]
✓ Tests cover loading, error, and success states.
7. Document
You> Document this bug and its fix.
Claude: [Adds comment to code]
[Updates CHANGELOG.md]
8. Commit
You> /commit
Claude: fix(dashboard): handle loading state to prevent undefined error
Fixed TypeError by adding loading state check before
mapping over stats array. Regression tests added.
Fixes #123
Bug Fixing Tips
✅ Understand before fixing
- Don't just patch symptoms
- Find root cause with Claude's help
✅ Reproduce first
- Create reproduction steps
- Verify fix resolves the issue
✅ Add regression tests
- Prevent same bug from returning
- Document the expected behavior
❌ Avoid:
- Fixing without understanding
- Skipping testing after fix
- Not documenting the bug
Workflow 3: Code Review
Code reviews are essential for quality. Claude assists as an extra reviewer.
Code Review Process
1. Request Review
You> Review the changes in PR #45
Claude: [Fetches PR, analyzes changes]
2. Analyze Changes
Claude: Code Review for PR #45
OVERVIEW:
Adds payment processing feature with Stripe integration.
STRENGTHS:
✓ Well-structured code
✓ Good error handling
✓ Comprehensive tests
✓ Follows project patterns
CONCERNS:
⚠ API key should be in environment variables
⚠ Missing idempotency key for payments
⚠ No rate limiting on payment endpoint
⚠ SQL injection risk in transaction query
SECURITY ISSUES:
🔴 Critical: API key hardcoded
🔴 High: Unparameterized SQL query
RECOMMENDATIONS:
1. Move STRIPE_SECRET_KEY to .env
2. Use parameterized queries for database
3. Add idempotency keys for payments
4. Implement rate limiting
SPECIFIC CHANGES:
Line 45: Hardcoded API key
- const key = "sk_test_..."
+ const key = process.env.STRIPE_SECRET_KEY
Line 78: SQL injection risk
- const query = `SELECT * FROM transactions WHERE id = ${transactionId}`
+ const query = 'SELECT * FROM transactions WHERE id = $1'
+ await client.query(query, [transactionId])
Line 102: Add idempotency
+ stripe.paymentIntents.create({
+ ...params,
+ idempotency_key: uuidv4()
+ })
3. Discuss Issues
You: Point 2 about SQL injection - can you show me exactly
where that is and how to fix it?
Claude: [Shows exact line, provides fix]
Here's the vulnerable code at src/payment.js:78
[Shows before/after]
4. Request Changes
You: Help me write a review comment requesting these fixes.
Claude: Here's a suggested review comment:
@@ Great work on the payment feature! I have a few security
concerns that should be addressed before merging:
**Must Fix:**
1. Line 45: API key should be in environment variables
2. Line 78: SQL injection risk - use parameterized queries
**Should Fix:**
3. Add idempotency keys for payments
4. Add rate limiting
I can help implement these fixes if needed.
@@
5. Verify Fixes
You: They updated the PR. Re-review it.
Claude: [Re-analyzes]
✓ All security issues addressed
✓ Code looks good to merge
Code Review Tips
✅ Be constructive
- Suggest, don't dictate
- Explain why changes are needed
✅ Prioritize issues
- Separate must-fix from nice-to-have
- Flag security issues prominently
✅ Provide examples
- Show code examples
- Explain the reasoning
❌ Avoid:
- Being overly critical
- Nitpicking style issues
- Not explaining your reasoning
Workflow 4: Refactoring
Refactoring improves code without changing behavior.
Refactoring Process
1. Identify Refactoring Need
You> The UserService class is 500 lines and hard to maintain.
Help me refactor it.
Claude: [Analyzes the class]
Found 8 distinct responsibilities. Suggest splitting into:
- UserCreationService
- UserValidationService
- UserQueryService
- UserAuthenticationService
2. Plan Refactoring
You> Create a refactoring plan.
Claude: PLAN: Refactor UserService
Phase 1: Extract concerns
- Identify distinct responsibilities
- Create separate service classes
Phase 2: Move methods
- Migrate methods to new services
- Update imports
Phase 3: Update tests
- Modify tests for new structure
- Ensure coverage maintained
Phase 4: Verify
- Run all tests
- Check functionality unchanged
3. Execute Refactoring
You: Execute Phase 1
Claude: [Extracts UserCreationService]
[Extracts UserValidationService]
✓ Services extracted
4. Test Continuously
You> Run tests after Phase 1
Claude: [Runs tests]
✓ All tests passing
5. Continue Incrementally
You> Continue with Phase 2
Claude: [Moves methods]
[Updates imports]
✓ Phase 2 complete
You> Run tests
Claude: ✓ All passing
6. Verify Behavior
You> Verify the refactoring preserves behavior
Claude: [Compares before/after]
- Same public API
- Same test results
- Code is cleaner and more maintainable
✓ Refactoring successful
7. Document
You> Document the refactoring
Claude: [Updates architecture docs]
[Explains new structure]
8. Commit
You> /commit
Claude: refactor(user): split UserService into focused services
Broke down monolithic UserService into:
- UserCreationService
- UserValidationService
- UserQueryService
- UserAuthenticationService
Improves maintainability and follows single responsibility principle.
Refactoring Tips
✅ Test before and after
- Ensure tests pass before starting
- Verify behavior unchanged after
✅ Work incrementally
- Small steps
- Test after each step
✅ Preserve behavior
- Only change structure
- Don't change functionality
❌ Avoid:
- Big bang refactoring
- Changing behavior while refactoring
- Skipping tests
Workflow 5: Learning a New Codebase
Starting with unfamiliar code? Claude accelerates learning.
Learning Process
1. Get Overview
You> Give me an overview of this codebase
Claude: [Explores structure]
PROJECT OVERVIEW:
This is an e-commerce platform with:
- Frontend: React + TypeScript
- Backend: Node.js + Express
- Database: PostgreSQL
- Auth: JWT tokens
MAIN DIRECTORIES:
/src/api - API endpoints
/src/models - Data models
/src/services - Business logic
/tests - Test files
2. Understand Architecture
You> How does authentication work in this codebase?
Claude: [Uses Explore agent]
AUTHENTICATION FLOW:
1. User posts to /api/auth/login
2. AuthService validates credentials
3. JWT token generated
4. Token stored in localStorage
5. Subsequent requests include token
6. Middleware validates token
Files:
- src/api/auth.js - Login/logout endpoints
- src/services/AuthService.js - Auth logic
- src/middleware/auth.js - Token validation
3. Trace Data Flow
You> Trace how an order is created
Claude: [Traces through code]
ORDER CREATION FLOW:
1. Frontend: POST /api/orders (components/Checkout.jsx)
2. API: src/api/orders.js creates order
3. Service: OrderService.processOrder()
4. Database: Order model saves to DB
5. Payment: PaymentService.charge()
6. Response: Order confirmation returned
4. Identify Patterns
You> What are the common patterns in this codebase?
Claude: PATTERNS FOUND:
API Structure:
- All routes in /src/api/
- Each resource has routes.js, controller.js, service.js
Error Handling:
- Centralized error handler in middleware/errors.js
- Custom error classes in /utils/errors
Testing:
- Integration tests in /tests/integration/
- Unit tests mirror src structure
- Use jest and supertest
5. Ask Questions
You> I don't understand why there are two user services
Claude: EXPLANATION:
UserService - Core user CRUD operations
UserSessionService - Session/token management
They're separate because:
- UserService doesn't need auth logic
- UserSessionService has sensitive token operations
- Separation of concerns
- Easier to test independently
Learning Tips
✅ Start broad, then deep
- Get overview first
- Then dive into specific areas
✅ Trace real flows
- Follow actual user actions
- Understand data flow end-to-end
✅ Ask "why" questions
- Understand reasons behind design
- Learn architectural decisions
❌ Avoid:
- Trying to understand everything at once
- Not running the code
- Skipping documentation
Workflow 6: Test-Driven Development
TDD means writing tests before implementation.
TDD Cycle with Claude
1. Write Test First
You> Write a test for a user registration function
Claude: [Creates test]
describe('User Registration', () => {
it('should register a new user', async () => {
const user = await registerUser({
email: 'test@example.com',
password: 'SecurePass123!'
})
expect(user).toHaveProperty('id')
expect(user.email).toBe('test@example.com')
})
it('should reject invalid email', async () => {
await expect(
registerUser({ email: 'invalid', password: 'pass' })
).rejects.toThrow('Invalid email')
})
})
2. Run Test (Fail)
You> Run the test
Claude: [Runs test]
✗ Test fails: registerUser is not defined
3. Implement Minimum Code
You> Implement registerUser to make the test pass
Claude: [Creates implementation]
async function registerUser(data) {
// Validate email
if (!isValidEmail(data.email)) {
throw new Error('Invalid email')
}
// Create user
const user = await db.users.create({
email: data.email,
password: hash(data.password)
})
return user
}
4. Run Test (Pass)
You> Run tests again
Claude: ✓ Tests passing
5. Refactor
You> Refactor the implementation for better quality
Claude: [Refactors while keeping tests green]
✓ Code cleaner, tests still pass
6. Repeat
You> Add another test case for password validation
[Repeat cycle...]
TDD Tips
✅ Write one test at a time
- Small, focused tests
- Don't write all tests upfront
✅ Write minimal implementation
- Just enough to pass
- Refactor after
✅ Keep cycle short
- Red, Green, Refactor
- Minutes, not hours
❌ Avoid:
- Writing implementation first
- Skipping tests
- Making tests too complex
✅ Check Your Understanding
-
What's the first step in feature development?
- Start coding immediately
- Understand and plan requirements
- Write tests
- Commit changes
-
When bug fixing, what should you do first?
- Fix the bug
- Understand and reproduce the bug
- Write tests
- Commit the fix
-
What does TDD stand for?
- Test-Driven Development
- Test-Driven Design
- Testing During Development
- Test-Data Documentation
-
True or False: Refactoring changes the behavior of code.**
- True
- False - it only changes structure
-
What's the best way to learn a new codebase?
- Read every file
- Start broad with overview, then dive deep
- Rewrite from scratch
- Only look at tests
Answers: 1-b, 2-b, 3-a, 4-False, 5-b
Summary
In this lesson, you learned:
- Feature development - Plan, implement, test, document
- Bug fixing - Understand, reproduce, fix, test
- Code review - Analyze, provide feedback, verify
- Refactoring - Improve structure, preserve behavior
- Learning codebases - Overview, trace flows, ask questions
- TDD - Test first, implement, refactor
Next Steps
In Lesson 12: Tips, Tricks, and Best Practices, you'll learn:
- Communication strategies for better results
- Common mistakes to avoid
- Performance optimization techniques
- Cost management with
/stats - Team collaboration tips
- Troubleshooting guide
Further Reading
Continue to Lesson 12: Tips, Tricks, and Best Practices →