Princípios SOLID em PHP: teoria e prática
SOLID é um acrônimo de cinco princípios fundamentais da programação orientada a objetos, formulados por Robert Martin (Uncle Bob). Esses princípios ajudam a criar código flexível, sustentável e escalável. Neste artigo, vamos analisar cada princípio com exemplos em PHP e mostrar como aplicá-los em projetos reais.
1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única
Essência: Cada classe deve ter apenas um motivo para ser alterada. Em outras palavras, a classe deve ser responsável por apenas uma tarefa.
Violação do SRP:
class Order { public function calculateTotal() { /* ... */ } public function saveToDatabase() { /* ... */ } public function sendEmailNotification() { /* ... */ }}Aqui, a classe Order é responsável pelo cálculo, pelo salvamento e pelo envio de notificações. Isso viola o SRP.
Solução:
class Order { public function calculateTotal() { /* ... */ }}
class OrderRepository { public function save(Order $order) { /* ... */ }}
class EmailNotificationService { public function sendOrderConfirmation(Order $order) { /* ... */ }}Agora cada classe tem uma responsabilidade clara, o que simplifica os testes e a modificação.
2. Open-Closed Principle (OCP) — Princípio Aberto/Fechado
Essência: As classes devem estar abertas para extensão, mas fechadas para modificação. Você deve ser capaz de adicionar novas funcionalidades sem alterar o código existente.
Violação do OCP:
class PaymentProcessor { public function process($type) { if ($type == 'credit_card') { // processamento de cartão de crédito } elseif ($type == 'paypal') { // processamento do PayPal } }}Para adicionar um novo método de pagamento, será necessário alterar a classe PaymentProcessor.
Solução usando interfaces:
interface PaymentMethod { public function process();}
class CreditCardPayment implements PaymentMethod { public function process() { /* ... */ }}
class PayPalPayment implements PaymentMethod { public function process() { /* ... */ }}
class PaymentProcessor { public function process(PaymentMethod $method) { $method->process(); }}Agora, para adicionar um novo método de pagamento, basta criar uma nova classe que implemente a interface PaymentMethod, sem alterar o código existente.
3. Liskov Substitution Principle (LSP) — Princípio da Substituição de Barbara Liskov
Essência: Os objetos das subclasses devem ser substituíveis por objetos da classe base sem quebrar a correção do programa. A subclasse não deve alterar o comportamento esperado da classe base.
Violação do LSP:
class Rectangle { protected $width; protected $height;
public function setWidth($w) { $this->width = $w; } public function setHeight($h) { $this->height = $h; } public function getArea() { return $this->width * $this->height; }}
class Square extends Rectangle { public function setWidth($w) { $this->width = $w; $this->height = $w; // violação do princípio } public function setHeight($h) { $this->height = $h; $this->width = $h; // violação do princípio }}Se o código cliente espera que a alteração da largura não afete a altura, então Square violará essa expectativa.
Solução: Evite herança se a subclasse não corresponder completamente ao comportamento da classe pai. É melhor usar composição ou classes separadas:
interface Shape