
Por que SOLID importa — e quando não importa
SOLID é ensinado como lei. Na prática é ferramenta — e como toda ferramenta, tem contexto certo para usar e contexto certo para ignorar.
Aprendi SOLID numa fase onde eu queria ter respostas para tudo.
Era reconfortante. Cinco princípios com nomes bonitos que, se seguidos, produziriam código bom. Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion. Decorei os acrônimos, li os exemplos, e saí aplicando em qualquer código que eu tocava.
O resultado foi código mais complexo, mais difícil de entender, e — paradoxalmente — mais difícil de mudar.
O problema não era SOLID. O problema era que eu estava usando princípios de design como regras de aplicação obrigatória, não como heurísticas para pensar sobre problemas específicos.
Single Responsibility não significa "cada classe deve ter exatamente um método." Significa que uma classe deve ter apenas uma razão para mudar. A diferença é enorme. Uma classe com cinco métodos que todos servem ao mesmo propósito tem responsabilidade única. Uma classe com um método que lida com lógica de negócio E formatação de output E acesso ao banco tem três razões para mudar.
Open/Closed — aberto para extensão, fechado para modificação — não significa nunca mudar código existente. Significa que o design deve permitir adicionar comportamento novo sem precisar modificar o que já funciona. Isso é relevante em sistemas de plugin, em handlers extensíveis, em abstrações estáveis. Num script de processamento de dados que só você vai manter, o custo de abstrair para extensibilidade pode ser maior que o benefício.
Liskov Substitution foi o que mais me confundiu no início. A ideia: se B é subtipo de A, você deve poder substituir A por B sem quebrar o comportamento do programa.
Isso parece óbvio até você tentar explicar por que um Quadrado não deve herdar de Retângulo mesmo que um quadrado seja matematicamente um retângulo. A herança é sobre comportamento, não sobre taxonomia do mundo real. Essa distinção — modelar comportamento, não ontologia — mudou como eu penso sobre herança e composição.
Interface Segregation e Dependency Inversion se tornaram mais úteis quando eu comecei a escrever testes. Interfaces pequenas são mais fáceis de mockar. Dependências injetadas são mais fáceis de substituir em testes. SOLID e testabilidade andam juntos por razões não acidentais.
Quando SOLID não importa:
Em protótipos que provavelmente vão ser jogados fora. Em scripts one-off. Em código de colagem que conecta duas APIs e vai rodar uma vez. Nessas situações, o custo de aplicar os princípios — o tempo de pensar, a complexidade adicional — supera qualquer benefício.
Em equipes onde o código vai ser lido por muitas pessoas ao longo do tempo, SOLID importa porque torna o código mais previsível. Cada parte tem um propósito claro. Mudar uma coisa não quebra outra.
A heurística que uso: se o código vai ser mantido por mais de uma pessoa por mais de seis meses, vale a pena pensar em design. Se não — escreve, faz funcionar, e não se culpe por não ter aplicado todos os princípios.
O que SOLID realmente ensina, por baixo dos cinco princípios, é pensar sobre acoplamento e coesão. Acoplamento alto significa que mudar uma coisa força mudanças em outras. Coesão baixa significa que uma peça de código faz coisas demais sem relação entre elas.
Código com baixo acoplamento e alta coesão é mais fácil de entender, testar, e mudar. SOLID é um conjunto de práticas para chegar lá. Mas não é o único caminho, e não é obrigatório em todos os contextos.
Essa semana: pegue uma classe ou módulo do projeto atual e faça a pergunta — "quantas razões essa coisa tem para mudar?" Se a resposta for três ou mais, você tem uma candidata a refatoração. Se for uma, deixa como está.