SOLID: Open Closed + Strategy (Parte 4)
Open/Closed sem misticismo
O Open/Closed Principle (OCP) é frequentemente mal interpretado como "nunca editar arquivo antigo". Não é isso.
A ideia útil é:
Você consegue adicionar comportamento novo com baixo risco para o comportamento existente, normalmente estendendo (via polimorfismo/composição) em vez de editar um núcleo instável cheio de condicionais.
Onde OCP dói de verdade
Quando cada nova regra vira mais um elseif no mesmo método. Isso cresce, assusta e quebra testes por qualquer motivo.
Strategy como alavanca de OCP
Na Parte 2 da série de Design Patterns, vimos Strategy: família de algoritmos intercambiáveis.
OCP "adora" Strategy porque o contexto permanece estável, novas variações entram como novas classes e você reduz modificações no miolo do fluxo.
Exemplo na prática: imposto com OCP + Strategy
<?php
declare(strict_types=1);
interface TaxRule
{
public function appliesTo(string $category): bool;
public function rate(): float;
}
final class TaxCalculator
{
/** @param list<TaxRule> $rules */
public function __construct(private array $rules) {}
public function taxFor(string $category, float $price): float
{
foreach ($this->rules as $rule) {
if ($rule->appliesTo($category)) {
return $price * $rule->rate();
}
}
return 0.0;
}
}
final readonly class ElectronicsTax implements TaxRule
{
public function appliesTo(string $category): bool
{
return $category === 'electronics';
}
public function rate(): float
{
return 0.20;
}
}
final readonly class BookTax implements TaxRule
{
public function appliesTo(string $category): bool
{
return $category === 'books';
}
public function rate(): float
{
return 0.05;
}
}
Uso:
$calculator = new TaxCalculator([
new ElectronicsTax(),
new BookTax(),
]);
$calculator->taxFor('electronics', 100.0); // 20.0
$calculator->taxFor('books', 50.0); // 2.5
$calculator->taxFor('food', 30.0); // 0.0 (nenhuma regra aplica)
Note que 'food' devolveu 0.0 porque nenhuma regra cobre essa categoria. Para cobrir, basta criar uma GroceryTax implements TaxRule — sem tocar em TaxCalculator. Esse é o ponto do OCP: o núcleo não muda quando o comportamento cresce.
OCP não substitui bom senso
Às vezes um match pequeno é mais claro do que 15 classes. OCP é um guia de custo de mudança, não um troféu.
Conclusão
OCP pede extensibilidade com segurança. Strategy (e outros polimorfismos) são caminhos comuns, especialmente quando regras crescem com o tempo.