Back to Articles
OnboardingBeginner

Understanding the Codebase: A QE's Guide

How to navigate and understand a large codebase when starting as a QE

6 min read
...
onboardingcodebasecode-reviewlearning
Banner for Understanding the Codebase: A QE's Guide

Introduction

Understanding a large codebase can be overwhelming for new QEs. This guide provides systematic approaches to learn the codebase efficiently.

First Steps

1. Get the Big Picture

Before diving into code:

  • Review architecture diagrams
  • Understand the tech stack
  • Identify main components
  • Map out service dependencies

2. Run the Application

Experience the product as a user:

# Clone and run locally
git clone <repository-url>
cd <project>
./run-local.sh

What to observe:

  • User flows
  • Features and functionality
  • Data flow
  • Error handling

Directory Structure

Understand the project organization:

project/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   ├── controllers/  # API endpoints
│   │   │   ├── services/     # Business logic
│   │   │   ├── models/       # Data models
│   │   │   └── repositories/ # Database access
│   │   └── resources/
│   │       ├── application.yml
│   │       └── db/migrations/
│   └── test/
│       ├── unit/
│       ├── integration/
│       └── e2e/
├── pom.xml
└── README.md

Key Files to Review

  1. README.md - Project overview, setup instructions
  2. Configuration files - application.yml, .env, config/
  3. Build files - pom.xml, build.gradle, package.json
  4. API documentation - OpenAPI/Swagger specs
  5. Database schemas - migrations, ERD diagrams

Reading Code Effectively

Start with Entry Points

API Endpoints

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody OrderRequest request) {
        // Trace this flow
        Order order = orderService.createOrder(request);
        return ResponseEntity.ok(order);
    }
}

Follow the flow:

  1. Controller → Service → Repository → Database
  2. Note validation logic
  3. Understand error handling
  4. Identify dependencies

Main Business Flows

Focus on critical paths:

  • User registration/login
  • Core product features
  • Payment processing
  • Order management

Use Your IDE

Essential IDE Features:

  1. Go to Definition (Ctrl/Cmd + Click)

    • Jump to method implementations
    • Navigate through call chains
  2. Find Usages (Alt + F7)

    • See where methods are called
    • Understand method impact
  3. Class Hierarchy (Ctrl + H)

    • View inheritance structure
    • Understand polymorphism
  4. Search Everywhere (Double Shift)

    • Find classes, files, symbols
    • Quick navigation

Code Reading Techniques

Bottom-Up Approach

Start with small, isolated components:

// Start with utility classes
public class DateUtils {
    public static LocalDate parseDate(String dateStr) {
        // Simple, easy to understand
    }
}
 
// Move to models
public class Order {
    private String id;
    private List<OrderItem> items;
    // Understand data structures
}
 
// Then services
public class OrderService {
    // Understand business logic
}

Top-Down Approach

Start with high-level flows:

// Start with API endpoint
@GetMapping("/orders/{id}")
public Order getOrder(@PathVariable String id) {
    return orderService.getOrder(id);
    // Then trace down to implementation
}

Understanding Tests

Tests are excellent documentation:

Unit Tests

Show how classes work in isolation:

@Test
public void testOrderCalculation() {
    Order order = new Order();
    order.addItem(new Item("PROD1", 10.00, 2));
    
    assertEquals(20.00, order.getTotal());
    // Shows expected behavior
}

Integration Tests

Show how components interact:

@Test
public void testOrderCreationFlow() {
    // Shows complete flow
    OrderRequest request = createOrderRequest();
    Order order = orderService.createOrder(request);
    
    // Reveals validations, side effects
    verify(inventoryService).reserveStock(anyList());
    verify(paymentService).processPayment(any());
}

E2E Tests

Show user journeys:

@Test
public void testCompleteCheckoutFlow() {
    // Login
    // Add to cart
    // Checkout
    // Verify order created
    // Shows business flow from user perspective
}

Building Mental Models

Create Documentation

As you learn, document your understanding:

# Order Service
 
## Purpose
Handles order creation, management, and fulfillment.
 
## Key Components
- OrderController: API endpoints
- OrderService: Business logic
- OrderRepository: Database access
 
## Main Flows
1. Create Order
   - Validate items
   - Reserve inventory
   - Process payment
   - Create order record
   
## Dependencies
- InventoryService (stock check)
- PaymentService (process payment)
- NotificationService (send confirmation)
 
## Database Tables
- orders
- order_items
- order_status_history

Draw Diagrams

Visualize architecture:

User Request

OrderController

OrderService ----→ InventoryService
    ↓                     ↓
PaymentService      Check Stock
    ↓                     ↓
OrderRepository     Update Stock

Database

Asking Questions

What to Ask

  1. Architecture Questions

    • "What's the purpose of this service?"
    • "How does service X communicate with service Y?"
  2. Code Questions

    • "Why is this pattern used here?"
    • "What's the expected behavior in edge case X?"
  3. Testing Questions

    • "What's our testing strategy for feature X?"
    • "Where should I add tests for this component?"

How to Ask

  • Search first - Check docs, code comments, tests
  • Be specific - "How does X work?" rather than "I don't understand"
  • Show effort - "I looked at X and Y, but I'm unsure about Z"
  • Ask publicly - Others might have same question

Learning Strategies

1. Fix Bugs

Start with small bug fixes:

  • Understand the problem
  • Find the bug location
  • Trace the code flow
  • Fix and test

2. Write Tests

Writing tests forces understanding:

@Test
public void testNewScenario() {
    // Setting up test requires understanding:
    // - What data is needed
    // - How to create test data
    // - What the expected behavior is
}

3. Pair with Developers

  • Pair programming sessions
  • Code review participation
  • Architecture discussions

4. Read Pull Requests

Learn from others' code:

  • See coding patterns
  • Understand changes
  • Learn from reviews

Common Patterns to Look For

Design Patterns

  1. Repository Pattern - Data access abstraction
  2. Service Layer - Business logic separation
  3. Factory Pattern - Object creation
  4. Builder Pattern - Complex object construction
  5. Strategy Pattern - Algorithm variations

Architectural Patterns

  1. MVC/MVP/MVVM - UI architecture
  2. Layered Architecture - Separation of concerns
  3. Microservices - Distributed system
  4. Event-Driven - Asynchronous communication

Tools to Help

Code Exploration Tools

  1. IntelliJ IDEA - Excellent Java navigation
  2. VS Code - Good for multi-language projects
  3. SourceGraph - Code search and navigation
  4. GitLens - Git history and blame

Documentation Tools

  1. PlantUML - Create diagrams from text
  2. Draw.io - Visual diagramming
  3. Notion/Confluence - Knowledge base

Progress Tracking

Week 1

  • Understand project structure
  • Run application locally
  • Identify main components
  • Review README and docs

Week 2

  • Trace 3 main business flows
  • Read existing test suites
  • Fix first small bug
  • Document learnings

Week 3

  • Understand service dependencies
  • Write first test
  • Participate in code review
  • Ask clarifying questions

Month 1

  • Contribute to codebase
  • Understand testing strategy
  • Document one component
  • Help onboard next new hire

Conclusion

Learning a codebase takes time. Be patient, systematic, and don't hesitate to ask questions. Every developer was once in your position.

Resources

Part of the QE Hub Onboarding series. Next: Team Collaboration & Communication

Comments (0)

Loading comments...