Skip to main content

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

  1. What's the first step in feature development?

    • Start coding immediately
    • Understand and plan requirements
    • Write tests
    • Commit changes
  2. When bug fixing, what should you do first?

    • Fix the bug
    • Understand and reproduce the bug
    • Write tests
    • Commit the fix
  3. What does TDD stand for?

    • Test-Driven Development
    • Test-Driven Design
    • Testing During Development
    • Test-Data Documentation
  4. True or False: Refactoring changes the behavior of code.**

    • True
    • False - it only changes structure
  5. 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