Entenda como a divisão entre Controller, Service e Repository garante escalabilidade e facilita a manutenção de sistemas modernos.
No desenvolvimento de software, a organização do código é tão importante quanto a sua funcionalidade. Uma API desestruturada pode funcionar no primeiro dia, mas rapidamente se torna um pesadelo de manutenção. Para evitar o acúmulo de dívida técnica, a indústria consolidou um padrão de divisão em três camadas principais: Controller, Service e Repository.
Esta estrutura baseia-se no princípio da Responsabilidade Única. Cada camada tem um papel estrito e não deve assumir tarefas que pertencem a outra.
1. Controller: A Interface de Entrada
A camada de Controller atua como o ponto de contato entre o cliente (como um aplicativo ou navegador) e a aplicação. Sua função é puramente administrativa e de fluxo.
- Responsabilidades: Receber a requisição HTTP, validar a presença de parâmetros obrigatórios, extrair dados de cabeçalhos (headers) e do corpo (body) da mensagem.
- O que não deve fazer: O Controller jamais deve conter regras de negócio, como cálculos de impostos ou validações de permissões complexas.
Após organizar os dados recebidos, o Controller os repassa para o Service correspondente. Assim que recebe o retorno, ele monta a resposta final com o status code adequado (200 OK, 201 Created, 400 Bad Request, etc.).
O que o Controller DEVE fazer:
- Capturar dados: Ler parâmetros de URL, cabeçalhos (headers) e o corpo (body) da requisição.
- Validar o formato: Verificar se o JSON enviado possui os campos obrigatórios e os tipos de dados corretos.
- Delegar: Repassar os dados já organizados para o Service responsável.
- Responder: Retornar o status HTTP adequado (ex: 201 para criação, 404 para não encontrado) e o corpo da resposta.
O que o Controller NÃO DEVE fazer:
- Lógica de Negócio: Nunca deve realizar cálculos, aplicar descontos ou validar regras de permissão complexas.
- Acesso a Dados: Jamais deve importar um modelo de banco de dados ou executar queries diretamente.
2. Service: O Coração da Lógica de Negócio
O Service é onde a inteligência da aplicação reside. É nesta camada que as regras de negócio são aplicadas, processamentos são realizados e cálculos são executados.
Uma característica fundamental do Service é que ele deve ser agnóstico à tecnologia de transporte. Isso significa que o Service não "sabe" o que é HTTP. Ele não deve lidar com objetos de requisição ou resposta do framework web.
Exemplo Prático: Se uma rota de busca permite filtrar nomes por vírgula (
?nomes=Ana,João), o Controller deve transformar essa string em um array de strings antes de passá-la ao Service. O Service recebe o dado já estruturado, focado apenas na lógica de filtragem.
Além de desconhecer o protocolo de entrada, o Service também não interage diretamente com o banco de dados. Ele solicita os dados de que precisa à próxima camada: o Repository.
O que o Service DEVE fazer:
- Processamento Central: Executar cálculos, aplicar regras de negócio e validações lógicas (ex: verificar se um saldo é suficiente).
- Orquestração: Chamar múltiplos Repositories ou serviços externos se a operação exigir.
- Trabalhar com Dados Estruturados: Receber tipos de dados limpos (como arrays e objetos) e não strings brutas vindas da URL.
O que o Service NÃO DEVE fazer:
-
Conhecer o HTTP: Não deve lidar com objetos de
requestouresponse, nem saber o que é um "Status Code". - Montar Queries: Não deve conter código SQL ou sintaxe específica de bancos de dados. ## 3. Repository: A Camada de Persistência
O Repository é o especialista em dados. Sua única missão é gerenciar a comunicação com o mecanismo de armazenamento, seja ele um banco de dados SQL, NoSQL ou até uma integração com um sistema de arquivos.
- Foco Técnico: Aqui ficam as queries (consultas) e a lógica de persistência.
- Isolamento: O Repository não toma decisões de negócio. Ele apenas executa comandos como "buscar usuário por ID" ou "salvar nova transação".
Ao isolar o acesso aos dados, tornamos o sistema flexível. Se no futuro for necessário trocar o banco de dados, as alterações ficam restritas apenas aos Repositories, sem afetar a lógica central da aplicação.
O que o Repository DEVE fazer:
- Operações de CRUD: Criar, ler, atualizar e deletar registros no banco de dados.
-
Abstrair a Query: Conter a implementação técnica da busca (ex:
SELECT * FROM users WHERE id = ?). - Mapeamento: Converter os dados brutos do banco para objetos que o Service consiga entender.
O que o Repository NÃO DEVE fazer:
- Tomar Decisões: Não deve decidir se um usuário "pode" ser deletado; ele apenas executa a deleção quando solicitado.
- Encadear Lógicas: Evitar chamadas de um Repository para outro; essa coordenação deve vir do Service.
Por que utilizar esta estrutura?
A separação de contextos traz benefícios tangíveis para o ciclo de desenvolvimento:
- Testabilidade: Com responsabilidades divididas, podemos criar testes automatizados muito mais assertivos. É possível testar a lógica do Service isoladamente, simulando (mocking) as respostas do banco de dados.
-
Reutilização de Código: Um método de um Repository, como o
getUserById, pode ser utilizado por diversos Services diferentes. Isso evita a duplicidade de código e facilita correções globais. - Manutenibilidade: Quando surge um erro, é mais fácil identificar onde ele está. Problemas de conexão com o banco? Verifique o Repository. Erro no cálculo de um desconto? O problema está no Service.
Top comments (0)