Boas Práticas de Refatoração em PHP: Técnicas para Melhorar Código Legado para Times Ágeis Já leu

Entendendo Refatoração em PHP Refatoração é o processo de reestruturar código existente sem alterar seu comportamento externo. Em PHP, especialmente em sistemas legados, essa prática é fundamental para melhorar manutenibilidade, performance e reduzir bugs. Diferentemente de reescrever do zero, refatoração preserva funcionalidades enquanto elimina débito técnico acumulado. A maioria dos projetos PHP legados sofre com código duplicado, funções gigantes, nomenclatura confusa e ausência de padrões. Refatorar esses sistemas não é luxo—é necessidade. Começamos identificando problemas: complexidade ciclomática alta, baixa coesão, alto acoplamento. Ferramentas como PHPStan e análise estática são aliadas nesse diagnóstico. Técnicas Fundamentais de Refatoração Extrair Métodos Uma das refatorações mais poderosas é quebrar funções grandes em métodos menores. Tome este exemplo legado: Refatorando em métodos menores: Substituir Condições por Polimorfismo Código com múltiplas condições é frágil. Veja: Com polimorfismo: Eliminando Code Smells Comuns Remover Duplicação Código duplicado é o inimigo da manutenção. Quando encontrar padrões repetidos, extraia para métodos reutilizáveis: Reduzir Acoplamento Código com alto acoplamento é difícil

Entendendo Refatoração em PHP

Refatoração é o processo de reestruturar código existente sem alterar seu comportamento externo. Em PHP, especialmente em sistemas legados, essa prática é fundamental para melhorar manutenibilidade, performance e reduzir bugs. Diferentemente de reescrever do zero, refatoração preserva funcionalidades enquanto elimina débito técnico acumulado.

A maioria dos projetos PHP legados sofre com código duplicado, funções gigantes, nomenclatura confusa e ausência de padrões. Refatorar esses sistemas não é luxo—é necessidade. Começamos identificando problemas: complexidade ciclomática alta, baixa coesão, alto acoplamento. Ferramentas como PHPStan e análise estática são aliadas nesse diagnóstico.

Técnicas Fundamentais de Refatoração

Extrair Métodos

Uma das refatorações mais poderosas é quebrar funções grandes em métodos menores. Tome este exemplo legado:

function processarPedido($pedidoId) {
    $pedido = $this->db->query("SELECT * FROM pedidos WHERE id = $pedidoId");

    $total = 0;
    foreach ($pedido['itens'] as $item) {
        $total += $item['preco'] * $item['quantidade'];
    }

    $imposto = $total * 0.15;
    $total += $imposto;

    $this->db->query("UPDATE pedidos SET total = $total WHERE id = $pedidoId");

    $this->enviarEmail($pedido['email'], "Seu pedido foi processado");

    return $total;
}

Refatorando em métodos menores:

public function processarPedido($pedidoId): float {
    $pedido = $this->obterPedido($pedidoId);
    $total = $this->calcularTotal($pedido['itens']);
    $this->salvarTotal($pedidoId, $total);
    $this->notificarCliente($pedido);

    return $total;
}

private function obterPedido($pedidoId): array {
    return $this->db->query("SELECT * FROM pedidos WHERE id = ?", [$pedidoId]);
}

private function calcularTotal(array $itens): float {
    $subtotal = array_reduce($itens, fn($acc, $item) => 
        $acc + ($item['preco'] * $item['quantidade']), 0
    );
    return $subtotal * 1.15; // inclui imposto
}

private function salvarTotal($pedidoId, float $total): void {
    $this->db->query("UPDATE pedidos SET total = ? WHERE id = ?", [$total, $pedidoId]);
}

private function notificarCliente(array $pedido): void {
    $this->enviarEmail($pedido['email'], "Seu pedido foi processado");
}

Substituir Condições por Polimorfismo

Código com múltiplas condições é frágil. Veja:

// Antes
function calcularDesconto($tipoCliente, $valor) {
    if ($tipoCliente == 'premium') {
        return $valor * 0.20;
    } elseif ($tipoCliente == 'vip') {
        return $valor * 0.30;
    } else {
        return $valor * 0.05;
    }
}

Com polimorfismo:

interface EstrategiaDesconto {
    public function calcular(float $valor): float;
}

class DescontoRegular implements EstrategiaDesconto {
    public function calcular(float $valor): float {
        return $valor * 0.05;
    }
}

class DescontoPremium implements EstrategiaDesconto {
    public function calcular(float $valor): float {
        return $valor * 0.20;
    }
}

class DescontoVIP implements EstrategiaDesconto {
    public function calcular(float $valor): float {
        return $valor * 0.30;
    }
}

// Uso
$estrategia = match($tipoCliente) {
    'premium' => new DescontoPremium(),
    'vip' => new DescontoVIP(),
    default => new DescontoRegular(),
};

$desconto = $estrategia->calcular($valor);

Eliminando Code Smells Comuns

Remover Duplicação

Código duplicado é o inimigo da manutenção. Quando encontrar padrões repetidos, extraia para métodos reutilizáveis:

// Antes (duplicado)
$usuariosAtivos = $this->db->query(
    "SELECT * FROM usuarios WHERE status = 'ativo' AND deletado_em IS NULL"
);
$pagamentosAtivos = $this->db->query(
    "SELECT * FROM pagamentos WHERE status = 'ativo' AND deletado_em IS NULL"
);

// Depois
private function filtrarAtivos(string $tabela): array {
    return $this->db->query(
        "SELECT * FROM $tabela WHERE status = 'ativo' AND deletado_em IS NULL"
    );
}

$usuariosAtivos = $this->filtrarAtivos('usuarios');
$pagamentosAtivos = $this->filtrarAtivos('pagamentos');

Reduzir Acoplamento

Código com alto acoplamento é difícil de testar e modificar. Injete dependências:

// Antes
class Relatorio {
    public function gerar() {
        $db = new Database();
        $email = new Email();
        // ...
    }
}

// Depois
class Relatorio {
    public function __construct(
        private Database $db,
        private Email $email
    ) {}

    public function gerar(): void {
        // Usa $this->db e $this->email
    }
}

Ferramentas e Práticas

Use ferramentas para guiar refatoração: PHPStan detecta tipos inconsistentes, Psalm valida tipos, PHP-CS-Fixer padroniza estilo. Testes são imprescindíveis—refatore com testes passando sempre.

composer require --dev phpstan/phpstan
./vendor/bin/phpstan analyse src/

Refatore em pequenos passos. Commit após cada refatoração funcional. Use versionamento para isolar mudanças e facilitar revert se necessário. Nunca refatore e adicione features simultaneamente—separe essas responsabilidades.

Conclusão

Refatoração em PHP é investimento em qualidade duradoura. Dominar extração de métodos, polimorfismo e eliminação de duplicação transforma código legado em sistemas mantíveis. Use ferramentas de análise estática como suporte e sempre mantenha testes passando durante o processo. Código refatorado é código que evolui.

Referências


Artigos relacionados