Separação de responsabilidades em camadas
Como dividir um sistema em camadas de apresentação, domínio e dados, por que as dependências apontam para dentro e como isso protege a regra de negócio.
Neste artigo
Há uma pergunta que todo desenvolvedor enfrenta assim que um projeto cresce além de um punhado de arquivos: onde eu coloco isto? A tela, a regra de negócio, o acesso ao banco, a validação, a formatação — tudo isso precisa morar em algum lugar, e sem um critério claro esses pedaços se misturam. Regra de negócio acaba dentro do botão da tela, consulta de banco vaza para o meio de um cálculo, e um sistema que começou simples vira um bloco onde tudo toca tudo. A resposta clássica e duradoura para esse problema tem um nome modesto: separação de responsabilidades em camadas.
A ideia é organizar o sistema em faixas horizontais, cada uma com um tipo de trabalho bem definido, empilhadas de tal forma que cada faixa só conhece as regras da que está logo abaixo — ou, na versão mais refinada, de tal forma que todas apontem para o centro onde vive o que realmente importa. Não é uma tecnologia nem um framework; é uma disciplina de arrumação. E, como toda boa arrumação, seu valor só fica óbvio quando você precisa achar ou trocar alguma coisa depressa.
Neste artigo vamos percorrer as camadas típicas de um sistema, entender a regra que governa a direção das dependências, ver por que a regra de negócio não deve saber que banco ou framework existem, e discutir os benefícios reais e as armadilhas frequentes. O objetivo é que, ao final, você tenha um mapa mental para decidir onde cada linha de código pertence.
As camadas típicas de um sistema#
Embora os nomes variem entre autores e comunidades, a maioria dos sistemas bem organizados se decompõe em três grandes territórios, com uma quarta preocupação transversal.
- Apresentação: a borda que conversa com o mundo externo. É a interface de usuário, a página web, a resposta de uma API, a tela de um aplicativo. Sua função é traduzir: pegar a intenção de quem está de fora e transformá-la em algo que o sistema entende, e depois pegar o resultado do sistema e apresentá-lo de volta num formato adequado. Ela cuida de botões, formatos, códigos de resposta, layout — e não deveria conter regra de negócio nenhuma.
- Aplicação e domínio: o coração. Aqui vivem as regras que definem o que o sistema é e o que ele faz — as decisões, os cálculos, as políticas, os fluxos de trabalho. É a camada que sabe que um pedido só pode ser cancelado antes do envio, que um saldo não pode ficar negativo, que um desconto se aplica sob certas condições. Frequentemente separamos aqui uma fatia de "aplicação" (orquestração de casos de uso, o roteiro de cada operação) de uma fatia de "domínio" puro (as regras e conceitos essenciais), mas as duas formam o miolo pensante do sistema.
- Dados e infraestrutura: a borda que conversa com o mundo técnico. Banco de dados, sistema de arquivos, filas de mensagem, serviços externos, envio de e-mail. É a camada que sabe como persistir e recuperar coisas, como falar SQL, como chamar uma API de terceiro. Sua função é executar o trabalho braçal de entrada e saída para que o domínio não precise se sujar com esses detalhes.
Essa divisão parece óbvia quando escrita assim, mas o valor está menos na existência das camadas e mais na relação entre elas. É a regra que governa quem pode depender de quem que dá o poder ao arranjo.
A regra da dependência: sempre para dentro#
O princípio mais importante da arquitetura em camadas cabe numa frase: as dependências apontam para dentro, nunca para fora. A camada de apresentação depende do domínio; a camada de dados depende do domínio; mas o domínio não depende de nenhuma das duas. O centro é ignorante das bordas. A regra de negócio não sabe que existe uma tela nem que existe um banco.
Isso costuma soar de trás para frente na primeira vez que se escuta, porque a intuição ingênua sugere que o domínio "usa" o banco e portanto deveria depender dele. Mas depender é diferente de usar. O domínio de fato precisa persistir coisas — só que ele expressa essa necessidade em termos abstratos, na sua própria linguagem, e delega a execução para fora sem saber quem executa. Ele diz "salve este pedido" contra uma interface que ele mesmo define, e alguém lá na borda de dados cumpre a promessa. A seta da dependência, portanto, vai da borda de dados em direção ao domínio, e não o contrário.
Visualize um alvo de dardos. No centro, o domínio, protegido. Ao redor, os anéis das aplicações e casos de uso. Na periferia, tudo que é volátil e técnico: telas, bancos, frameworks, protocolos. As setas de dependência apontam sempre do anel externo para o interno. O que é estável e essencial fica no meio; o que é substituível e detalhista fica na borda. Quando você respeita essa direção, protege o que é caro de mudar (as regras do negócio) das oscilações do que é barato e frequente de mudar (a tecnologia da vez).
A regra de negócio não conhece banco nem framework#
Vale demorar nesse ponto porque ele é a alma da coisa e o que mais se viola na prática. Quando dizemos que o domínio não conhece banco nem framework, estamos dizendo que o código que expressa as regras essenciais do seu negócio não deveria mencionar SQL, não deveria importar a biblioteca do banco, não deveria saber se os dados vêm de Postgres, de um arquivo ou de uma chamada de rede. Ele também não deveria depender do framework web da moda, do formato JSON, do protocolo HTTP.
Por que essa disciplina rígida? Porque bancos, frameworks e protocolos são detalhes, e detalhes mudam. A empresa troca de banco, migra para a nuvem, adota um framework novo, muda o formato da API. Se as regras de negócio estiverem entrelaçadas com esses detalhes, cada troca de tecnologia vira uma cirurgia de risco no coração do sistema. Mas se o domínio permanece puro — expresso apenas em termos dos conceitos do próprio negócio, sem contaminação técnica — então trocar o banco vira um trabalho localizado na borda, sem tocar uma linha de regra.
Há também um ganho de clareza que é fácil subestimar. Código de domínio puro se lê como uma descrição do negócio, não como um manual técnico. Quem abre o miolo do sistema encontra as regras nuas, sem o ruído de conexões, cursores e serialização. Isso torna o sistema mais fácil de entender, de discutir com pessoas não técnicas e de manter ao longo dos anos, quando as pessoas que o escreveram já se foram e restam apenas as regras.
Contratos e interfaces entre camadas#
A cola que permite que o domínio delegue trabalho sem depender de quem executa são os contratos — interfaces, no vocabulário de muitas linguagens. Um contrato é uma promessa expressa em abstrato: uma lista de operações com suas entradas e saídas, sem dizer como são cumpridas. O domínio define o contrato "algo que sabe guardar e buscar pedidos" e programa contra essa promessa. A camada de dados fornece uma implementação concreta que honra o contrato falando com o banco de verdade.
O truque elegante é que o contrato pertence ao domínio, não à infraestrutura. É o centro que dita os termos, e a periferia que se adapta a eles. Essa inversão é o que mantém a seta de dependência apontando para dentro mesmo quando os dados fisicamente fluem para fora. O domínio não pergunta ao banco "o que você oferece?"; ele declara "eis o que eu preciso", e a borda se conforma.
Esses contratos são também as costuras onde o sistema se abre para o teste e para a troca. Como o domínio depende de uma promessa e não de uma implementação, você pode encaixar ali qualquer coisa que cumpra a promessa — o banco real em produção, uma versão em memória nos testes, um dublê durante o desenvolvimento. As interfaces entre camadas são, ao mesmo tempo, a fronteira de responsabilidade e o ponto de flexibilidade.
Os benefícios reais#
Toda essa disciplina não é ginástica intelectual; ela paga dividendos concretos.
- Testabilidade: com o domínio isolado das bordas por contratos, você testa as regras de negócio sem subir banco, sem servidor, sem rede. Os testes ficam rápidos, determinísticos e focados exatamente na lógica que mais importa proteger. A parte cara e frágil do sistema de testes — tudo que envolve infraestrutura real — fica confinada à borda.
- Troca de tecnologia: quer migrar de um banco para outro, trocar o framework web, mudar de e-mail para fila de mensagens? Se as camadas estão bem separadas, o impacto se limita à periferia. O coração permanece intocado, e a troca deixa de ser um projeto de reescrita para virar uma substituição de peça.
- Clareza e divisão de trabalho: as camadas dão a cada tipo de código um endereço óbvio. Quem procura uma regra sabe onde ela mora; quem procura o acesso a dados sabe onde ele vive. Pessoas diferentes podem trabalhar em camadas diferentes com menos colisão, e uma pessoa nova encontra o sistema navegável em vez de labiríntico.
- Longevidade: talvez o benefício mais profundo. Regras de negócio duram décadas; tecnologias duram alguns anos. Ao proteger o durável do volátil, a arquitetura em camadas permite que o valor essencial do sistema sobreviva a muitas gerações de ferramentas.
As armadilhas mais comuns#
Camadas mal aplicadas podem trazer tanto atrito quanto ordem. Vale conhecer os erros típicos para não cair neles.
- Camadas anêmicas: o sintoma em que o domínio vira apenas um saco de dados sem comportamento, e toda a lógica real escapa para a camada de aplicação ou, pior, para a de apresentação. As regras que deveriam estar protegidas no centro se espalham pelas bordas, e a separação vira teatro: existem pastas com os nomes certos, mas o coração está oco.
- Vazamento de detalhes: quando conceitos técnicos da borda escorregam para dentro. Um objeto de domínio que carrega anotações do banco, uma regra que menciona formato JSON, um erro de SQL que borbulha até a tela sem tradução. Cada vazamento fura a fronteira e reintroduz o acoplamento que as camadas existiam para evitar.
- Over-engineering: o excesso oposto. Sistemas pequenos afogados em camadas, interfaces e indireções que ninguém pediu, onde acompanhar uma requisição simples exige atravessar sete arquivos. A separação em camadas é um investimento, e como todo investimento só compensa acima de certa escala. Um script de trezentas linhas não precisa de arquitetura hexagonal.
- A fronteira burocrática: quando cada camada apenas repassa dados para a próxima sem agregar nada, criando objetos espelhados e conversões mecânicas em cada passagem. Camadas devem existir porque cada uma faz um trabalho distinto e real, não para cumprir um ritual.
O bom senso aqui é entender que camadas são um meio, não um fim. Elas existem para tornar a mudança barata e o sistema claro. Quando estão produzindo o oposto — mais cerimônia do que proteção — algo se inverteu, e vale recuar.
Onde colocar cada código: um guia rápido#
Diante de uma linha de código órfã, a pergunta orientadora é: que tipo de conhecimento isto representa? Se é conhecimento sobre como apresentar — formato, layout, código de resposta, tradução de entrada externa —, é apresentação. Se é conhecimento sobre o que o negócio decide — uma regra, uma política, um cálculo, uma condição —, é domínio. Se é conhecimento sobre como conversar com o mundo técnico — persistir, buscar, enviar, integrar —, é infraestrutura.
Um teste prático e revelador: imagine que amanhã o negócio troque de banco de dados e de framework web ao mesmo tempo. Que código teria que mudar? Se a resposta inclui suas regras de negócio, elas estão no lugar errado — vazaram para a borda ou a borda vazou para elas. Num sistema bem estratificado, essa troca dupla deixa o domínio inteiramente em paz. Esse é o padrão-ouro contra o qual medir a arrumação.
Conclusão#
Separar responsabilidades em camadas é, no fundo, dar a cada tipo de decisão o seu devido lugar e organizar as dependências para que o essencial fique protegido do acidental. A apresentação traduz para o mundo externo, a infraestrutura conversa com o mundo técnico, e no centro, blindado pela regra da dependência que aponta sempre para dentro, vive o domínio — as regras que definem o que o sistema realmente é.
Feita com bom senso, essa organização torna o sistema testável, adaptável a novas tecnologias e legível para quem chega depois. Feita em excesso, vira burocracia; feita pela metade, vira teatro de pastas vazias. O equilíbrio se encontra lembrando por que as camadas existem: proteger o que é caro de mudar das oscilações do que é barato de trocar. Da próxima vez que hesitar sobre onde uma linha pertence, pergunte que tipo de conhecimento ela carrega e o que a manteria intacta numa troca de tecnologia. A resposta quase sempre aponta a camada certa.