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
- O comportamento foi preservado?
- Os testes passaram após cada passo?
- O código ficou mais simples de ler?
- 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.