
A programação orientada a objetos (POO) é um dos paradigmas mais utilizados no desenvolvimento de software moderno. Porém, com grandes sistemas, é comum surgirem códigos difíceis de manter, testar e evoluir. Para evitar esse tipo de problema, surgiram boas práticas e padrões de design, entre eles os princípios do SOLID.
Esses princípios foram popularizados por Robert C. Martin (Uncle Bob) e têm como objetivo tornar o código mais flexível, reutilizável e fácil de entender. Vamos conhecer cada um deles:
1. S – Single Responsibility Principle (Princípio da Responsabilidade Única)
“Uma classe deve ter apenas um motivo para mudar.”
Esse princípio defende que cada classe deve ter apenas uma responsabilidade clara.
Se uma classe faz muitas coisas diferentes, qualquer alteração em uma funcionalidade pode impactar as demais, tornando o código frágil.
class User {
public function saveToDatabase($data) {
// código para salvar usuário
}
public function sendEmail($email, $message) {
// código para enviar e-mail
}
}
O correto serua uma classe para manipulação de usuários e outra para envio de e-mails:class UserRepository {
public function save($data) {
// código para salvar usuário no banco
}
}
class EmailService {
public function send($email, $message) {
// código para enviar e-mail
}
}
2. O – Open/Closed Principle (Aberto/Fechado)
“Aberto para extensão, fechado para modificação.”
Ou seja, você deve poder adicionar novas funcionalidades sem precisar alterar o código já existente. Isso reduz riscos de quebrar o que já funciona.
Exemplo:
- Usar herança ou interfaces para estender funcionalidades sem alterar a classe original.
No seguinte caso se surgir outro método de pagamento, precisamos alterar a classe:
class Payment {
public function pay($type) {
if ($type == 'paypal') {
// lógica do PayPal
} elseif ($type == 'pix') {
// lógica do Pix
}
}
}
Então o correto seria da seguinte maneira, em que permite criar novas classes de pagamento, sem mexer no código existente:
interface PaymentMethod {
public function pay();
}
class PayPalPayment implements PaymentMethod {
public function pay() {
echo "Pagamento via PayPal";
}
}
class PixPayment implements PaymentMethod {
public function pay() {
echo "Pagamento via Pix";
}
}
class PaymentProcessor {
public function process(PaymentMethod $payment) {
$payment->pay();
}
}
3. L – Liskov Substitution Principle (Princípio da Substituição de Liskov)
“Objetos de uma classe derivada devem poder substituir objetos da classe base sem alterar o comportamento esperado.”
Se você usa uma subclasse no lugar da classe pai, o sistema deve continuar funcionando corretamente.
Caso contrário, significa que a herança foi mal aplicada.
Exemplo:
- Se
Avetem o métodovoar(), mas você cria uma subclassePinguimque não voa, isso quebra o princípio. Nesse caso, seria melhor repensar a hierarquia.
Aqui quebramos o princípio, pois Penguin não se comporta como um Bird:
class Bird {
public function fly() {
echo "Voando...";
}
}
class Penguin extends Bird {
public function fly() {
throw new Exception("Pinguins não voam!");
}
}
O correto seria o Penguin não ser forçado a implementar fly():
interface Bird {
public function eat();
}
interface FlyingBird extends Bird {
public function fly();
}
class Sparrow implements FlyingBird {
public function eat() { echo "Comendo sementes"; }
public function fly() { echo "Voando..."; }
}
class Penguin implements Bird {
public function eat() { echo "Comendo peixes"; }
}
4. I – Interface Segregation Principle (Segregação de Interfaces)
“Uma classe não deve ser forçada a implementar interfaces que não utiliza.”
É melhor criar interfaces menores e mais específicas, em vez de uma única interface “inchada” com muitos métodos. Isso evita implementações desnecessárias.
Exemplo:
- Em vez de ter uma interface
IAvecom métodosvoar()enadar(), criarIAveVoadoraeIAveNadadora.
Nesse caso, o Dog nunca vai voar, mas é obrigado a implementar fly():
interface Animal {
public function fly();
public function swim();
}
class Dog implements Animal {
public function fly() { /* ??? */ }
public function swim() { echo "Nadando"; }
}
Cada classe deve implementar apenas o que precisa, nesse caso o dog vai implementar somente canSwim:
interface CanFly {
public function fly();
}
interface CanSwim {
public function swim();
}
class Dog implements CanSwim {
public function swim() { echo "Nadando"; }
}
5. D – Dependency Inversion Principle (Princípio da Inversão de Dependência)
“Dependa de abstrações, não de implementações.”
Classes de alto nível não devem depender diretamente de classes de baixo nível, mas sim de abstrações (interfaces). Isso deixa o sistema mais flexível e facilita a substituição de implementações.
- Em vez de uma classe
Pedidodepender diretamente deMySQLRepository, ela deve depender de uma interfaceIRepository, que pode ter implementações diferentes (MySQL, MongoDB, etc.).
Nessa situação, se mudar o banco para MongoDB, temos que reescrever o código:
class MySQLRepository {
public function getUsers() {
return ['João', 'Maria'];
}
}
class UserService {
private $repository;
public function __construct() {
$this->repository = new MySQLRepository(); // dependência direta
}
public function listUsers() {
return $this->repository->getUsers();
}
}
Para corrigir podemos trocar a implementação do repositório sem alterar o UserService:
interface UserRepository {
public function getUsers();
}
class MySQLRepository implements UserRepository {
public function getUsers() {
return ['João', 'Maria'];
}
}
class MongoRepository implements UserRepository {
public function getUsers() {
return ['Carlos', 'Ana'];
}
}
class UserService {
private $repository;
public function __construct(UserRepository $repository) {
$this->repository = $repository;
}
public function listUsers() {
return $this->repository->getUsers();
}
}
// Exemplo de uso:
$service = new UserService(new MySQLRepository());
print_r($service->listUsers());
Porque usar o SOLID?
Seguir os princípios do SOLID ajuda a criar aplicações mais limpas, organizadas e fáceis de manter. Seja em projetos grandes ou pequenos, aplicar essas boas práticas é um investimento que evita dores de cabeça no futuro.

