Introdução: o que é código legado e por que refatorá-lo
\n\nTodo desenvolvedor Java, mais cedo ou mais tarde, se depara com código legado — software desatualizado, mal estruturado e pouco documentado. Esse código geralmente é escrito sem testes unitários, violando os princípios SOLID, e sua manutenção se torna um pesadelo. A refatoração de código legado em Java não é um capricho, mas uma necessidade para reduzir a dívida técnica e acelerar o desenvolvimento de novas funcionalidades.
\n\nNeste artigo, abordaremos a refatoração de código legado em Java de A a Z: desde a identificação de trechos problemáticos até a implementação segura de mudanças com ferramentas modernas.
\n\nEtapa 1: Análise e avaliação do código legado
\n\nAntes de alterar o código, é preciso entendê-lo. Aqui estão as principais etapas da análise:
\n\n1.1. Coleta de métricas e busca por "code smells"
\n\nUse analisadores estáticos:
\n- \n
- SonarQube — identifica duplicação, métodos complexos, violações de code style \n
- PMD — encontra potenciais bugs e dead code \n
- Checkstyle — verifica conformidade com padrões de formatação \n
Exemplo de um "code smell" típico — um método gigante:
\n\npublic class OrderProcessor {\n public void process(Order order) {\n // 200 linhas de código: validação, cálculo de descontos, envio de e-mail, logging...\n // Divida isso em métodos pequenos!\n }\n}\n\n1.2. Construção do mapa de dependências
\n\nCódigo legado frequentemente contém dependências cíclicas e God-classes. Use ferramentas de visualização:
\n- \n
- IntelliJ IDEA Dependency Viewer — ferramenta integrada \n
- Structure101 — solução profissional para análise de arquitetura \n
Etapa 2: Criação de uma rede de proteção com testes
\n\nSem testes, refatoração é jogar roleta-russa. Seu objetivo é cobrir os cenários principais com Characterization Tests (testes que fixam o comportamento atual).
\n\n2.1. Técnica "Golden Master" (Registro Mestre)
\n\nPara grandes blocos de código sem testes:
\n- \n
- Execute o sistema com dados reais \n
- Salve a saída (logs, respostas de API) como referência \n
- Após a refatoração, compare o resultado com a referência \n
2.2. Exemplo de teste para uma classe legada
\n\nimport org.junit.jupiter.api.Test;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LegacyCalculatorTest {\n \n @Test\n public void testLegacyCalculation() {\n LegacyCalculator calc = new LegacyCalculator();\n // Fixa o comportamento atual\n int result = calc.calculate(10, 5);\n assertEquals(15, result); // Se for bug — o teste preserva o bug!\n }\n}\n\nImportante: primeiro faça commit dos testes, depois refatore. Teste verde é seu seguro.
\n\nEtapa 3: Refatoração passo a passo com padrões
\n\nRefatoração de código legado em Java não é "reescrever tudo", mas uma série de pequenas transformações seguras.
\n\n3.1. Extrair Método (Extract Method)
\n\nA refatoração mais segura. A IDE faz isso automaticamente.
\n\nAntes:
\npublic void printInvoice(Invoice invoice) {\n double total = 0;\n for (Item item : invoice.getItems()) {\n total += item.getPrice() * item.getQuantity();\n }\n double discount = total > 100 ? total * 0.1 : 0;\n double finalTotal = total - discount;\n System.out.println("Total: " + finalTotal);\n}\n\nDepois (com extração de métodos):
\npublic void printInvoice(Invoice invoice) {\n double total = calculateTotal(invoice);\n double discount = calculateDiscount(total);\n double finalTotal = total - discount;\n printTotal(finalTotal);\n}\n\nprivate double calculateTot