Refatoração de código legado em PHP: do A ao Z para iniciantes

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Refatoração de código legado em PHP: do A ao Z

\n\n

Trabalhar com código PHP legado é uma realidade inevitável para muitos desenvolvedores. Projetos escritos há 5-10 anos geralmente são "código espaguete" com variáveis globais, mistura de lógica de negócios e apresentação, falta de tipagem e funções obsoletas (mysql_*, ereg, etc.). Neste artigo, vamos abordar uma abordagem passo a passo para refatorar código PHP legado, permitindo melhorar o projeto sem interromper seu funcionamento.

\n\n

Por que refatorar código legado é difícil?

\n\n

O principal problema do código legado é a falta de testes. Você não pode ter certeza de que as alterações não quebrarão a funcionalidade existente. Dificuldades adicionais:

\n\n
    \n
  • Falta de documentação — a lógica de funcionamento geralmente é incompreensível
  • \n
  • Mistura de camadas — consultas SQL dentro de templates HTML
  • \n
  • Estado global — variáveis acessíveis de qualquer ponto do código
  • \n
  • Padrões obsoletos — uso de register_globals, funções mysql_*
  • \n
  • Dependências rígidas — criação direta de objetos com new dentro das classes
  • \n
\n\n

Preparação para a refatoração: criando uma "rede de segurança"

\n\n

Antes de alterar o código, é necessário garantir que você conseguirá detectar erros. Aqui estão as etapas obrigatórias:

\n\n

1. Adicionar testes de caracterização

\n\n

Testes de caracterização (characterization tests) fixam o comportamento atual do código. Eles são escritos após o código ser escrito e permitem garantir que a refatoração não alterou o comportamento.

\n\n
<?php\n// Exemplo de teste de caracterização para uma função legada\nclass LegacyCalculatorTest extends PHPUnit\\Framework\\TestCase\n{\n    public function testCalculateTotal()\n    {\n        // Fixando o comportamento atual\n        $result = legacy_calculate_total(100, 0.2);\n        $this->assertEquals(120, $result);\n    }\n}\n
\n\n

2. Criar uma "cobertura" de testes

\n\n

Comece com testes de integração que verificam os principais cenários de usuário (cadastro, finalização de pedido, etc.). Isso dará uma confiança básica durante a refatoração.

\n\n

Estratégia passo a passo para refatorar código PHP legado

\n\n

Utilizamos a abordagem "Strangler Fig Pattern" (figueira estranguladora) — substituímos gradualmente os componentes antigos pelos novos, sem interromper o funcionamento do sistema.

\n\n

Passo 1: Isole e encapsule o estado global

\n\n

Variáveis e funções globais são o maior inimigo da refatoração. Comece encapsulando-as:

\n\n
<?php\n// ANTES: função e variável global\n$db = mysql_connect('localhost', 'user', 'pass');\nfunction get_user($id) {\n    global $db;\n    $result = mysql_query("SELECT * FROM users WHERE id = $id", $db);\n    return mysql_fetch_assoc($result);\n}\n\n// DEPOIS: classe com dependência explícita\nclass UserRepository {\n    private PDO $pdo;\n    \n    public function __construct(PDO $pdo) {\n        $this->pdo = $pdo;\n    }\n    \n    public function findById(int $id): ?array {\n        $stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = ?');\n        $stmt->execute([$id]);\n        $user = $stmt->fetch();\n        return $user ?: null;\n    }\n}\n
\n\n

Passo 2: Separe a lógica da apresentação

\n\n

O código legado típico contém SQL e lógica PHP diretamente no HTML. Use o padrão "Template Method" para separar:

\n\n
<?php\n// ANTES: código espaguete no template\n?>\n<ul>\n<?php\n$result = mysql_query("SELECT * FROM products");\nwhile ($row = mysql_fetch_assoc($result)) {\n    echo "<li>" . $row['name'] . " - " . $row['price'] . " R$</li>";\n}\n?>\n</ul>\n\n// DEPOIS: extração da lógica para um serviço\nclass ProductService {\n    public function __construct(private ProductRepository $repo) {}\n    \n    public function getProductList(): array {\n        return $this->repo->findAll();\n    }\n}\n\n// No template                

Blogs

Book Recommendations