Quản Lý Technical Debt trong Java
1. Khái Niệm Technical Debt
1.1 Định Nghĩa
- Nợ kỹ thuật là gì?
- Tại sao nó phát sinh?
- Ảnh hưởng đến dự án
- Chi phí của technical debt
- Lợi ích ngắn hạn vs dài hạn
1.2 Các Loại Technical Debt
- Code Debt
- Design Debt
- Architecture Debt
- Test Debt
- Documentation Debt
- Infrastructure Debt
- People Debt
2. Nhận Diện Technical Debt
2.1 Code Smells
// 1. Duplicate Code
public class OrderService {
public void processOrder(Order order) {
// Duplicate validation logic
if (order == null || order.getItems() == null) {
throw new ValidationException("Invalid order");
}
// Process order
}
public void updateOrder(Order order) {
// Same validation logic duplicated
if (order == null || order.getItems() == null) {
throw new ValidationException("Invalid order");
}
// Update order
}
}
// 2. Long Method
public class ReportGenerator {
public void generateReport() {
// 200+ lines of code doing multiple things
// - Load data
// - Process data
// - Format data
// - Generate PDF
// - Send email
}
}
// 3. God Class
public class SystemManager {
// Too many responsibilities
public void handleOrders() {}
public void manageInventory() {}
public void processPayments() {}
public void generateReports() {}
public void manageUsers() {}
}
2.2 Design Issues
// 1. Tight Coupling
public class OrderProcessor {
private final PaymentService paymentService;
private final InventoryService inventoryService;
private final ShippingService shippingService;
public void process(Order order) {
// Direct dependencies make changes difficult
paymentService.process(order);
inventoryService.update(order);
shippingService.ship(order);
}
}
// 2. Poor Abstraction
public class DataAccess {
public void saveToDatabase(Object data) {
// Direct SQL queries
String sql = "INSERT INTO " + data.getClass().getSimpleName() +
" VALUES (" + buildValues(data) + ")";
// Execute SQL
}
}
3. Đo Lường Technical Debt
3.1 Metrics
public class CodeMetrics {
// 1. Cyclomatic Complexity
public int calculateRisk(Order order) {
if (order == null) return -1;
if (order.getItems() == null) return -2;
if (order.getCustomer() == null) return -3;
if (order.getPayment() == null) return -4;
// More conditions...
return 0;
}
// 2. Method Length
public void processOrder(Order order) {
// 100+ lines of code
}
// 3. Class Coupling
public class OrderService {
private CustomerService customerService;
private InventoryService inventoryService;
private PaymentService paymentService;
private ShippingService shippingService;
private NotificationService notificationService;
// More dependencies...
}
}
<!-- pom.xml -->
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>${sonar.version}</version>
<configuration>
<properties>
<!-- Technical Debt Configuration -->
<sonar.technicalDebt.ratingGrid>
0.1,0.2,0.5,1
</sonar.technicalDebt.ratingGrid>
<sonar.technicalDebt.developmentCost>
30
</sonar.technicalDebt.developmentCost>
</properties>
</configuration>
</plugin>
4. Giải Quyết Technical Debt
4.1 Refactoring Strategies
// Before: Duplicate Validation
public class OrderService {
public void processOrder(Order order) {
if (order == null || order.getItems() == null) {
throw new ValidationException("Invalid order");
}
// Process order
}
public void updateOrder(Order order) {
if (order == null || order.getItems() == null) {
throw new ValidationException("Invalid order");
}
// Update order
}
}
// After: Extracted Validation
public class OrderService {
private final OrderValidator validator;
public void processOrder(Order order) {
validator.validate(order);
// Process order
}
public void updateOrder(Order order) {
validator.validate(order);
// Update order
}
}
public class OrderValidator {
public void validate(Order order) {
if (order == null || order.getItems() == null) {
throw new ValidationException("Invalid order");
}
}
}
4.2 Architecture Improvements
// Before: Monolithic Design
public class OrderProcessor {
public void process(Order order) {
// Everything in one place
validateOrder(order);
calculateTotal(order);
processPayment(order);
updateInventory(order);
generateInvoice(order);
sendNotification(order);
}
}
// After: Event-Driven Design
public class OrderProcessor {
private final EventPublisher eventPublisher;
public void process(Order order) {
// Publish events for different aspects
eventPublisher.publish(new OrderCreatedEvent(order));
}
}
@Service
public class PaymentHandler {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// Handle payment processing
}
}
@Service
public class InventoryHandler {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// Handle inventory update
}
}
5. Phòng Ngừa Technical Debt
5.1 Code Standards
// 1. Naming Conventions
public class CustomerOrderProcessor {
private static final int MAX_RETRY_ATTEMPTS = 3;
private static final String ERROR_MESSAGE_TEMPLATE =
"Failed to process order: %s";
public OrderResult processOrder(
CustomerOrder order,
ProcessingOptions options) {
// Implementation
}
}
// 2. Documentation
/**
* Processes customer orders with validation and notification.
*
* @param order The order to process
* @param options Processing options and configurations
* @return OrderResult containing status and details
* @throws ValidationException if order is invalid
* @throws ProcessingException if processing fails
*/
public OrderResult processOrder(
CustomerOrder order,
ProcessingOptions options) {
// Implementation
}
5.2 Architecture Guidelines
// 1. Dependency Injection
@Configuration
public class ServiceConfig {
@Bean
public OrderService orderService(
OrderRepository repository,
OrderValidator validator,
OrderProcessor processor) {
return new OrderService(repository, validator, processor);
}
}
// 2. Interface Segregation
public interface OrderProcessor {
void process(Order order);
}
public interface OrderValidator {
void validate(Order order);
}
public interface OrderRepository {
Order save(Order order);
Optional<Order> findById(Long id);
}
6. Monitoring và Maintenance
@Configuration
public class MonitoringConfig {
@Bean
public MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}
@Bean
public Timer orderProcessingTimer(MeterRegistry registry) {
return Timer.builder("order.processing")
.description("Order processing time")
.register(registry);
}
}
@Service
public class MonitoredOrderService {
private final Timer orderProcessingTimer;
public void processOrder(Order order) {
orderProcessingTimer.record(() -> {
// Process order
});
}
}
6.2 Maintenance Strategies
// 1. Regular Health Checks
@Component
public class SystemHealthCheck {
@Scheduled(fixedRate = 300000) // 5 minutes
public void checkSystemHealth() {
checkDatabaseConnections();
checkExternalServices();
checkMemoryUsage();
checkResponseTimes();
}
}
// 2. Performance Monitoring
@Aspect
@Component
public class PerformanceMonitor {
private final MeterRegistry registry;
@Around("@annotation(Monitored)")
public Object monitorPerformance(ProceedingJoinPoint joinPoint)
throws Throwable {
Timer.Sample sample = Timer.start(registry);
try {
return joinPoint.proceed();
} finally {
sample.stop(registry.timer("method.execution",
"class", joinPoint.getSignature().getDeclaringTypeName(),
"method", joinPoint.getSignature().getName()));
}
}
}
7. Best Practices
7.1 Development Guidelines
// 1. SOLID Principles
public interface PaymentProcessor {
void process(Payment payment);
}
@Service
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void process(Payment payment) {
// Process credit card payment
}
}
@Service
public class PayPalProcessor implements PaymentProcessor {
@Override
public void process(Payment payment) {
// Process PayPal payment
}
}
// 2. Design Patterns
public class OrderProcessorFactory {
private final Map<String, OrderProcessor> processors;
public OrderProcessor getProcessor(String type) {
return processors.getOrDefault(type,
new DefaultOrderProcessor());
}
}
7.2 Review Process
// Code Review Checklist
public class ReviewChecklist {
public void checkTechnicalDebt() {
// 1. Code Quality
checkCodeDuplication();
checkComplexity();
checkCoverage();
// 2. Architecture
checkDependencies();
checkLayering();
checkScalability();
// 3. Performance
checkMemoryUsage();
checkResponseTimes();
checkResourceUtilization();
// 4. Maintainability
checkDocumentation();
checkNaming();
checkTestability();
}
}
8. Case Studies
8.1 Legacy System Modernization
// Before: Legacy Code
public class LegacyOrderSystem {
public void processOrder(String orderData) {
// Parse CSV string
String[] data = orderData.split(",");
// Direct database calls
Connection conn = DriverManager.getConnection(URL);
Statement stmt = conn.createStatement();
// Raw SQL
stmt.execute("INSERT INTO ORDERS ...");
}
}
// After: Modern Implementation
@Service
public class ModernOrderSystem {
private final OrderRepository repository;
private final OrderMapper mapper;
public Order processOrder(OrderDTO orderDTO) {
Order order = mapper.toEntity(orderDTO);
return repository.save(order);
}
}
8.2 Microservices Migration
// Before: Monolithic Application
@Service
public class MonolithicOrderService {
public Order processOrder(Order order) {
validateOrder(order);
processPayment(order);
updateInventory(order);
notifyCustomer(order);
return order;
}
}
// After: Microservices
@Service
public class OrderService {
private final OrderValidator validator;
private final EventPublisher eventPublisher;
public Order processOrder(Order order) {
validator.validate(order);
Order savedOrder = repository.save(order);
eventPublisher.publish(new OrderCreatedEvent(savedOrder));
return savedOrder;
}
}
// Separate Payment Microservice
@Service
public class PaymentService {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
processPayment(event.getOrder());
}
}
// Separate Inventory Microservice
@Service
public class InventoryService {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
updateInventory(event.getOrder());
}
}
9. References và Further Reading
9.1 Books
- Working Effectively with Legacy Code (Michael Feathers)
- Refactoring (Martin Fowler)
- Clean Architecture (Robert C. Martin)
- Domain-Driven Design (Eric Evans)
- Building Evolutionary Architectures (Neal Ford)
9.2 Online Resources