<h2>Entendendo Refatoração em PHP</h2>
<p>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.</p>
<p>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.</p>
<h2>Técnicas Fundamentais de Refatoração</h2>
<h3>Extrair Métodos</h3>
<p>Uma das refatorações mais poderosas é quebrar funções grandes em métodos menores. Tome este exemplo legado:</p>
<pre><code class="language-php">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;
}</code></pre>
<p>Refatorando em métodos menores:</p>
<pre><code class="language-php">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");
}</code></pre>
<h3>Substituir Condições por Polimorfismo</h3>
<p>Código com múltiplas condições é frágil. Veja:</p>
<pre><code class="language-php">// Antes
function calcularDesconto($tipoCliente, $valor) {
if ($tipoCliente == 'premium') {
return $valor * 0.20;
} elseif ($tipoCliente == 'vip') {
return $valor * 0.30;
} else {
return $valor * 0.05;
}
}</code></pre>
<p>Com polimorfismo:</p>
<pre><code class="language-php">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);</code></pre>
<h2>Eliminando Code Smells Comuns</h2>
<h3>Remover Duplicação</h3>
<p>Código duplicado é o inimigo da manutenção. Quando encontrar padrões repetidos, extraia para métodos reutilizáveis:</p>
<pre><code class="language-php">// 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');</code></pre>
<h3>Reduzir Acoplamento</h3>
<p>Código com alto acoplamento é difícil de testar e modificar. Injete dependências:</p>
<pre><code class="language-php">// 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
}
}</code></pre>
<h2>Ferramentas e Práticas</h2>
<p>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.</p>
<pre><code class="language-bash">composer require --dev phpstan/phpstan
./vendor/bin/phpstan analyse src/</code></pre>
<p>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.</p>
<h2>Conclusão</h2>
<p>Refatoração em PHP é investimento em qualidade duradoura. Dominar <strong>extração de métodos</strong>, <strong>polimorfismo</strong> e <strong>eliminação de duplicação</strong> transforma código legado em sistemas mantíveis. Use <strong>ferramentas de análise estática</strong> como suporte e <strong>sempre mantenha testes passando</strong> durante o processo. Código refatorado é código que evolui.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://phptherightway.com/#code_style_guide" target="_blank" rel="noopener noreferrer">PHP: The Right Way - Code Style Guide</a></li>
<li><a href="https://refactoring.com" target="_blank" rel="noopener noreferrer">Martin Fowler - Refactoring: Improving the Design of Existing Code</a></li>
<li><a href="https://phpstan.org/user-guide/getting-started" target="_blank" rel="noopener noreferrer">PHPStan Documentation</a></li>
<li><a href="https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design" target="_blank" rel="noopener noreferrer">SOLID Principles in PHP</a></li>
<li><a href="https://getcomposer.org/doc/" target="_blank" rel="noopener noreferrer">Composer Dependency Management</a></li>
</ul>