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).
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, framework backend para Node.js focado em performance e tipagem, com Zod para validar e tipar o body das rotas e Drizzle ORM 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). 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.
- 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.
- Crie o use case na pasta
application. A classeCreateUsercom um métodoexecuterecebe a regra de negócio que estava no handler: verificar e-mail duplicado, comparar senha com a confirmação e gerar o hash. - Defina DTOs de entrada e saída. O use case não conhece
requestnemresponse; um InputDTO e um OutputDTO em TypeScript fixam o contrato entre driver e application. No output, por exemplo, a senha nunca volta. - Crie erros customizados na application, como
PasswordDoesntMatchErroreEmailAlreadyInUseError. O use case lança o erro de negócio; o driver decide o status HTTP correspondente, 400 ou 409. - Enxugue o handler. Ele passa a fazer três coisas: validar com Zod, chamar
executee 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): 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,serviceserepositories. - 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 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.
Fork this article
Start a new branch from the same video, shaped your way. You keep the credit; the original keeps the attribution.
A fork in another language is filed as a translation of this article, so the two pages point at each other. You can unlink it later from the editor.
0/240
You are creating
- Format
- For
- Language
- Source
- Your angle
You will be asked to sign in before it is generated.
Buy credits