Controller acessando Repository é uma boa prática?

24 respostas
javaprogramação
E

Bom dia, pessoal. Será que é uma boa prática o controller acessar os repository, diretamente. Dessa forma poupa alguns códigos que seriam apenas de repasse do service para repository.

Por outra parte, não sei se fica tão robusto. A principio os services definiriam claramente a fronteira de nossa aplicação (regras de negócio) com apresentação.

Qual é a experiência de vcs neste ponto?

24 Respostas

J

Eu particularmente sempre centralizei em classes de serviço, deixando somente no controller o que diz respeito à camada de apresentação, tudo o que diz respeito à domínio internalizado nos services, mesmo que em um primeiro momento não houvessem regras a serem aplicadas.

E

Pois é, às vezes parece perda de tempo, pq muitos services apenas estariam delegando para os repository.

Por outra parte a evolução é mais tranquila, se tiver qualquer regra é só colocar no service.

Também me deu a impressão de ficar mais robusto, com uma fronteira bem definida. Tudo que passa pelo services tem validação, todos os parâmetros são validados.

Qual forma será mais utilizada no mercado?

A

Olha, se teu service tá apenas delegando para o repository sem qualquer regra de negócio aplicada, eu acho perda de tempo mesmo.

Você pode ter 100 endpoints no seu sistema, e em apenas um precisa de uma lógica extra? Adiciona o service só ali. Não vejo vantagem em adicionar essa camada ali só pra manter consistência.

Se precisar inserir regra depois, cria o service. Não precisa pagar o preço da burocracia antes.

J

Pra consultas direto no banco também acho perda de tempo ficar criando um método no service só pra chamar um método do repositório. É um capricho que deixa o desenvolvimento burocrático. Se um dia mudar, refatora, mas isso não é rotineiro.

E

No caso de uma consulta que tenha um filtro obrigatório, seria melhor deixar num service para poder levantar uma exceção de negócio?

J

Nesse caso você vai ter um service (ou qualquer outro mecanismo como Bean Validation) que vai validar os dados do filtro. O método do repositório que vai retornar o resultado só deve ser chamado caso passar nessa validação.

M

Manter as fronteiras definidas entre controller, service e repository é sempre a melhor solução. Hoje as regras de negócio podem ser simples, mas conforme a aplicação evolui, vão ficando mais complexas. Imagina ter que alterar 20 controllers pra incluir uma modificação qualquer de um Dao, quando bastaria mexer em 1 classe de serviço?! Escreva o código pensando no futuro tbm (manutenção, performance, legibilidade).

J

Não precisa amarrar o retorno de uma consulta com regras em um service. Isso que faz complicar e gerar burocracia quando nao é o caso de ter validação. Caso a requisição x exija validação, chama o service pra validar (ou bean validation no caso do Java), caso ok chama o repositório pra retornar os dados. A exemplo do caso citado pelo colega, que precisa validar os dados do filtro antes de retornar a consulta.

Controller não é pra ser algo totalmente burro, não deve ter regras de negócio mas pode decidir se vai validar ou nao o que ta entrando. Não é a toa o nome Controller. E isso não tem nada haver com performance.

Importante é ter agilidade no desenvolvimento, não cometer amarrações e a empresa ter retorno imediato do previsto de valor pro Negócio, sem perder tempo com burocracias e exoterismos.

Outra burocracia muito comum entre os puristas é criar interface sem necessidade, onde sempre só tem uma implementação daquele contrato.

E

Meu único receio é “regrinhas” começar a ficar espalhadas pelos controllers.

Acho que se a consulta tem alguma validação tanto na entrada(filtro obrigatório) ou na saída(levantar exceção caso a consulta retorne vazio) o melhor seria deixar num service, né?

Quando a consulta não tem validações, nem na entrada nem na saída, não vejo necessidade de colocar num service.

J

Validações de dados de entrada eu sempre aplico no controller, nos services somente o que diz respeito à regras de negócio e afins, gosto deste formato pois fica bem simples e dividido o código.
Logicamente isso não é regra, se colocar tudo junto e misturado vai funcionar do mesmo jeito, porém a medida em que se evoluí a aplicação, vai aumentando a complexidade de manutenibilidade ou novas implementações acabam sendo bem maiores e demoradas.

E

Eu aprendi que essas validações “deviam” ser colocadas nos services. Dessa forma eu posso usar o mesmo service em várias partes do sistema sem precisar duplicar as validações.

J

No meu caso eu sempre utilizo Beans Validation, então estas validações eu não preciso reimplementar nada para verificar se um dado é nulo, vazio, maior ou menor que zero e coisas do tipo, garanto que os dados só cheguem aos services se já estiverem todos Ok na entrada.
São abordagens diferentes, não existe certo e errado ao meu ver neste contexto se ambas atendem o propósito da solução.

J

A regra deve ficar no service ou bean validation. Mas você pode decidir chamar ou não a validação na controller, dependendo de cada caso requisitado. Requisição pra uma combo simples por exemplo não precisaria de validação. Já esse caso citado do filtro sim.

A exemplo do próprio bean validation, a validação pode ser chamada na controller através de anotação nos parâmetros da requisição, fazendo o backend retornar bad request (400).

A

Mudança é uma constante em desenvolvimento. Logo imagine um sistema que em alguns casos o Controller chama o Service e em outros chama o Repository. Isso é uma caracteristica de um sistema padronizado?

Vamos pensar um pouco: Digamos que em uma determinada funcionalidade não tenha nenhuma regra de negocio, então decidi que o Controller nesse caso vai chamar direto o Repository, em um certo dia alguém resolve colocar uma regra de negocio, dai eu tenho que criar um Service e colocar a regra de negocio, mas não é só isso, tenho que varrer todos os meus Controllers pra verificar quem esta chamando o Repository em questão pra trocar pelo Service, eis duas perguntas: 1 - Quanto tempo de manutenção isso vai gastar? 2 - Se eu esquecer algum Controller o que vai acontecer?

Volto a pergunta do topico: Controller acessar o repository é uma boa pratica? Se for qual o embasamento no arcabouço da literatura técnica isso se sustenta? Vamos pensar um pouco?

E

Parece que há um “tradeoff” aqui. Robustez, Burocracia e mais linhas de código vs Menos Robustez, flexibilidade e código mais enxuto.

O que tenho observado é que alguns anos atrás era quase um padrão o controller chamar apenas services.

Recentemente tenho visto vários projetos e profissionais bem conceituados usando a outra abordagem. Controller chamando services e repository, conforme a demanda.

J

Não tem varredura se atender demandas de forma incremental. Ai voce já tem um problema de gestão.

Ja trabalhei com ambas as abordagens, e era muito mais entediante trabalhar de forma burocratica.

E

Será que a abordagem do controller chamando apenas services é mais robusta? O que vc conseguiu perceber empiricamente falando.

Certamente essa abordagem é mais entediante, demorada e tem mais linhas de código, porém fico com receio de que essa abordagem é mais robusta.

Na abordagem de controller chamando repository, nada impede de um controler chamar um save diretamente, sem passar pelas regras de negócio. Isso é muito ruim. Para evitar isso teria que criar interfaces e assim aumentar as linhas de código e burocracia.

A

No livro Arquitetura Limpa de Robert C. Martin diz que: “A camada de interface não pode conhecer nada da camada de acesso a dados.”, no nosso caso o Controller seria a entrada da nossa API, portanto chamar diretamente o Repository quebra o paradigma.

J

Isso varia de equipe para equipe, de gestão pra gestão. Voce tem que seguir o que for mais prático pro seu dia a dia, independente do que Papas da TI preguem. Se tu ver o que javeiros pregavam no passado como correto iria cair da cadeira.

No final o que importa é o retorno financeiro pro Negócio, sem burocracias técnicas atrapalhando. Maioria dos programadores tem a visão muito fechada só pra código.

Por isso o nome Controller, é o controlador. Se nao o nome seria Mule. Voce impede ou nao de acordo com a requisição/demanda.

J

Nao sigo o que vá me atrapalhar na entrega de resultados pra faturar. Imagina se eu seguisse o que literaturas pregavam de complexo no passado como na epoca do extremo DDD? Eu sempre ignorava e ganhava com isso.

J

Existe em tudo, você precisa sempre avaliar os ganhos e percas e se questionar qual o melhor caminho à seguir no momento.

Pensar somente no atual momento é condenar o futuro da solução, e pensar só no futuro é sacrificar o momento atual, por isso vale sempre avaliar, mas visando tanto o atual momento como o futuro também.

J

Importante não ter amarrações, isso que condena o futuro.

E

Nisso concordo contigo. Sempre achei uma furada fazer um sistema usando DDD. Eu sigo a moda antiga, modelo o banco primeiro, seguindo o modelo relacional, e ainda por cima trabalho com entidades anêmicas. Toda a regra de negocio nos services. Consigo ser muito mais produtivo assim e as pessoas que entram no projeto conseguem dar manutenção tranquilamente. Testes apenas nos services e testes de integração.

Inclusive estou seguindo uma dica tua, rsrsrs. A menor quantidade possível de javascript no front. Já “cuspo” o html prontinho do server. Claro, não é uma SPA.

J

É por ai mesmo, seguir só o que for mais prático pra fluir seu horizonte e conseguir o máximo de retorno financeiro, sem exageros nem de um lado, nem de outro, buscar o equilíbrio. É bom sempre avaliar o que for proveitoso das literaturas, não seguir como se fosse religião.

Também trabalho orientado a banco. Sem as amarrações do modelo orientado a objetos, uso DTOs conforme a demanda. Pelo menos pra mim também é muuuito mais produtivo e sem problemas de uma funcionalidade impactar a outra.

Essa questão de se complicar com SPA pra tudo sem ter necessidade também rola muito. Claro que é mais adequado em alguns cenários e traz retorno. Mas quando não é, principalmente em sistemas usados por funcionários internos, nao precisa se complicar só pela moda, criando um abismo entre projetos front e back só pra entregar o html ao browser, sem o usuário precisar de fluidez e n interações na tela que ele trabalha. Claro, sempre o mínino de javascript necessário.

Criado 27 de outubro de 2020
Ultima resposta 29 de out. de 2020
Respostas 24
Participantes 6