# Como aplicar o princípio da responsabilidade única hoje

> Published 2026-10-11T13:55:51.988Z on https://www.crazystack.com.br/pt/p/como-aplicar-o-principio-da-responsabilidade-unica-hoje/
> Source video: https://www.youtube.com/watch?v=FLaOpbHdiFQ

A definição mais popular do princípio da responsabilidade única, 'uma classe, uma responsabilidade', é justamente a que menos ajuda. A versão útil é outra: uma classe deve ter apenas uma razão para mudar. É essa leitura que guia a refatoração abaixo.

## O que é o princípio da responsabilidade única

O princípio da responsabilidade única (SRP) afirma que uma classe deve ter apenas uma razão para mudar. O S do SOLID, popularizado por Robert C. Martin no início dos anos 2000, não fala de quantas coisas a classe faz, mas de quantos motivos externos existem para você editar o arquivo dele ([Agile Software Development, Robert C. Martin, 2002](https://www.pearson.com/en-us/subject-catalog/p/agile-software-development-principles-patterns-and-practices/P200000009445)).

Essa leitura resolve a confusão mais comum. Perguntar 'quantas responsabilidades essa classe tem?' é subjetivo: quem decide o que conta como responsabilidade? Perguntar 'quantos atores pedem mudanças nessa classe?' é concreto. Se mudanças de validação, de regra de negócio e de banco de dados todas passam pelo mesmo arquivo, ele tem três razões para mudar.

Você pode lembrar desse conteúdo por aulas e mentorias que circulam na comunidade, como as de Felipe Rocha no Full Stack Club e materiais de nomes como Gustavo Dev Doido. A base, porém, é sempre a mesma ideia do SRP aplicada camada por camada.

## Por que 'uma responsabilidade por classe' confunde mais do que ajuda

A definição 'uma classe pode ter apenas uma responsabilidade' parece simples e na prática não diz nada verificável. Toda classe faz várias coisas menores: formata strings, chama métodos, lança erros. Se você levar essa frase ao pé da letra, acaba fragmentando o código sem ganho real.

Já 'uma razão para mudar' dá um teste objetivo. Em uma aplicação web típica existem três motivos de mudança recorrentes, e cada um pertence a uma camada diferente:

- **Recepção e validação da requisição** — mudou o formato dos dados de entrada? Você edita o driver.
- **Regras de negócio** — agora e-mails podem se repetir? Você edita a application.
- **Persistência** — trocou PostgreSQL por MongoDB? Você edita o resource.

Quando as três mudanças batem no mesmo handler, você tem um arquivo acoplado a três atores diferentes. É isso que o SRP proíbe.

## Um handler Node.js que viola o SRP

O exemplo clássico é uma rota `POST /users` que cria usuário e faz tudo dentro do handler: valida o formato dos dados (e-mail válido, senha com mais de 8 caracteres), aplica a regra de negócio (verificar se já existe usuário com o mesmo e-mail) e persiste no banco com hash de senha. Um único arquivo, três motivos para mudar.

Na versão construída no vídeo de 2026 do canal Full Stack Club, o projeto usa [Fastify](https://fastify.dev/), framework backend para Node.js focado em performance e tipagem, com [Zod](https://zod.dev/) para validar e tipar o body das rotas e [Drizzle ORM](https://orm.drizzle.io/) para falar com o PostgreSQL. A documentação do Fastify ainda sai pronta via integração com Swagger.

O problema não é o tamanho do arquivo, é o acoplamento. Mudar a validação do e-mail toca esse código. Mudar a regra de duplicidade toca esse código. Trocar o banco toca esse código. Cada mudança arrisca quebrar as outras duas.

## Arquitetura hexagonal: o mapa das responsabilidades

A arquitetura hexagonal, proposta por Alistair Cockburn nos anos 2000, divide a aplicação em três camadas e é a forma mais direta de respeitar o SRP no backend ([Hexagonal Architecture, Alistair Cockburn](https://alistair.cockburn.us/hexagonal-architecture/)). Cada camada responde a uma única razão para mudar.

| Camada | Responsabilidade | Exemplo no artigo |
| --- | --- | --- |
| Driver | Receber a requisição e validar os dados | Rota Fastify com schema Zod |
| Application | Executar as regras de negócio | Use case CreateUser |
| Resource (driven) | Persistir dados ou chamar serviços externos | UserDAO com Drizzle |

O driver não sabe o que é regra de negócio. A application não conhece HTTP nem banco. O resource só conversa com o banco de dados ou com uma fila como SQS. Quando cada camada se limita ao seu papel, cada classe dentro dela herda a mesma disciplina: uma razão para mudar.

## Refatoração passo a passo: do handler ao use case

A refatoração do vídeo segue uma sequência reproduzível. Ela funciona em qualquer stack com orientação a objetos, inclusive em projetos orientados por cursos como o Crazystack Typescript ou o Bootcamp do Dev Doido, porque depende apenas de separar camadas e não de uma biblioteca específica.

1. **Escreva (ou confirme) os testes** antes de mexer em qualquer linha. Refatorar sem testes é editar às cegas: você não tem como saber se quebrou o comportamento.
2. **Crie o use case** na pasta `application`. A classe `CreateUser` com um método `execute` recebe a regra de negócio que estava no handler: verificar e-mail duplicado, comparar senha com a confirmação e gerar o hash.
3. **Defina DTOs de entrada e saída.** O use case não conhece `request` nem `response`; um InputDTO e um OutputDTO em TypeScript fixam o contrato entre driver e application. No output, por exemplo, a senha nunca volta.
4. **Crie erros customizados** na application, como `PasswordDoesntMatchError` e `EmailAlreadyInUseError`. O use case lança o erro de negócio; o driver decide o status HTTP correspondente, 400 ou 409.
5. **Enxugue o handler.** Ele passa a fazer três coisas: validar com Zod, chamar `execute` e mapear erros para respostas. Nada mais.

Um detalhe prático do vídeo: um teste que verificava a resposta 500 quando o banco fica inacessível foi removido durante a refatoração, porque a rota deixou de chamar o banco diretamente e o teste cobria um cenário em que todos os outros já falhariam. Nem todo teste sobrevive a uma mudança de arquitetura.

## DAO: tirando a persistência do use case

Mesmo depois do passo anterior, o use case ainda tinha duas razões para mudar: regra de negócio e persistência. A solução é o padrão Data Access Object, descrito no livro *Patterns of Enterprise Application Architecture* de Martin Fowler ([P of EAA, 2002](https://martinfowler.com/books/eaa.html)): uma classe que chama o banco e retorna o que está lá, nada além disso.

O `UserDAO` criado em `src/resources` expõe dois métodos: `create`, que grava o usuário e retorna nulo se falhar, e `findByEmail`, que procura por e-mail e retorna nulo quando não encontra. O Drizzle fica confinado aqui dentro; o use case passa a depender do DAO e não sabe mais que o Drizzle existe.

Com isso, cada arquivo do projeto tem exatamente um motivo para mudar. Mudou a regra de e-mail duplicado? Você edita o `CreateUser`. Trocou o ORM? Você edita o DAO. Mudou o contrato da API? Você edita a rota. O commit do vídeo fecha o ciclo com `add user dao`.

## Testes como rede de segurança da refatoração

O critério de sucesso da refatoração não é 'parece melhor', é 'os testes continuam passando'. O projeto do vídeo roda contra um PostgreSQL subido via Docker Compose, e os testes cobrem os cenários de negócio: e-mail duplicado retorna 409, senha e confirmação divergentes retornam 400.

Sem essa rede, mover código entre camadas é arriscado demais para valer a pena. A ordem recomendada é sempre a mesma: teste verde antes, refatora, teste verde depois. Se você não tem testes, escrever eles é o primeiro passo do SRP, não o último.

## Perguntas frequentes sobre o princípio da responsabilidade única

- **O SRP significa que uma classe só pode ter um método?** Não. Uma classe pode ter quantos métodos forem necessários, desde que todos respondam à mesma razão para mudar. O teste é quem pede mudanças nela, não a contagem de métodos.
- **Preciso de arquitetura hexagonal para aplicar o SRP?** Não, mas a arquitetura hexagonal dá o mapa mais claro de onde cada responsabilidade mora: driver, application e resource. Você pode aplicar o SRP em pastas simples como `controllers`, `services` e `repositories`.
- **Use case e service são a mesma coisa?** Na prática, ambos moram na camada de application e guardam regras de negócio. Use case costuma denotar uma operação única com um método `execute`; service pode agrupar operações relacionadas a uma entidade.
- **Como sei que uma classe viola o SRP?** Liste os motivos externos que forçariam uma edição nela. Se você nomeia dois atores diferentes (o time de produto mudando regra e o time de infraestrutura mudando banco), há violação.
- **O SRP vale só para classes?** O princípio se aplica a qualquer unidade de código: módulos, funções e camadas. Em uma API REST, a leitura por camadas é a aplicação mais útil no dia a dia.

## Transforme aulas em vídeo em artigos com o Skala Blog

Separar uma razão para mudar por camada é o que torna um código entendível meses depois. O mesmo vale para conteúdo: uma aula de trinta minutos sobre SRP vira um texto muito mais útil quando você extrai dela a estrutura, os passos e o exemplo.

Se você tem conhecimento valioso gravado em vídeos do YouTube, aulas, mentorias, entrevistas ou opiniões, o [Skala Blog](https://skalablog.com) transforma esse material em artigo: você cola a URL do vídeo, o conteúdo é transcrito e vira um texto estruturado e pronto para revisar. É a sua aula sobre arquitetura, agora em formato que dá para buscar, citar e reler.

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