Refatoração de código legado em PHP: técnicas e estratégias avançadas

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: nível avançado



Trabalhar com código legado (obsoleto) em PHP é uma realidade inevitável para muitos desenvolvedores. Frequentemente, esse código é uma aplicação monolítica sem testes, com dependências globais e mistura de lógica de negócios com apresentação. Uma simples refatoração "de olho" pode levar a erros fatais. Neste artigo, veremos técnicas avançadas de refatoração que permitirão modernizar sistemas legados de forma segura e eficiente.



1. Estratégia "Seam": criando pontos de ruptura



O primeiro passo na refatoração de código legado é criar costuras (seams). Uma costura é um lugar onde você pode alterar o comportamento do código sem editá-lo diretamente. Isso é especialmente importante quando o código não tem cobertura de testes e você não pode executá-lo isoladamente.



Vamos considerar um exemplo clássico: trabalho direto com o banco de dados dentro de um método.



<?php// Código legadoclass UserReport {    public function getActiveUsers() {        $db = new PDO('mysql:host=localhost;dbname=test', 'root', '');        $stmt = $db->query("SELECT * FROM users WHERE active = 1");        return $stmt->fetchAll();    }}?>


Problema: new PDO(...) cria uma dependência rígida. Para testar este método, você precisa ter um banco de dados real.



Solução: injeção de dependência através do construtor.



<?php// Refatoração: criando uma costura via DIclass UserReport {    private PDO $pdo;

public function __construct(PDO $pdo) { $this->pdo = $pdo; }

public function getActiveUsers(): array { $stmt = $this->pdo->query("SELECT * FROM users WHERE active = 1"); return $stmt->fetchAll(); }}

// Uso$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');$report = new UserReport($pdo);?>


Agora você pode substituir o PDO por um objeto mock nos testes. Esta é uma costura simples, mas eficaz.



2. Padrão "Sprout Method" e "Sprout Class"



Quando você não pode alterar um método existente (por exemplo, devido à falta de testes), use a estratégia "Sprout" — crie novo código ao lado do antigo, redirecionando gradualmente as chamadas.



Exemplo: temos um método enorme que valida e salva um usuário.



<?phpclass UserService {    public function saveUser(array $data): bool {        // 100 linhas de validação, registro e salvamento        $email = $data['email'] ?? '';        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {            throw new InvalidArgumentException('Invalid email');        }        // ... muito outro código        $db = new PDO(...);        $stmt = $db->prepare("INSERT INTO users ...");        // ...    }}?>


Em vez de refatorar o método inteiro de uma vez, crie uma nova classe para validação.



<?phpclass UserValidator {    public function validate(array $data): void {        if (!filter_var($data['email'] ?? '', FILTER_VALIDATE_EMAIL)) {            throw new InvalidArgumentException('Invalid email');        }        // Adicione outras verificações    }}

class UserService { private UserValidator $validator;

public function __construct(UserValidator $validator) { $this->validator = $validator; }

public function saveUser(array $data): bool { $this->validator->validate($data); // O restante do código permanece por enquanto }}?>


Agora você pode escrever testes unitários para UserValidator sem tocar no código antigo. Gradualmente, você extrairá a lógica de saveUser para novas classes.



3. Eliminação de estados globais e estáticos



Código legado frequentemente usa variáveis globais, singletons e métodos estáticos. Isso torna o código praticamente impossível de

Blogs

Book Recommendations