PHP

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

6 min de leitura

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

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

<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-&gt;db-&gt;query(&quot;SELECT * FROM pedidos WHERE id = $pedidoId&quot;);

$total = 0;

foreach ($pedido[&#039;itens&#039;] as $item) {

$total += $item[&#039;preco&#039;] * $item[&#039;quantidade&#039;];

}

$imposto = $total * 0.15;

$total += $imposto;

$this-&gt;db-&gt;query(&quot;UPDATE pedidos SET total = $total WHERE id = $pedidoId&quot;);

$this-&gt;enviarEmail($pedido[&#039;email&#039;], &quot;Seu pedido foi processado&quot;);

return $total;

}</code></pre>

<p>Refatorando em métodos menores:</p>

<pre><code class="language-php">public function processarPedido($pedidoId): float {

$pedido = $this-&gt;obterPedido($pedidoId);

$total = $this-&gt;calcularTotal($pedido[&#039;itens&#039;]);

$this-&gt;salvarTotal($pedidoId, $total);

$this-&gt;notificarCliente($pedido);

return $total;

}

private function obterPedido($pedidoId): array {

return $this-&gt;db-&gt;query(&quot;SELECT * FROM pedidos WHERE id = ?&quot;, [$pedidoId]);

}

private function calcularTotal(array $itens): float {

$subtotal = array_reduce($itens, fn($acc, $item) =&gt;

$acc + ($item[&#039;preco&#039;] * $item[&#039;quantidade&#039;]), 0

);

return $subtotal * 1.15; // inclui imposto

}

private function salvarTotal($pedidoId, float $total): void {

$this-&gt;db-&gt;query(&quot;UPDATE pedidos SET total = ? WHERE id = ?&quot;, [$total, $pedidoId]);

}

private function notificarCliente(array $pedido): void {

$this-&gt;enviarEmail($pedido[&#039;email&#039;], &quot;Seu pedido foi processado&quot;);

}</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 == &#039;premium&#039;) {

return $valor * 0.20;

} elseif ($tipoCliente == &#039;vip&#039;) {

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) {

&#039;premium&#039; =&gt; new DescontoPremium(),

&#039;vip&#039; =&gt; new DescontoVIP(),

default =&gt; new DescontoRegular(),

};

$desconto = $estrategia-&gt;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-&gt;db-&gt;query(

&quot;SELECT * FROM usuarios WHERE status = &#039;ativo&#039; AND deletado_em IS NULL&quot;

);

$pagamentosAtivos = $this-&gt;db-&gt;query(

&quot;SELECT * FROM pagamentos WHERE status = &#039;ativo&#039; AND deletado_em IS NULL&quot;

);

// Depois

private function filtrarAtivos(string $tabela): array {

return $this-&gt;db-&gt;query(

&quot;SELECT * FROM $tabela WHERE status = &#039;ativo&#039; AND deletado_em IS NULL&quot;

);

}

$usuariosAtivos = $this-&gt;filtrarAtivos(&#039;usuarios&#039;);

$pagamentosAtivos = $this-&gt;filtrarAtivos(&#039;pagamentos&#039;);</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-&gt;db e $this-&gt;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>

Comentários

Mais em PHP

Boas Práticas de Laravel Migrations e Seeders na Prática para Times Ágeis
Boas Práticas de Laravel Migrations e Seeders na Prática para Times Ágeis

Entendendo Migrations: Versionamento do Seu Banco de Dados Migrations no Lara...

Camada Controller: Recebendo Requisições e Orquestrando Respostas na Prática
Camada Controller: Recebendo Requisições e Orquestrando Respostas na Prática

O Papel do Controller na Arquitetura MVC O controller é o intermediário funda...

O que Todo Dev Deve Saber sobre Camada Model: Repositórios e Mapeamento de Dados
O que Todo Dev Deve Saber sobre Camada Model: Repositórios e Mapeamento de Dados

Compreendendo a Camada Model: Fundamentos A camada Model é o coração de qualq...