Clean Code en Java: principios y ejemplos prácticos
Todo desarrollador Java, tarde o temprano, se enfrenta al problema del código "sucio". Métodos difíciles de leer, nombres de variables sin sentido, números mágicos y clases gigantescas: todo esto ralentiza el desarrollo, aumenta la cantidad de errores y desmotiva al equipo. El libro de Robert Martin "Clean Code" se ha convertido en la biblia para quienes desean escribir software de calidad. En este artículo, analizaremos los principios clave del código limpio en Java y mostraremos cómo aplicarlos en la práctica con ejemplos concretos.
1. Nombramiento de variables, métodos y clases
Un nombre correcto es la mitad del éxito. El nombre debe revelar la intención del programador. Si necesita leer el cuerpo del método para entender lo que hace, el nombre ha sido mal elegido.
Ejemplo incorrecto:
int d; // elapsed time in daysList<Integer> lst = new ArrayList<>();public void proc(int a, int b) { // ...}Ejemplo correcto:
int elapsedTimeInDays;List<Integer> customerIds = new ArrayList<>();public void calculateTotalPrice(double basePrice, double discount) { // ...}Reglas de nombramiento:
- Clases e interfaces — sustantivos (Customer, OrderProcessor, PaymentService).
- Métodos — verbos o construcciones verbales (saveCustomer, findById, isActive).
- Variables — sustantivos con significado que reflejen la esencia de los datos (userName, totalAmount).
- Evite abreviaturas — escriba fullName en lugar de fn, de lo contrario, en un mes usted mismo no recordará qué significa fn.
2. Métodos pequeños y principio de responsabilidad única
Un método debe hacer solo una cosa y hacerla bien. Si un método contiene más de 10-15 líneas de código o tiene varios niveles de anidamiento, es una señal para refactorizar.
Ejemplo incorrecto (el método hace demasiado):
public void processOrder(Order order) { // 1. Validación if (order.getItems().isEmpty()) throw new IllegalArgumentException("Order is empty"); // 2. Cálculo del descuento double discount = 0; if (order.getCustomer().isPremium()) discount = 0.1; // 3. Cálculo del precio total double total = 0; for (Item item : order.getItems()) { total += item.getPrice() * item.getQuantity(); } total = total * (1 - discount); // 4. Guardar en la BD orderRepository.save(order); // 5. Envío de email emailService.sendConfirmation(order.getCustomer().getEmail());}Ejemplo correcto (división en métodos pequeños):
public void processOrder(Order order) { validateOrder(order); double discount = calculateDiscount(order.getCustomer()); double totalPrice = calculateTotalPrice(order, discount); order.setTotalPrice(totalPrice); orderRepository.save(order); sendConfirmationEmail(order.getCustomer());}
private void validateOrder(Order order) { if (order.getItems().isEmpty()) { throw new IllegalArgumentException("Order cannot be empty"); }}
private double calculateDiscount(Customer customer) { return customer.isPremium() ? 0.1 : 0.0;}
private double calculateTotalPrice(Order order, double discount) { double subtotal = order.getItems().stream() .mapToDouble(item -> item.getPrice() * item.getQuantity()) .sum(); return subtotal * (1 - discount);}
private void sendConfirmationEmail(Customer customer) { emailService.sendConfirmation(customer.getEmail());}3. Evite la duplicación de código (DRY — Don't Repeat Yourself)
La duplicación es la raíz de muchos males. Cuando la lógica se repite en varios lugares, cualquier cambio requiere modifi