Pular para o conteúdo principal

Separação de Responsabilidades

Visão Geral

Separação de responsabilidades é o princípio de que cada parte do sistema deve tratar de um assunto, e de que assuntos distintos devem ficar em partes distintas.

A dificuldade inteira está em "assunto". O princípio é trivialmente aceito e raramente aplicado bem, porque a definição do que conta como um assunto separado é onde o julgamento acontece.

Problema

Código que mistura responsabilidades é difícil de mudar por uma razão precisa: para alterar um assunto, é preciso entender e não quebrar os outros que moram no mesmo lugar.

Uma função que valida entrada, aplica regra de negócio, formata saída e grava no banco tem quatro razões para mudar. Qualquer uma delas obriga a reler as outras três e arriscar quebrá-las.

O efeito composto é o que importa: cada assunto adicional no mesmo lugar não soma dificuldade, multiplica. Quatro assuntos misturados não são quatro vezes mais difíceis de mudar que um — são muito mais, porque as interações entre eles também precisam ser mantidas na cabeça.

Conceitos Centrais

O eixo é a razão de mudança

O critério operacional, e o mesmo que orienta modularidade: duas coisas são assuntos distintos se mudam por razões diferentes.

Validação de formato muda quando o contrato de entrada muda. Regra de negócio muda quando a empresa decide diferente. Persistência muda quando o esquema ou a tecnologia muda. Três razões independentes, três assuntos.

Isso é a formulação prática do Princípio da Responsabilidade Única, que fala em "uma razão para mudar" e é frequentemente lido como "fazer uma coisa só" — leitura que leva a fragmentar código sem critério.

Responsabilidades transversais

Alguns assuntos atravessam todo o sistema: log, autenticação, transação, telemetria, tratamento de erro.

Eles não podem ser isolados num módulo porque precisam estar em toda parte. A separação, aqui, é feita por outro mecanismo — middleware, decoradores, interceptadores, aspectos — que mantém o assunto em um lugar e o aplica em muitos.

Misturar transversais no código de negócio é a forma mais comum de violação do princípio, e a mais tolerada.

Separar não é fragmentar

O princípio diz que assuntos distintos ficam separados. Não diz que tudo deve ser pequeno.

Aplicá-lo mecanicamente produz o problema oposto: dezenas de unidades minúsculas que sempre mudam juntas, entre as quais o leitor precisa saltar para entender um fluxo. A separação aumentou o custo de leitura sem reduzir o de mudança — porque não havia razões de mudança independentes para começar.

Se duas coisas sempre mudam juntas, elas são um assunto só, e separá-las é erro.

Modelo Mental

Conte as razões pelas quais este código mudaria.

Se a lista tem mais de um item e os itens são independentes, há responsabilidades misturadas. Se tem mais de um item mas eles sempre ocorrem juntos, é um assunto só — e separar seria dano.

Quando Usar

  • Quando um trecho tem razões de mudança genuinamente independentes.
  • Quando um assunto precisa ser testado sem os outros.
  • Quando pessoas diferentes precisam alterar assuntos diferentes do mesmo fluxo.
  • Quando um assunto transversal está espalhado e duplicado.
  • Quando um assunto precisa ser substituído — trocar o provedor de pagamento sem tocar na regra de cobrança.

Quando Não Usar

Quando os assuntos sempre mudam juntos. É o caso mais importante e o mais ignorado. Separar aqui produz indireção pura: o leitor salta entre arquivos e não ganha nada, porque nunca vai alterar um sem o outro.

Quando a separação exige uma abstração que não se sustenta. Separar regra de negócio de persistência é fácil de enunciar e às vezes caro de fazer — se a regra depende de agregação que só o banco faz eficientemente, forçar a separação produz uma abstração que vaza ou um desempenho inaceitável.

Em código descartável. Protótipo, script de migração, análise pontual. Separar responsabilidades é investimento em mudança futura; onde não haverá mudança futura, o investimento não se paga.

Quando o custo de navegação supera o de mudança. Um fluxo que atravessa oito arquivos para fazer o que caberia legivelmente em um está separado demais. O sintoma é precisar de um diagrama para entender uma operação simples.

Alternativas

  • Coesão por proximidade — manter junto o que muda junto, sem impor separação formal. É o default correto até que razões independentes apareçam.
  • Separação por convenção — mais barata e menos confiável que separação imposta.
  • Aspectos e middleware — para transversais, é a alternativa correta à separação por módulo.

Trade-offs

O eixo é custo de mudar um assunto versus custo de entender o fluxo inteiro.

Mais separaçãoMenos separação
Mudança isolada em um assuntoMudança exige entender vizinhos
Cada parte testável sozinhaTeste carrega tudo
Substituir um assunto é viávelSubstituição toca tudo
Fluxo exige saltar entre arquivosFluxo legível linearmente
Abstrações a manter e justificarSem abstração intermediária

Vale notar que os dois lados falham do mesmo jeito no extremo: código impossível de entender. As causas são opostas.

Modos de Falha

Abstração vazada. A separação existe formalmente, mas o consumidor precisa saber como o outro lado funciona. Um repositório que devolve estruturas do ORM não separou persistência de domínio.

Separação no eixo errado. Assuntos que mudam juntos foram separados; os que mudam independentemente ficaram juntos. Pior que não separar, porque tem o custo sem o benefício.

Transversal espalhado. Tratamento de erro replicado em cada função, com variações sutis. Quando a política muda, muda em trinta lugares — e em dois deles alguém esquece.

Camadas anêmicas. Camadas que existem por simetria e apenas repassam chamadas, sem tratar assunto nenhum. Custo de navegação sem separação real.

Erros Comuns

Ler o Princípio da Responsabilidade Única como "faça uma coisa só". Leva a fragmentar sem critério. A formulação correta é sobre razões de mudança.

Separar por tipo técnico em vez de por assunto. Todos os validadores num lugar, todos os mapeadores em outro. Agrupa o que muda por razões diferentes.

Aceitar transversal misturado por conveniência. Log e transação dentro da regra de negócio parecem inofensivos e são a violação mais comum.

Confundir com camadas. Camadas são uma forma de separar responsabilidades, não a definição dela. Um sistema em camadas pode ter responsabilidades tremendamente misturadas dentro de cada uma.

Exemplo Real

Uma função de processamento de pedido, com 180 linhas, fazia: validar o payload, verificar estoque, calcular impostos, aplicar desconto, gravar, emitir evento e enviar e-mail.

A pergunta aplicada foi "quantas razões de mudança?". A resposta revelou algo que a contagem de linhas não revelava.

Cinco razões distintas: o contrato de entrada, a regra fiscal, a política comercial de desconto, o esquema de persistência, e a integração de notificação.

Mas duas coisas que pareciam separáveis — verificar estoque e gravar o pedido — sempre mudavam juntas, porque a reserva de estoque fazia parte da mesma transação. Separá-las teria criado uma abstração que precisaria ser furada na primeira alteração.

O resultado: cinco unidades, não sete. E a mais valiosa foi a de regra fiscal, que passou a ser alterável e testável sem tocar em nada do resto — o que importava porque regra fiscal muda por decisão externa, com prazo, várias vezes por ano.

Conceitos Relacionados

  • Modularidade — a estrutura que materializa a separação.
  • Coesão — a medida de se o que ficou junto pertence junto.
  • Abstração — o mecanismo que torna a separação possível.

Exercício Prático

Escolha a função mais longa do seu sistema e liste as razões pelas quais ela mudaria. Seja específico: não "mudança de regra", mas "quando o time fiscal alterar a alíquota".

Para cada par de razões, pergunte: já aconteceu de uma mudar sem a outra?

Só os pares que já divergiram justificam separação. Os demais são um assunto só.

Perguntas de Entrevista

  • Como identifica responsabilidades misturadas?
  • Quando separar responsabilidades piora o código?
  • Qual a diferença entre separação de responsabilidades e camadas?

Para Aprofundar

  • Dijkstra, Edsger. On the role of scientific thought, 1974 — origem do termo.
  • Martin, Robert C. Clean Architecture. Prentice Hall, 2017 — o Princípio da Responsabilidade Única em termos de razão de mudança.