Clean Code em Java: princípios e exemplos na prática
Todo desenvolvedor Java, mais cedo ou mais tarde, enfrenta o problema do código "sujo". Métodos difíceis de ler, nomes de variáveis sem sentido, números mágicos e classes gigantescas — tudo isso retarda o desenvolvimento, aumenta o número de bugs e desmotiva a equipe. O livro "Clean Code" de Robert Martin tornou-se uma bíblia para quem deseja escrever software de qualidade. Neste artigo, vamos analisar os princípios-chave do código limpo em Java e mostrar como aplicá-los na prática com exemplos concretos.
1. Nomeação de variáveis, métodos e classes
Um nome correto é metade do sucesso. O nome deve revelar a intenção do programador. Se você precisa ler o corpo do método para entender o que ele faz — o nome foi mal escolhido.
Exemplo ruim:
int d; // elapsed time in daysList<Integer> lst = new ArrayList<>();public void proc(int a, int b) { // ...}Exemplo bom:
int elapsedTimeInDays;List<Integer> customerIds = new ArrayList<>();public void calculateTotalPrice(double basePrice, double discount) { // ...}Regras de nomeação:
- Classes e interfaces — substantivos (Customer, OrderProcessor, PaymentService).
- Métodos — verbos ou construções verbais (saveCustomer, findById, isActive).
- Variáveis — substantivos significativos que reflitam a essência dos dados (userName, totalAmount).
- Evite abreviações — escreva fullName em vez de fn, caso contrário, em um mês você mesmo não se lembrará do que fn significa.
2. Métodos pequenos e princípio da responsabilidade única
Um método deve fazer apenas uma coisa e fazê-la bem. Se um método contém mais de 10-15 linhas de código ou tem vários níveis de aninhamento — é um sinal para refatoração.
Exemplo ruim (método faz demais):
public void processOrder(Order order) { // 1. Validação if (order.getItems().isEmpty()) throw new IllegalArgumentException("Order is empty"); // 2. Cálculo do desconto double discount = 0; if (order.getCustomer().isPremium()) discount = 0.1; // 3. Cálculo do preço total double total = 0; for (Item item : order.getItems()) { total += item.getPrice() * item.getQuantity(); } total = total * (1 - discount); // 4. Salvamento no BD orderRepository.save(order); // 5. Envio de email emailService.sendConfirmation(order.getCustomer().getEmail());}Exemplo bom (divisão em métodos pequenos):
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 duplicação de código (DRY — Don't Repeat Yourself)
A duplicação é a raiz de muitos males. Quando a lógica se repete em vários lugares, qualquer alteração requer correções