Refatoração de código legado em PHP: do A ao Z
Trabalhar com código legado (obsoleto) é uma parte inevitável da vida de qualquer desenvolvedor PHP. Mais cedo ou mais tarde, você encontrará um projeto escrito em PHP 5.6 (ou até 4), onde não há carregamento automático, variáveis globais são usadas e a lógica de negócios está misturada com HTML. Refatorar esse código não é apenas "dar uma arrumada", mas um processo estratégico que pode salvar o projeto da dívida técnica e torná-lo sustentável.
Neste artigo, vamos analisar como abordar a refatoração de código PHP legado de forma sistemática, sem quebrar a funcionalidade existente, e transformar um "pântano" em código moderno e testável.
1. Diagnóstico e avaliação: por onde começar?
Antes de alterar o código, você precisa entender com o que está lidando. Comece com uma auditoria do projeto.
Passo 1. Identifique os "pontos problemáticos"
- Dependências: Bibliotecas obsoletas estão sendo usadas? Por exemplo, funções
mysql_*em vez de PDO ou MySQLi. - Arquitetura: Existe alguma estrutura (MVC)? Ou todo o código está em um único arquivo
index.php? - Testes: Existem testes automatizados? Se não, esta é sua primeira prioridade.
Passo 2. Ferramentas para análise
Use analisadores estáticos para identificar rapidamente áreas problemáticas:
- PHPStan / Psalm: Encontrarão erros de tipo e incompatibilidades de assinatura.
- Rector: Atualizará automaticamente a sintaxe para a nova versão do PHP.
- PhpMetrics: Mostrará a complexidade ciclomática e o acoplamento do código.
Exemplo de execução do Rector para atualizar do PHP 7.4 para 8.0:
vendor/bin/rector process src/ --set php802. Estratégia "Cirurgia sem dor": plano passo a passo
Refatoração de código legado não é uma "grande explosão". É uma série de pequenos passos seguros. Use a técnica "Strangler Fig" (figo estrangulador) — substitua gradualmente os módulos antigos por novos, sem reescrever tudo de uma vez.
Passo 1. Cubra o código com testes
Sem testes, refatoração é um jogo de roleta-russa. Comece com testes de caracterização (characterization tests):
class LegacyCalculatorTest extends TestCase { public function testOldCalculation(): void { // Executa o código antigo e registra o resultado $result = legacy_calculation(10, 5); $this->assertEquals(15, $result); }}Isso criará uma "rede de segurança" antes das alterações.
Passo 2. Isole a lógica "suja"
Se o código trabalha com variáveis globais ($GLOBALS), mova-as para parâmetros da função:
// Era (dependência global)function processOrder() { global $db; $result = $db->query("SELECT * FROM orders");}
// Ficou (injeção de dependência)function processOrder(PDO $db) { $result = $db->query("SELECT * FROM orders");}Passo 3. Substitua funções obsoletas
Por exemplo, substituição de mysql_* por PDO:
// Código antigo$link = mysql_connect('localhost', 'user', 'pass');mysql_select_db('test', $link);$result = mysql_query("SELECT * FROM users", $link);
// Novo código (PDO)$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');$stmt = $pdo->query("SELECT * FROM users");$result = $stmt->fetchAll(PDO::FETCH_ASSOC);3. Problemas típicos do PHP legado e suas soluções
Problema 1: "Código espaguete" (mistura de lógica e apresentação)
Solução: Separe o código em camadas. Mova a lógica de negócios para classes separadas e o HTML para templates (por exemplo, usando Twig).
// Ruim: lógica e HTML no mesmo arquivoif ($user->isAdmin()) { echo "<h1>Olá, admin!</h1>";} else { echo "<h1>Olá, usuário!</h1>";}
// Bom: controlador + template//