Você Está Quebrando o SOLID e Nem Sabe: Entenda os 5 Princípios que Todo Dev Precisa Dominar

Matheus AlmeidaMatheus Almeida
4 min read

Você já abriu um código seu de semanas atrás e pensou: “Quem escreveu isso?” Spoiler: foi você mesmo.

Essa situação é mais comum do que parece. E, muitas vezes, ela acontece porque estamos quebrando — sem perceber — os princípios do SOLID, um conjunto de boas práticas que ajudam a manter seu código limpo, flexível e escalável.

Neste post, vou te mostrar:

  • O que significa cada letra do SOLID

  • Explicações práticas com exemplos simples

  • Como aplicar esses conceitos no seu dia a dia como dev


O que é SOLID?

SOLID é um acrônimo criado por Robert C. Martin (Uncle Bob) que representa cinco princípios fundamentais do design de software orientado a objetos. Eles ajudam a criar sistemas mais organizados, coesos e fáceis de manter.


S — Single Responsibility Principle (SRP)

Princípio da Responsabilidade Única

Uma classe deve ter apenas um motivo para mudar.

Isso significa que cada classe, módulo ou função deve ter uma única responsabilidade bem definida. Quando uma classe tem várias responsabilidades, qualquer alteração em uma delas pode impactar negativamente outras partes da aplicação.

Problema comum:

Classes que fazem muitas coisas ao mesmo tempo, como lógica de negócio, persistência e envio de notificações.

Exemplo ruim:

class UsuarioService {
  void registrar(Usuario user) {
    validar(user);
    salvarNoBanco(user);
    enviarEmailBoasVindas(user);
  }
}

Solução:

Crie classes especializadas para cada ação:

class ValidadorUsuario { void validar(Usuario u) { ... } }
class UsuarioRepository { void salvar(Usuario u) { ... } }
class EmailService { void enviarBoasVindas(Usuario u) { ... } }

O — Open/Closed Principle (OCP)

Aberto para extensão, fechado para modificação

Você deve ser capaz de adicionar novos comportamentos ao sistema sem alterar o código existente.

Esse princípio incentiva o uso de abstrações (interfaces ou classes base) para que você possa estender funcionalidades sem tocar no que já funciona.

Exemplo:

Ao invés de usar if ou switch para tratar múltiplas regras, use polimorfismo com subclasses.

interface Desconto {
  double calcular(double valor);
}

class DescontoBlackFriday implements Desconto {
  public double calcular(double valor) {
    return valor * 0.9;
  }
}

Você pode adicionar novos descontos sem alterar a lógica principal.


L — Liskov Substitution Principle (LSP)

Subtipos devem ser substituíveis por seus tipos base

Se S é um subtipo de T, objetos do tipo T devem poder ser substituídos por objetos do tipo S sem afetar a funcionalidade.

Se uma subclasse quebra o comportamento esperado da superclasse, você está violando o LSP.

Exemplo ruim:

class Pato {
  void voar() { ... }
}

class PatoDeBorracha extends Pato {
  void voar() {
    // não faz sentido: pato de borracha não voa!
  }
}

Solução:

Evite herança quando não há relação de comportamento real. Use composição ou interfaces específicas.


I — Interface Segregation Principle (ISP)

Muitos contratos específicos são melhores que um único contrato genérico

Os clientes não devem ser forçados a depender de interfaces que não usam.

Interfaces grandes demais causam implementações infladas. Divida-as em interfaces menores e mais focadas.

Exemplo ruim:

interface OperacoesConta {
  void sacar();
  void depositar();
  void pedirEmprestimo(); // nem toda conta permite isso!
}

Exemplo bom:

interface SaqueDeposito {
  void sacar();
  void depositar();
}

interface ContaComEmprestimo {
  void pedirEmprestimo();
}

D — Dependency Inversion Principle (DIP)

Dependa de abstrações, não de implementações concretas

Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.

Ao invés de criar dependências diretas em uma classe, use interfaces para injetar comportamentos. Isso facilita testes, mudanças e reutilização.

Exemplo:

class PedidoService {
  private EmailService email;

  PedidoService(EmailService email) {
    this.email = email;
  }
}

Você pode facilmente trocar EmailService por um mock ou outro tipo de serviço.


Conclusão

Aplicar o SOLID na prática evita que seu projeto vire um monstro difícil de entender e manter. Comece aos poucos, especialmente com os princípios SRP e DIP, e você verá a diferença no dia a dia.


Curtiu o conteúdo?

Deixe um comentário se quiser ver mais exemplos aplicados em outras linguagens como PL/SQL, Java ou Python!


Publicado por Dev Prático — onde código, carreira e café se encontram.

0
Subscribe to my newsletter

Read articles from Matheus Almeida directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Matheus Almeida
Matheus Almeida

Desenvolvedor focado em PL/SQL, Java, Angular e qualidade de código.