SOLID ainda importa? Sim. E talvez mais do que nunca na era da IA.
Ferramentas de IA estão transformando a forma como desenvolvemos software. Hoje é possível gerar controllers, services, testes, queries SQL e até funcionalidades completas em poucos minutos.
SOLID ainda importa? Sim. E talvez mais do que nunca na era da IA.
Ferramentas de IA estão transformando a forma como desenvolvemos software.
Hoje é possível gerar controllers, services, testes, queries SQL e até funcionalidades completas em poucos minutos.
Mas existe um problema:
Código rápido sem estrutura vira dívida técnica rápida.
A IA acelera a produção de código, mas não elimina a necessidade de uma arquitetura saudável.
Na prática, quanto mais código é gerado, mais importante se torna ter princípios que mantenham o projeto organizado, previsível e fácil de evoluir.
É exatamente nesse cenário que os princípios SOLID continuam extremamente relevantes.
Por que SOLID importa (ainda mais com IA)?
Quando um projeto segue SOLID:
- O código é mais previsível.
- As responsabilidades são claras.
- As mudanças possuem impacto controlado.
- Os testes são mais simples.
- A revisão de código é mais rápida.
- A própria IA gera sugestões melhores.
Quando o projeto não segue SOLID, a IA tende a amplificar os problemas existentes.
Ela pode até gerar a funcionalidade solicitada, mas normalmente seguirá os padrões já presentes no projeto.
Se a base estiver ruim, o resultado tende a ser ainda mais código difícil de manter.
Um exemplo fictício: o sistema da padaria
Imagine um sistema para uma rede de padarias. Existe uma classe chamada:
PedidoManager
Ela faz tudo:
- Calcula descontos
- Salva pedidos
- Envia e-mails
- Atualiza estoque
- Gera relatórios
- Emite notas fiscais
Um dia o time recebe uma solicitação simples:
"Adicionar um novo desconto para clientes VIP."
Parece uma tarefa de 30 minutos.
Mas ao alterar a lógica de desconto:
- O relatório para de calcular corretamente.
- O estoque deixa de atualizar.
- A emissão da nota fiscal começa a falhar.
Por quê? Porque tudo está acoplado dentro da mesma classe.
Agora imagine outro cenário.
Um desenvolvedor precisa encontrar a funcionalidade de envio de e-mail. Naturalmente ele procura por:
Email
Notification
Mailer
Depois de uma hora procurando, descobre que a implementação está dentro de:
Financeiro/PedidoManager.cs
Misturada com cálculo de impostos.
Esse é exatamente o tipo de problema que SOLID ajuda a evitar.
Os 5 princípios em uma linha
S — Single Responsibility Principle
Uma classe, uma responsabilidade.
Se existem dois motivos para mudar uma classe, provavelmente ela deveria ser dividida.
O — Open Closed Principle
Estenda sem modificar.
Novo comportamento deve ser adicionado através de novas implementações, não alterando código que já funciona.
L — Liskov Substitution Principle
Uma subclasse deve poder substituir sua classe pai sem quebrar o sistema.
Se a implementação muda completamente o comportamento esperado, a herança está errada.
I — Interface Segregation Principle
Interfaces pequenas e específicas.
Ninguém deveria implementar métodos que não utiliza.
D — Dependency Inversion Principle
Dependa de abstrações.
A regra de negócio não deveria saber se os dados estão em SQL Server, PostgreSQL ou MongoDB.
Exemplos simples para memorizar
| Princípio | Exemplo |
|---|---|
| S | Um robô serve bebidas. Outro limpa mesas. |
| O | Novo tipo de bebida? Crie um novo robô sem alterar os existentes. |
| L | Qualquer robô garçom deve conseguir servir uma bebida sem comportamento inesperado. |
| I | O robô que limpa não precisa implementar "ServirBebida()". |
| D | O garçom não sabe onde a bebida é armazenada, apenas pede para alguém fornecer. |
S — Single Responsibility Principle
❌ Ruim
public class UsuarioService
{
public void SalvarUsuario()
{
// salva usuário
}
public void EnviarEmailBoasVindas()
{
// envia email
}
}
A classe possui dois motivos para mudar:
- Alteração de cadastro
- Alteração de e-mail
✅ Bom
public class UsuarioService
{
public void SalvarUsuario()
{
// salva usuário
}
}
public class EmailService
{
public void EnviarBoasVindas()
{
// envia email
}
}
Cada classe possui apenas uma responsabilidade.
O — Open Closed Principle
❌ Ruim
public decimal CalcularDesconto(string tipoCliente)
{
if (tipoCliente == "Normal")
return 0;
if (tipoCliente == "VIP")
return 10;
if (tipoCliente == "Premium")
return 20;
return 0;
}
Toda vez que surge um novo tipo de cliente a função precisa ser alterada.
✅ Bom
public interface IDesconto
{
decimal Calcular();
}
public class DescontoVip : IDesconto
{
public decimal Calcular() => 10;
}
public class DescontoPremium : IDesconto
{
public decimal Calcular() => 20;
}
Novo desconto? Nova classe. Sem alterar o código existente.
L — Liskov Substitution Principle
❌ Ruim
public class Passaro
{
public virtual void Voar()
{
}
}
public class Pinguim : Passaro
{
public override void Voar()
{
throw new Exception("Pinguim não voa");
}
}
Quem usa Passaro espera que ele voe.
Mas o pinguim quebra essa expectativa.
✅ Bom
public abstract class Passaro
{
}
public interface IVoa
{
void Voar();
}
public class Aguia : Passaro, IVoa
{
public void Voar()
{
}
}
public class Pinguim : Passaro
{
}
Agora cada tipo possui apenas os comportamentos válidos.
I — Interface Segregation Principle
❌ Ruim
public interface IFuncionario
{
void Trabalhar();
void GerenciarEquipe();
}
Um estagiário não gerencia equipe. Mesmo assim é obrigado a implementar.
✅ Bom
public interface ITrabalhador
{
void Trabalhar();
}
public interface IGerente
{
void GerenciarEquipe();
}
Cada classe implementa apenas o que realmente utiliza.
D — Dependency Inversion Principle
❌ Ruim
public class PedidoService
{
private readonly SqlServerRepository _repository =
new SqlServerRepository();
public void Salvar()
{
_repository.Salvar();
}
}
A regra de negócio está presa ao SQL Server.
✅ Bom
public interface IRepository
{
void Salvar();
}
public class SqlServerRepository : IRepository
{
public void Salvar()
{
}
}
public class PedidoService
{
private readonly IRepository _repository;
public PedidoService(IRepository repository)
{
_repository = repository;
}
public void Salvar()
{
_repository.Salvar();
}
}
Agora é possível trocar banco de dados sem alterar a regra de negócio.
O benefício menos falado: IA entende melhor projetos SOLID
Quando um projeto segue SOLID:
- As responsabilidades são claras.
- Os arquivos possuem objetivos bem definidos.
- Os pontos de extensão são previsíveis.
- Os testes são mais isolados.
- As dependências são explícitas.
Isso não ajuda apenas os desenvolvedores.
Ajuda também as ferramentas de IA.
Um agente de IA consegue localizar mais facilmente onde uma alteração deve ser realizada quando a arquitetura é organizada.
Em projetos caóticos, a IA frequentemente replica problemas existentes, aumenta acoplamentos e cria mais dívida técnica.
Conclusão
SOLID nunca teve como objetivo tornar o código mais elegante. O objetivo sempre foi tornar mudanças mais seguras.
E isso se tornou ainda mais importante em uma era onde gerar código custa poucos segundos.
A velocidade de desenvolvimento aumentou. Mas a complexidade continua existindo.
Por isso, mais do que nunca:
Código gerado por IA sem SOLID é apenas uma forma mais rápida de criar problemas.
Já código estruturado com SOLID é mais fácil de entender, testar, revisar, evoluir e confiar.
E isso vale tanto para humanos quanto para as IAs que vão implementar a próxima feature.