Understanding the Codebase: A QE's Guide
How to navigate and understand a large codebase when starting as a QE
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.shWhat to observe:
- User flows
- Features and functionality
- Data flow
- Error handling
Navigating the Codebase
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.mdKey Files to Review
- README.md - Project overview, setup instructions
- Configuration files - application.yml, .env, config/
- Build files - pom.xml, build.gradle, package.json
- API documentation - OpenAPI/Swagger specs
- 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:
- Controller → Service → Repository → Database
- Note validation logic
- Understand error handling
- 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:
-
Go to Definition (Ctrl/Cmd + Click)
- Jump to method implementations
- Navigate through call chains
-
Find Usages (Alt + F7)
- See where methods are called
- Understand method impact
-
Class Hierarchy (Ctrl + H)
- View inheritance structure
- Understand polymorphism
-
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_historyDraw Diagrams
Visualize architecture:
User Request
↓
OrderController
↓
OrderService ----→ InventoryService
↓ ↓
PaymentService Check Stock
↓ ↓
OrderRepository Update Stock
↓
DatabaseAsking Questions
What to Ask
-
Architecture Questions
- "What's the purpose of this service?"
- "How does service X communicate with service Y?"
-
Code Questions
- "Why is this pattern used here?"
- "What's the expected behavior in edge case X?"
-
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
- Repository Pattern - Data access abstraction
- Service Layer - Business logic separation
- Factory Pattern - Object creation
- Builder Pattern - Complex object construction
- Strategy Pattern - Algorithm variations
Architectural Patterns
- MVC/MVP/MVVM - UI architecture
- Layered Architecture - Separation of concerns
- Microservices - Distributed system
- Event-Driven - Asynchronous communication
Tools to Help
Code Exploration Tools
- IntelliJ IDEA - Excellent Java navigation
- VS Code - Good for multi-language projects
- SourceGraph - Code search and navigation
- GitLens - Git history and blame
Documentation Tools
- PlantUML - Create diagrams from text
- Draw.io - Visual diagramming
- 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...