← Back to Home

Code-Alongs

Code-Along 1: Dependency Injection

Learning Objectives

  • Implement dependency injection in a real-world Java application
  • Apply loose coupling principles to improve code maintainability
  • Learn to identify dependencies that should be injected
  • Practice constructor-based dependency injection
  • Use interfaces to define contracts between components

Implementation Details

In this code-along, we'll refactor a tightly coupled application to use dependency injection. We'll extract interfaces for our dependencies and inject them through constructors to make the code more modular and testable.

// Before: Tightly coupled code
public class OrderService {
    private final MySQLOrderRepository repository = new MySQLOrderRepository();
    private final SmtpEmailSender emailSender = new SmtpEmailSender();
    
    public void createOrder(Order order) {
        repository.save(order);
        emailSender.sendOrderConfirmation(order);
    }
}

// After: Dependency injection
public class OrderService {
    private final OrderRepository repository;
    private final EmailSender emailSender;
    
    public OrderService(OrderRepository repository, EmailSender emailSender) {
        this.repository = repository;
        this.emailSender = emailSender;
    }
    
    public void createOrder(Order order) {
        repository.save(order);
        emailSender.sendOrderConfirmation(order);
    }
}

Code-Along 2: TDD and Mocks

Learning Objectives

  • Apply Test-Driven Development in a practical scenario
  • Learn to use Mockito to create and configure mock objects
  • Practice the red-green-refactor cycle of TDD
  • Write tests that verify specific method interactions
  • Use mock objects to isolate units during testing

Implementation Details

In this code-along, we'll build a feature using the Test-Driven Development approach while using mocks to isolate our system under test. We'll write tests first, implement the minimum code to make them pass, and then refactor.

// 1. First we write a test with mocks
@Test
void shouldProcessOrderAndNotifyCustomer() {
    // Arrange
    Order testOrder = new Order("123", "Test Customer", 99.99);
    OrderRepository mockRepository = mock(OrderRepository.class);
    NotificationService mockNotification = mock(NotificationService.class);
    
    OrderProcessor processor = new OrderProcessor(mockRepository, mockNotification);
    
    // Act
    processor.processOrder(testOrder);
    
    // Assert
    verify(mockRepository).saveOrder(testOrder);
    verify(mockNotification).notifyCustomer(testOrder.getCustomerEmail(), 
                                           contains("Order 123 processed"));
}

// 2. Then we implement the minimum code to make the test pass
public class OrderProcessor {
    private final OrderRepository repository;
    private final NotificationService notificationService;
    
    public OrderProcessor(OrderRepository repository, 
                          NotificationService notificationService) {
        this.repository = repository;
        this.notificationService = notificationService;
    }
    
    public void processOrder(Order order) {
        repository.saveOrder(order);
        notificationService.notifyCustomer(order.getCustomerEmail(),
                                         "Order " + order.getId() + " processed");
    }
}