Interação controller/service
15/05/2013 14:20
1
A documentação do Grails recomenda mover toda lógica dos controllers para services, deixando os controllers cuidarem apenas de coisas como o fluxo de páginas, mas não há nenhum exemplo "oficial" de como fazer isso, então gostaria de saber como os colegas do forum procedem.

Exemplo... Quem deve construir (ou recuperar do banco) os objetos de domínio com base nos parametros da requisição... controller ou service?
Sendo o service, como retorna-lo para o controller (este pode precisar saber por exemplo o ID do objeto criado para fazer um redirecionamento)... E também como sinalizar à partir do service possíveis erros que ocorreram durante a operação para que o controller possa direcionar o fluxo apropriadamente?

Acho que ficaria estranho fazer algo assim no serviço:
if (sucesso)
return instanciaCriada
else
return "codigo.erro.xpto"


Erros de validação ficam embutidos na propriedade errors da instancia, então poderia retorna-lo e depois verificar no controller se houve algum erro ou não, mas nem todas as situações podem ser sinalizadas desta forma

Particularmente gostei muito desta abordagem:
http://www.kromhouts.net/blog/grails/grails-service-and-controller-interface/

Mas para aplicar em vários pontos, gera muito código repetitivo... Pensei até em escrever uma transformação AST para auxiliar nisso, mas posso estar complicando algo que poderia ser mais simples
Tags: service controller


0
Oi Magno,

vai muito de acordo com o bom senso esta questão. No caso de uma página que é apenas um create ou uma busca por id específico que não envolva alguma lógica mais avançada que um Entidade.get(id) ou new Entidade(), eu coloco no controlador mesmo.

Quando é algo mais complexo, por exemplo: uma pesquisa não trivial, a aplicação de alguma lógica, aí já mando para o serviço executar pra mim: mesmo porque escrever testes de serviço é mais simples que de controladores.

A passagem de valores é por injeção mesmo: eu injeto o serviço no controlador e simplesmente passo pro model o que ele me retorna ou faço a transformação para algum outro formato caso seja necessário.


0
Você passa os parametros "crus" vindos do request para o service, ou deixa que ele já receba objetos de domínio prontos?


0
Oi Magno,

este é um erro comum: bom você ter perguntado. Nunca faço isto: normalmente eu aplico alguma transformação, instanciando algum objeto, ou mesmo um map.

O que ocorre: quando você passa seus valores de requisição (o params) para o service direto, ele vai funcionar, não há duvida sobre isto. O problema é que se você mudar sua camada de visualização, alterando por exemplo a presença ou não de um campo ou mesmo seu nome, isto vai impactar diretamente no seviço que não vai mais encontrar este valor. Consequentemente, o serviço vai estar diretamente acoplado ao seu arquivo gsp acidentalmente.


0
É verdade, você não poderá alterar o padrão dos nomes dos campos sem afetar o service, mas onde quer que se faça essa conversão parametros/objetos, este mesmo acoplamento vai surgir...
Alias, pode me dar algum exemplo de como/onde você faz este tratamento?
Seria algo simples como:
class FooController {
def fooService
def foo() {
def bar = new Bar(params)
fooService.bar(bar)
}

ou uma solução mais elaborada?

Vi algumas recomendações para se usar command objects... Confesso que não sei como funcionam, mas pelo que li a respeito me parece que estaria praticamente duplicando meu domínio


0
Oi Magno,

no caso, esta conversão já é papel do próprio controlador, então este é uma espécie de acoplamento inevitável entre as duas partes. O que não pode é vazar pro serviço.

E é exatamente como você colocou no seu exemplo mesmo. Não há muito o que ser feito. Apenas isto. É importante lembrar sempre que o papel do controlador é fazer este meio de campo, entre negócio e visualização.


0
Kra apenas por curiosidade, você já tentou efetuar alteração em um objeto dentro de um service e mandar persistir isso no BD no próprio service e não no Controlador?

Eu tentei fazer com que meu service gerasse uma instância de outro objeto, porém sempre dava erro quando eu mandava salvar no próprio service. Só que observando alguns plugins vi que eles fazem isso, persistem no BD diretamente do service.

Queria entender melhor como isso funciona, alguém tem alguma dica?
16/05/2013 16:45


0
Oi Rodrigo, sim. Funciona normal e até hoje nunca tive qualquer problema com isto.

Teria de ver o seu código pra entender o que pode estar acontecendo.


0
Para persistir no service eh a mesma coisa. A única diferença eh que o service é transacional por padrão, o controlador não tenho certeza


0
Henrique,

vc usa o save(flush: true) no service?

Acho que pelo que o Magno disse, ele é transacional e eu sempre colocava save(flush: true), talvez seja isso que esteja dando o problema.

Como vcs usam com save() ou save(flush: true)?

A persistência realmente ocorre após o sucesso do serviço sem a necessidade de flush:true?
17/05/2013 12:29


0
Rodrigo, que erro ocorria ao salvar a instancia no service?


0
Oi Rodrigo,

bom: o que é este "flush:true" né? A idéia é a seguinte: as ferramentas de ORM pra garantir máxima performance costumam armazenar todos os comandos que serão executados contra o banco de dados em um buffer para que sejam enviados todos de uma vez. Algo do tipo: "de 10 em 10 comandos envie-os para o BD".

Isto trás um ganho de performance bacana, porque você evita idas e voltas da rede, além do que, o próprio SGBD vai agir mais rápido executando os comandos em lote. O problema é que de tempos em tempos vão ocorrer situações em que os dados estão na aplicação mas não estão ainda no SGBD. É por isto que você consulta o BD de vez em quando, os registros não estão lá, mas quando você reinicia a aplicação, "mágicamente" eles aparecem.

Bom: quando uso flush;true né? Quando eu preciso que os dados sejam enviados imediatamente para o BD. Tirando isto, uso o modo normal mesmo. Quando uso ou não? Depende do caso. Raras vezes eu uso.



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto