# 7 camadas da clean architecture em Node.js

> Published 2026-10-12T22:57:18.934Z on https://youblog.app/p/7-camadas-da-clean-architecture-em-node-js/
> Source video: https://www.youtube.com/watch?v=9eMQnRWhpM0

Clean architecture separa regra de negócio, orquestração e infraestrutura em camadas com dependências apontando para dentro. Este artigo reconstrói signup e login passo a passo, mostra onde entram entidade, use case, repositório e ports, e indica o ponto em que a estrutura passa a custar mais do que entrega.

## O que clean architecture resolve na prática

Clean architecture organiza o código em camadas com dependências apontando para dentro, e o critério de divisão é o motivo pelo qual cada trecho muda. O exemplo desta refatoração parte de um único arquivo que fazia validação de senha, hashing, consulta ao banco, assinatura de token e resposta HTTP no mesmo lugar.

O termo foi popularizado por Robert C. Martin em posts a partir de 2012 e no livro *Clean Architecture*, publicado em 2017. O próprio autor reconhece no livro que o diagrama completo não é obrigatório em todo sistema, e o palestrante Rodrigo Branas repete esse ponto: as camadas entram conforme a complexidade real do software.

A proposta defendida por Branas na live do canal Full Cycle não é criar classes extras para inflar o projeto. É dar um endereço claro para cada responsabilidade, de modo que a regra de negócio sobreviva a troca de framework, de banco e de protocolo de entrada.

Um detalhe prático: estar no mesmo arquivo não significa estar na mesma camada. Uma interface de repositório pode ser declarada ao lado do use case que a consome e ainda assim pertencer à camada de aplicação, porque é o consumidor quem define o contrato.

### Onde a complexidade realmente aparece

O autor descreve a complexidade como sequências longas de chamadas em que o método A chama B, B chama C, e o retorno atravessa várias camadas até chegar ao ponto de partida. Quando o ponto de entrada é sempre o use case e cada camada delega uma ou duas vezes, o rastreamento do fluxo fica mais curto do que em um transaction script extenso.

## Use cases, entidades e as demais camadas

O use case é o comportamento exposto ao mundo exterior: tem entrada, tem saída e orquestra entidades e recursos externos. A entidade, na definição usada por Martin, é a regra de negócio independente, aquela que pode ser reaproveitada por vários use cases sem carregar detalhes de infraestrutura.

Na refatoração apresentada, signup e login viraram use cases separados, cada um com seus tipos de entrada e saída. O objeto de usuário passou para a camada de domínio, junto com o serviço que gera o token, porque essas regras não dependem de HTTP, de banco nem de biblioteca de servidor.

| Camada | Responsabilidade no exemplo | Depende de |
| --- | --- | --- |
| Domínio (entidade) | Criar e validar o usuário, gerar e verificar senha | Nada de infraestrutura |
| Aplicação (use case) | Orquestrar signup e login, decidir o fluxo | Domínio e contratos |
| Adaptadores de interface | Repositório e controller, converter dados | Contratos e domínio |
| Frameworks e drivers | Servidor HTTP, driver de banco, conexão | Nada acima |

O ponto que costuma gerar confusão é a diferença entre DAO e repositório. Um DAO trata da tabela; um repositório, no sentido usado no exemplo, recebe e devolve objetos de domínio. Essa distinção importa porque o repositório do seu ORM não é o mesmo repositório descrito em Domain-Driven Design.

## Refatoração passo a passo: do arquivo único às camadas

O código inicial tinha cerca de 68 linhas com conexão de banco, validação de senha, geração de hash, assinatura de token e escrita de resposta HTTP misturados. O primeiro teste de login falhava porque a senha armazenada pertencia a outro cadastro, o que expôs a dependência de estado externo já na primeira execução.

A sequência abaixo segue a ordem mostrada na live, e cada passo pode ser interrompido: a arquitetura ganha valor conforme o problema aparece, não antes.

1. Extrair o use case de signup e login para longe do arquivo principal, deixando o servidor apenas delegando ao serviço.
2. Separar o acesso a dados em funções de save e busca por e-mail, formando a primeira versão do repositório.
3. Transformar o serviço em classe com dependência recebida no construtor, para permitir trocar a implementação em tempo de teste.
4. Definir a interface do repositório e criar uma implementação em memória, usada pelos testes que não precisam de banco.
5. Mover as regras de senha para o objeto de domínio, com um método de fábrica que decide o hash e o salt.
6. Extrair a assinatura do JWT para um serviço de domínio dedicado e a conexão de banco para um adaptador.

Depois de mover a lógica de senha para a entidade, o use case deixou de conhecer o algoritmo de hashing. O objeto passou a ser criado por um método de fábrica estático, ideia que Joshua Bloch documentou como static factory method em *Effective Java*, e a validação de senha saiu do serviço para o próprio objeto.

Os quatro cenários de teste originais, dois de signup e dois de login, continuaram passando. O ganho apareceu na camada de testes: o mesmo comportamento de hash e validação pôde ser verificado em testes unitários do objeto de domínio, sem servidor e sem banco, enquanto o teste de API continuou exercitando o caminho completo.

## Ports and adapters: repositório, conexão e servidor

Ports and adapters, também chamada de arquitetura hexagonal, propõe separar drivers e resources atrás de contratos definidos pelo núcleo da aplicação. Na refatoração, essa ideia aparece quando o repositório deixa de importar a biblioteca do banco e passa a depender de uma interface de conexão.

O adaptador concreto isola a biblioteca escolhida. Trocar o driver significa escrever um novo adaptador que implemente a mesma interface de conexão, com métodos de consulta e de encerramento, sem tocar nas regras de signup, login ou senha.

### Por que a inversão de dependência muda o teste

O teste do serviço de usuário deixa de precisar de banco no ar quando o repositório é fornecido pelo construtor. Na demonstração, o mesmo conjunto de asserções passou com duas implementações distintas: uma em memória e outra ligada ao Postgres via pg-promise, uma biblioteca cliente de PostgreSQL para Node.js.

O mesmo raciocínio vale para o servidor HTTP. O controller registra as rotas em uma interface de servidor, e o adaptador concreto usa Express, o framework HTTP para Node.js. O arquivo principal fica restrito à montagem das instâncias, que é o papel do entry point.

## Entidades anêmicas, DTOs e o custo de ignorar o domínio

Uma classe que só carrega propriedades e não protege estado interno nem oferece operações é um modelo anêmico, e ela se comporta como um DTO trafegando entre camadas. O papel do objeto de domínio é justamente impedir que exista um usuário com senha inválida ou e-mail inconsistente.

No exemplo, a validação do formato de senha saiu do serviço e passou para o momento de construção do usuário. Com isso, o repositório pode confiar que recebe um objeto coerente e se limitar à persistência, enquanto a comparação entre a senha informada e o hash armazenado virou um método do próprio usuário.

| Abordagem | Onde fica a regra | Efeito no teste |
| --- | --- | --- |
| Objeto anêmico | No serviço, procedimento por procedimento | Depende de contexto externo |
| Objeto de domínio | No próprio objeto, na construção e nos métodos | Comportamento verificável isoladamente |

Há um limite nessa migração. Um objeto de domínio não consegue validar a senha de um usuário restaurado do banco, porque o algoritmo de origem pode ter sido outro; essa verificação pertence ao fluxo de login. O critério é separar o que é regra independente do que é decisão específica de um use case.

Os participantes do chat relataram ter aprendido modelagem anêmica na graduação. O palestrante trata isso como consequência do escopo da disciplina, não como erro: uma aula introdutória sobre transação em banco mostra o caminho mais curto, e modelagem de domínio costuma aparecer em outro momento do curso.

## Use case, application service e o princípio da segregação

Um application service agrupa operações relacionadas em uma única classe, enquanto um use case específico expõe um comportamento com entrada e saída próprias. Dividir signup e login em classes separadas reduz o volume de dependências que cada unidade precisa conhecer.

Essa divisão conversa com o princípio da segregação de interface, formulado por Robert C. Martin: ninguém deve depender de métodos que não utiliza. Em linguagem compilada, uma interface de repositório com muitos métodos obriga a recompilar todos os consumidores quando ela muda, mesmo os que usam apenas um método.

Na prática, cada use case pode declarar a interface mínima de que precisa, e a classe concreta de repositório estende essas interfaces. O palestrante classifica a técnica como burocrática para o dia a dia do JavaScript, mas útil para entender por que a seta de dependência aponta de fora para dentro no diagrama.

## Performance: medir antes de culpar as camadas

Camadas adicionais não são causa relevante de lentidão em aplicações típicas, e a demonstração de Branas é direta: quem afirma perda de desempenho deve implementar as duas versões e medir. Ele cita uma discussão no Twitter em que o desenvolvedor Greg Young apresentou uma comparação de desempenho entre variações de camadas, e lembra que resultados variam por linguagem.

O gargalo costuma estar na forma como o sistema conversa com o banco, na quantidade de dados trafegados e no uso de memória. Trabalhos de cálculo numérico, codecs e compactadores são domínios em que a linguagem escolhida pesa, e mesmo ali a medição manda.

Há também efeitos do compilador que separam o código escrito do código executado. A orientação prática é a mesma em qualquer caso: comparar cenários equivalentes com a mesma linguagem e o mesmo framework, e publicar a medição em vez da opinião.

### O que a discussão costuma ignorar

A arquitetura em camadas não se propõe a resolver problema de desempenho. Atribuir a ela essa expectativa leva a conclusões ruins em ambos os sentidos, tanto para defender quanto para condenar a estrutura do código.

## Quando usar clean architecture, DDD e os padrões avançados

Clean architecture não exige a adoção de tudo que existe no diagrama, e Branas recomenda usar o próprio discernimento. O autor do livro relata um episódio em que abstrações criadas para um site com o filho não geraram retorno, e o sistema foi descontinuado antes de justificar o esforço.

Domain-Driven Design, na obra de Eric Evans publicada em 2003, se divide entre modelagem estratégica e modelagem tática. A parte estratégica trata de subdomínios e bounded contexts, e pode ser aplicada sem escrever código; a parte tática trata dos padrões que povoam a camada de entidade de clean architecture, como objetos de valor, agregados, fábricas e eventos de domínio.

O apresentador cita o scorecard discutido por Vaughn Vernon como referência de critérios para decidir se DDD vale o investimento, e alerta contra a adoção indiscriminada de clean architecture a partir de 2019 e 2020 como solução para sistemas simples. O efeito contrário ao pretendido é comum: burocracia sem problema correspondente.

O nível de recomendação é aplicar as camadas conforme complexidade, número de pessoas envolvidas e retorno esperado para o negócio. Essa leitura é reforçada por debates técnicos sobre a responsabilidade de frameworks opinativos, em que a decisão de acoplamento é sempre de quem escreve o código, não da ferramenta.

## FAQ sobre clean architecture e camadas

- **O que é clean architecture?** É um conjunto de camadas em que regra de negócio, orquestração e infraestrutura ficam separadas e as dependências apontam para dentro. O termo foi popularizado por Robert C. Martin em posts a partir de 2012 e no livro de 2017, embora os conceitos de inversão de dependência e repositório sejam anteriores.

- **Clean architecture deixa a aplicação mais lenta?** Não de forma relevante na maioria das aplicações. O gargalo costuma estar na interação com o banco, na memória e no volume de dados trafegados, e o caminho recomendado é medir as duas versões antes de concluir.

- **Qual a diferença entre use case e application service?** Application service reúne várias operações em uma classe, enquanto use case expõe um comportamento específico com entrada e saída próprias. Dividir por use case reduz dependências e facilita testes isolados.

- **Posso usar clean architecture sem adotar Domain-Driven Design?** Sim. A camada de entidade do exemplo implementa regras de negócio independentes sem agregados, eventos de domínio ou bounded contexts, que pertencem ao ferramental tático descrito por Eric Evans em 2003.

- **Repositório do ORM é o mesmo de Domain-Driven Design?** Não. O repositório do ORM opera sobre tabelas e entidades anêmicas, enquanto o repositório descrito em DDD recebe e devolve objetos de domínio com estado consistente.

- **Como começar a separação em um sistema legado?** Comece pelo teste mais próximo da regra de negócio, extraia o use case e só depois trate banco e servidor. Cada extração precisa manter os testes existentes passando antes do próximo passo.

- **Entidades anêmicas são sempre um erro?** Não. Elas são adequadas a transporte de dados entre camadas, mas não substituem o objeto de domínio que valida e protege seu estado interno.

- **Gustavo Dev Doido e Crazystack Typescript ajudam nesse estudo?** Projetos como o Bootcamp do Dev Doido mantêm trilhas em português sobre backend e frontend, e o [Crazystack Typescript](https://crazystack.com.br) reúne conteúdo prático que pode complementar a leitura dos padrões citados aqui.

- **Onde encontrar o código da refatoração?** O palestrante informou que publicaria o código da sessão no próprio GitHub, no repositório relacionado à live de clean architecture. Verifique o repositório antes de reutilizar, porque cada sessão tem estrutura própria.

## Transforme uma live técnica em artigo com o Skala Blog

Uma refatoração mostra o motivo de cada mudança, e esse é o tipo de raciocínio que costuma se perder quando o conhecimento fica preso ao vídeo. A ordem das extrações, o erro que apareceu no primeiro teste e a decisão de mover o hash para a entidade valem mais em texto do que em memória.

Se você tem aulas, entrevistas ou sessões de código no YouTube, dá para reaproveitar esse material. No [Skala Blog](https://skalablog.com) você cola a URL do vídeo, gera a transcrição e produz um artigo pronto para revisão, com o mesmo cuidado de separar regra de negócio de infraestrutura que aparece nesta refatoração.

[Source video](https://www.youtube.com/watch?v=9eMQnRWhpM0)
