Refatoração de código legado em PHP: como transformar caos em ordem
Todo desenvolvedor PHP mais cedo ou mais tarde se depara com código legado — um projeto antigo, mal documentado e frequentemente não funcional. Em vez de reescrever tudo do zero (o que é arriscado e caro), uma refatoração competente permite melhorar o código sem interromper os processos de negócio. Neste artigo, vamos analisar como refatorar com segurança projetos PHP legados, mantendo sua funcionalidade.
1. Avaliação e preparação: por onde começar a refatoração de código legado
Antes de tocar no código, é necessário entender seu estado atual. Pule esta etapa — e corre o risco de quebrar tudo.
- Crie um backup — dump completo do banco de dados e arquivos do projeto.
- Realize uma auditoria — encontre todos os pontos de entrada, dependências e "caixas-pretas". Use
greppara buscar funçõesinclude,require,evalemysql_*. - Configure o ambiente — levante uma cópia local do projeto (Docker, Vagrant ou XAMPP).
- Adicione logging —
error_loge monitoramento ajudarão a rastrear erros após as alterações.
Exemplo de uma auditoria simples via console:
# Busca por funções mysql obsoletasgrep -rn "mysql_query\\|mysql_connect\\|mysql_fetch" /caminho/para/projeto/legado/Importante: se o projeto não tem testes — a refatoração se transforma em um jogo de roleta-russa. Primeiramente, cubra a lógica crítica com testes (mesmo que sejam cenários manuais, documentados).
2. Estratégia de refatoração: pequenos passos para grandes mudanças
A melhor estratégia para legado é a melhoria gradual. Não tente reescrever todo o projeto em um fim de semana. Use a abordagem da "regra do escoteiro": deixe o código mais limpo do que estava antes de você.
2.1. Isole as alterações
Cada alteração deve ser mínima e atômica. Exemplo: renomear uma variável em um arquivo, depois extrair código duplicado para uma função.
<?php// Antes da refatoração (legado)$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];$result = mysql_query($sql);
// Depois: pelo menos escapamos$id = (int)$_GET['id'];$sql = "SELECT * FROM users WHERE id = $id";$result = mysqli_query($link, $sql);?>2.2. Use ferramentas de automação
- PHPStan — análise estática, encontra erros sem executar o código.
- Rector — refatoração automática (PSR-12, substituição de funções obsoletas).
- PHP CodeSniffer — verificação de estilo de código.
- PHPUnit — teste unitário.
Exemplo de execução do Rector para substituir mysql_* por mysqli_*:
vendor/bin/rector process src/ --set mysql-to-mysqli3. Técnicas específicas de refatoração de código PHP
3.1. Substituição de "código espaguete" por POO
O legado frequentemente é escrito como um único arquivo enorme com HTML e PHP misturados. Separe a lógica em classes e funções.
<?php// Ruim: código misturado$user = getUser($_GET['id']);echo "<h1>Olá, " . $user['name'] . "</h1>";if ($_POST['action'] === 'save') { saveUser($_POST);}
// Bom: separação de responsabilidadesclass UserController { public function show(int $id): void { $user = $this->userRepository->find($id); $this->render('profile', ['user' => $user]); }}?>3.2. Remoção de código "morto"
Funções não utilizadas, comentários, blocos comentados — tudo isso cria ruído. Remova sem piedade, mas verifique através de git log se o código não é usado em algum outro lugar.
// Busca por funções não utilizadas (requer PHPStan)vendo