Aula 3

Refatoração em Java

Professor: Ricardo Pires
3º Técnico DS - Desenvolvimento de Sistemas II


🚀 Roteiro (105 min)

  • Ritmo: Conceito Código Resolução de Problema.
  • Foco: melhorar estrutura sem alterar comportamento.
  • Meta: reduzir dívida técnica com segurança.

🧠 Conceito: refatorar não é reescrever

  • Refatoração melhora design interno.
  • O comportamento externo deve permanecer igual.
  • Refatoração segura exige teste automatizado.
RED -> GREEN -> REFACTOR

💻 Live Code: extração de método

// Antes
public double calcular(double valor, boolean vip, boolean ativo) {
    if (!ativo) return 0;
    if (vip) return valor - (valor * 0.2);
    return valor - (valor * 0.1);
}
// Depois
public double calcularDesconto(double valor, boolean vip, boolean ativo) {
    if (!ativo) {
        return 0;
    }
    double percentual = vip ? 0.2 : 0.1;
    return aplicarDesconto(valor, percentual);
}
 
private double aplicarDesconto(double valor, double percentual) {
    return valor - (valor * percentual);
}

🔎 Sinais clássicos de refatoração

  • Método grande demais.
  • Duplicação em várias classes.
  • Nomes confusos e sem intenção.
  • Classe que concentra responsabilidades demais.
Se está difícil de explicar, está na hora de refatorar.

🗣️ Desafio do Código - O Bug de Produção

Regra de desconto alterada em um trecho, mas esquecida em outro método duplicado.

Impacto:
- Pedido com desconto errado
- Reclamação de cliente
- Ajuste manual no financeiro
  • Causa: lógica repetida sem refatoração prévia.

✅ Desafio do Código - A Solução do Sênior

  • Extrair cálculo para método único.
  • Cobrir cenários com JUnit (VIP, comum, inativo).
  • Evoluir regra em um ponto só.
assertEquals(80.0, calcularDesconto(100.0, true, true));
assertEquals(0.0, calcularDesconto(100.0, false, false));

🎯 Checklist final da Aula 3

  1. O comportamento foi preservado?
  2. Os testes passaram após cada passo?
  3. O código ficou mais simples de ler?
  4. O commit ficou pequeno e revisável?

📝 Atividades práticas em sala (30 min)

Exercício 1: Extrair método

Refatore o método abaixo extraindo lógica para métodos menores:

public String processarPedido(Pedido pedido) {
    if (pedido.getCliente().getIdade() < 18) {
        return "Cliente menor de idade";
    }
    if (pedido.getItens().isEmpty()) {
        return "Pedido sem itens";
    }
    double total = 0;
    for (Item item : pedido.getItens()) {
        total += item.getPreco() * item.getQuantidade();
    }
    if (total < 10) {
        return "Valor mínimo não atingido";
    }
    if (pedido.getCliente().isVip()) {
        total = total * 0.9;
    }
    return "Pedido processado. Total: " + total;
}

Exercício 2: Simplificar condicional

Refatore removendo nested if:

public boolean podeComprar(Usuario usuario, Produto produto) {
    if (usuario != null) {
        if (usuario.isAtivo()) {
            if (produto != null) {
                if (produto.getEstoque() > 0) {
                    return true;
                }
            }
        }
    }
    return false;
}

✅ Gabarito das atividades

Gabarito 1:

public String processarPedido(Pedido pedido) {
    String validacao = validarPedido(pedido);
    if (validacao != null) {
        return validacao;
    }
 
    double total = calcularTotal(pedido);
    total = aplicarDesconto(pedido.getCliente(), total);
 
    return "Pedido processado. Total: " + total;
}
 
private String validarPedido(Pedido pedido) {
    if (pedido.getCliente().getIdade() < 18) {
        return "Cliente menor de idade";
    }
    if (pedido.getItens().isEmpty()) {
        return "Pedido sem itens";
    }
    return null;
}
 
private double calcularTotal(Pedido pedido) {
    return pedido.getItens().stream()
        .mapToDouble(item -> item.getPreco() * item.getQuantidade())
        .sum();
}
 
private double aplicarDesconto(Cliente cliente, double total) {
    return cliente.isVip() ? total * 0.9 : total;
}

Gabarito 2:

public boolean podeComprar(Usuario usuario, Produto produto) {
    return usuario != null
        && usuario.isAtivo()
        && produto != null
        && produto.getEstoque() > 0;
}

Atividade rápida

  • Escolher um dos exercícios.
  • Aplicar técnica Extract Method.
  • Testar que comportamento foi preservado.