Dúvida - Comunicação entre camadas+Domain Model

Aê galera, tranquilo?! :smiley:

Estou tendo dificuldades com relação a forma correta de haver comunicação entre as camadas em uma aplicação.

Por exemplo: O usuário submete um formulário para cadastro no meu sistema. Observando que eu estarei utilizando JSF, qual seria o percurso correto que o Objeto com os dados do usuário deveria fazer até ser persistido no banco de dados?

Eu pensei em algo como: Página JSF -> Managed Bean -> Repositório; mas tenho dúvidas se deveria haver “alguém” intermediando a comunicação entre o managed bean e o repositório? como um controller por exemplo, sei lá…

Alguma dica com relação a isso?

Outra dúvida que eu tenho é: Se por ventura um médoto de uma entidade precisa interagir de alguma forma com o banco de dados, a entidade deve possuir uma referência direta ao repositório, ou deve haver um “alguém” para coordenar essa operação?

Por exemplo: A entidade executa a operação, envia o resultado ao controller, e este por sua vez aciona o repositório para que o resultado seja armazenado no banco.

Desculpem pelo tamanho do tópico, mas acho que assim as minhas dúvidas ficam mais fáceis de se entender.

Obrigado pela atenção, abraços.

Não é sempre que Managed Bean consegue ficar completamente livre de código relativo a camada view. Infelizmente não é sempre que da para usar ele em outras camadas.
Mas eu acho que dificilmente um managed bean se encaixaria na domain layer. Talvez na application layer em alguns casos.

Eu acho que na maioria dos casos não é uma boa o managed bean acessar o repository, prefiro deixar nas entities e em raríssimos casos nos services.

E ai Erick,

Estas suas perguntas/dúvidas geralmente geram bastante polemica.

Dá uma olhada nestes links aqui:

http://guj.com.br/posts/list/70275.java
http://debasishg.blogspot.com/2007/12/domain-modeling-what-exactly-is-rich.html
http://debasishg.blogspot.com/2007/02/domain-driven-design-inject.html

Nos casos estremamente simples acho que não teria problemas, eu prefiro não fazer isso eu colocaria um serviço;

[quote]Outra dúvida que eu tenho é: Se por ventura um médoto de uma entidade precisa interagir de alguma forma com o banco de dados, a entidade deve possuir uma referência direta ao repositório, ou deve haver um “alguém” para coordenar essa operação?

Por exemplo: A entidade executa a operação, envia o resultado ao controller, e este por sua vez aciona o repositório para que o resultado seja armazenado no banco.
[/quote]

Este ponto é bastante polemico; Acredito que muitos irão dizer/dizem que a entidade deve ter uma referência direta para o repositório mas outros dizem que preferem não envolver questões relacionadas a mecanismos de persistencia nas entidades. Por conta disto, prefiro indicar um livro sobre este e varios outros assuntos relacionados para vc ter uma referencia maior sobre o tema:
http://www.lcm.com.br/index.php?Escolha=20&Livro=L00521

flws

[quote]

Nos casos estremamente simples acho que não teria problemas, eu prefiro não fazer isso eu colocaria um serviço;[/quote]

Tava pensando a respeito… seria uma boa solução eu adicionar uma fachada pra isolar o meu domínio da camada de aplicação?

Ficaria tipo assim: Página JSF -> Managed Bean -> Fachada -> Repositório;

De que forma as entities poderiam manter referências aos repositórios? No construtor da classe seria instanciado o atributo correpondente ao repositório?

Este é o link que fala sobre isto:
http://debasishg.blogspot.com/2007/02/domain-driven-design-inject.html

O problema que envolve esta questão é a seguinte: Geralmente a entidade é instanciada por uma ORM (JPA/Hibernate) e vc iria precisar de informar para o ORM qual é o repositório a ser utilizado. No link acima aponta uma maneira de fazer isso através do SPRING.

Outra maneira seria após a leitura das entidades vc informar o repositório através de um método set (setGrupoRepository(GrupoRepository repository) ) esta forma é indicada no livro que mencionei no post anterior, quem utiliza esta maneira defente um NÃO envolvimento maior das entidade com mecanismo de acesso a dados.

flws

Eu acho que sim.

flws

A idéia de injetar (Spring) é extremamente mais limpa e vai tornar seu código mais claro.

A idéia de fachada não se aplica no seu caso… o padrão “fachada” foi desenvolvido para suprir deficiências no modelo de objetos remotos proposto pela Sun. Você pode encontrar uma explicação mais detalhada nos blog por ai, mas, resumindo, servia para evitar a grande quantidade de lookup`s remotos nos EJB’s. Ao invés de buscar 3 referencias remotas, busca-se apenas uma, e esta serve como fachada para o serviço prestado pelas outras duas.

Abraços,
Eduardo Amuri

[quote=Eduardo Amuri]
A idéia de fachada não se aplica no seu caso… o padrão “fachada” foi desenvolvido para suprir deficiências no modelo de objetos remotos proposto pela Sun. [/quote]

Hmm… não. Façade é um padrão GoF, catalogado bem antes dos padrões da Sun (e até de J2EE existir).

[quote=Erick Jeronimo]
Tava pensando a respeito… seria uma boa solução eu adicionar uma fachada pra isolar o meu domínio da camada de aplicação?

Ficaria tipo assim: Página JSF -> Managed Bean -> Fachada -> Repositório;

De que forma as entities poderiam manter referências aos repositórios? No construtor da classe seria instanciado o atributo correpondente ao repositório?[/quote]

No fluxo acima eu não consigo ver seu domínio. O que você tem ali é um Transaction Script, não um Domain Model.

E eu não entendi porque você está usando Repositório. Será que você não está apenas mudando o nome do DAO?

Hum, entendi. Mas acho que o uso mais evidente, é esse… não? Não acho que se aplicaria no caso do amigo ai de cima.

Eu optaria por algo como:

Página JSF -> Managed Bean -> Serviço -> Repositório;

Existe algum problema nessa abordagem?

[quote]
Hum, entendi. Mas acho que o uso mais evidente, é esse… não? Não acho que se aplicaria no caso do amigo ai de cima. [/quote]

Na verdade quando eu falei em Fachada eu estava me referindo ao padrão da GoF. Se quiser dar uma olhada tem uma breve descrição do padrão aqui.

[quote]

No fluxo acima eu não consigo ver seu domínio. O que você tem ali é um Transaction Script, não um Domain Model.

E eu não entendi porque você está usando Repositório. Será que você não está apenas mudando o nome do DAO? [/quote]

De fato não fui feliz na nomenclatura, aonde lerem repositório podem interpretar como DAO :oops:

pcalcado, na verdade o que seria um “Transaction Script”?

Quando eu fiz a “ilustração” do fluxo de requisições eu quis mostrar situações nas quais a Fachada faz chamadas diretas ao DAO (isso é recomendável?). Eu tenho dúvidas com relação a “quem deve requisitar a quem” no modelo arquitetural que eu ilustrei.

O meu modelo de domínio ficaria entre a fachada e o DAO. Só que a questão é que eu não sei se as classes de entidade devem requisitar “algo” diretamente ao DAO.

Exemplo: Página JSF -> Aplicação (Managed Bean, Fachada…) -> Domínio(Classes de Entidade…) -> Infra (DAO…)

Também tenho dúvida se existe a necessidade de ter alguma classe para se comunicar com o DAO (ao invés da fachada manter uma referência direta ao mesmo).

Eu venho de um modelo onde as regras de negócio ficavam em classes controladoras e as classes de entidade eram apenas um conjuto de atributos+gets/sets. Estou tentando abandonar este modelo (através de leitura e de experiência “própria” percebi que ele não é o mais adequado), porém estou tento certa dificuldade em perceber qual seria o fluxo correto que as requisições devem percorrer.

Orientações são muito bem vindas, obrigado pelas dicas galera! :smiley:

Ok, como DAO e Repositório são coisas diferentes recomendo que mantenhamos o que você está usando como DAO para evitar confusão.

http://www.google.com/search?q=transaction+script

Primeiro hit.

Se sua Fachada faz requisições ao DAO você não tem um Domain Model. Leia o link acima para entender melhor.

Erick,

http://dddsample.sourceforge.net/

Talvez lhe interesse =)

Interessante cara, eu não sabia da existência de transactions scripts.

Mas assim, é “ruim” ou “errado” fazer uso de transactions scripts?

Em uma abordagem “não transaction scrpit”, de que forma eu poderia realizar os cadastros básicos do sistema sem que a fachada se comunicasse diretamente com o DAO? A entidade de domínio teria o método “cadastrar” que comunicaria com o DAO?

Não é errado. Dependendo do seu escopo e do seu propósito, é uma abordagem vantajosa. O site do Fowler explica com maiores detalhes, caso você não tenha acesso ao PEA.

Não é questão de ser certo ou errado.
Tanto Domain Model quanto Transaction Script são padrões para lógica de domínio, o que não quer dizer você não possa utilizar os dois no mesmo projeto, porém não é aconselhavél pois seu design vai ficar muito ruim.

Procure sobre repositórios, vai te clarear bastante sobre a idéia de como acessar a camada de persistência.
veja: http://gc.blog.br/2009/01/17/sindrome-de-dao/ o Guilherme escreveu recentemente.

Na abordagem do fowler sobre repositórios, acredito não ser a 100% correta sobre trabalhar com DDD, mas já te dar base sobre o assunto.

Abraços

[quote=Erick Jeronimo]Aê galera, tranquilo?! :smiley:

Estou tendo dificuldades com relação a forma correta de haver comunicação entre as camadas em uma aplicação.

Por exemplo: O usuário submete um formulário para cadastro no meu sistema. Observando que eu estarei utilizando JSF, qual seria o percurso correto que o Objeto com os dados do usuário deveria fazer até ser persistido no banco de dados?

Eu pensei em algo como: Página JSF -> Managed Bean -> Repositório; mas tenho dúvidas se deveria haver “alguém” intermediando a comunicação entre o managed bean e o repositório? como um controller por exemplo, sei lá…

Alguma dica com relação a isso?
[/quote]

O managedBean do JSF é o controler. Só que ele é o controller da camada de apresentação ( padrão MVC).
Se a operação é uma simples leitura de dados ele pode invocar o repositorio directamente. Se é uma operação que vai mudar o estado do sistema , tal como insert, update , delete ou algum processamento (que resulta em um ou mais insert, update ou delete)
então é bom que o o ManagedBean invoke o controlador de negocio/dominio. O controlador de dominio é um Serviço.
O ManagedBean deve então apenas consumir o serviço e deixar que o serviço faça o seu papel.

Em todos os casos o papel do ManagedBean é traduzir os dados do formato JSF para o formato do dominio e vice-versa. (ou seja, pegar os dados dos escopos certos , invocar o dominio e depois colocar os resultados nos escopos certos)

Quem coordena a operação é o Repositorio. a entidade deve ter uma referencia ao repositorio apropriado, ou localizar um através do padrão Service Locator. No reino da ADI é mais simples que a entidade seja injetada com os repositorios que precisa.
Agora, cuidado com o tipo de invocação que faz ao repositorio. Ela tem que ser read-only sem alterar o estado do sistema.
( básicamente apenas para encontrar outros objetos através de alguma referencia/chave )

entidades não envia coisa alguma a ninguem. É o controler que pede à entidade algo. A entidades não tem referencia ao controlador que a está invocando. Violar isto é violar o principio de inversão de controle, e violar este principio é fazer gambe.

A abordagem do Fowler não apenas é a correta como é aquela que é verdadeiramente OO.
O pessoal do DDD aproveitou essa ideia. O problema é que o pessoal do DDD confunde repositorio com DAO, enquanto o Fowler não.
( O DAO é um serviço , o repositorio não é um serviço)

Na real, DAO é coisa do passado. Só se deve usar em sistemas legados que são orientados a dados (que é diferente de sistemas orientados a dominio). Mais sobre isso em :







Em primeiro lugar, queria agradecer a ajuda de todos, muitas dúvidas minhas estão sendo esclarecidas. :smiley:

[quote]O managedBean do JSF é o controler. Só que ele é o controller da camada de apresentação ( padrão MVC).
Se a operação é uma simples leitura de dados ele pode invocar o repositorio directamente. Se é uma operação que vai mudar o estado do sistema , tal como insert, update , delete ou algum processamento (que resulta em um ou mais insert, update ou delete)
então é bom que o o ManagedBean invoke o controlador de negocio/dominio. O controlador de dominio é um Serviço.
O ManagedBean deve então apenas consumir o serviço e deixar que o serviço faça o seu papel. [/quote]

Blz Sérgio, entendi melhor a questão de quem deve chamar a quem pra solicitar uma operação. Só tive dúvida com relação à possibilidade de haver um serviço pra realizar inserts, updates e deletes, e o ManagedBean apenas solicitar ao serviço a operação desejada.

Qual o objetivo de separar essas operações em um serviço? sendo que para consultas, o ManagedBean pode solicitar diretamente ao repositório? As operações de insert, update e delete não podem ficar diretamente no managed bean? já que este possuiria uma referência ao repositório mesmo…

Atualmente eu trabalho com tudo dentro do próprio managed bean. Queria entender porque essa abordagem seria incorreta, quais as vantagens (caso haja alguma…), desvantagens, etc…

Obrigado pela ajuda galera, abraços.

Normalmente o sistema não fará um save ou delete “puro”. Ou seja, ele vai fazer outras operações. Por exemplo, ele pode enviar emails , informar listeners de eventos, fazer operações de save/delete em cascada, validações , verificação de autorização, log , etc…

No inicio pode parece apenas um save simples no banco, mas à medida que o sistema cresce novas coisas são adicionadas. Se vc não isolar em um serviço o seu ManagedBean vai aumentar em responsabilidade. É esse o problema. Ele não tem , nem deve ter essas responsabilidade. Ele é um item da apresentação. Não deve conter lógicas de negocio. Colocando em um serivo a coisas fica muito mais simples. Um serviço é definido como uma interface e uma ou mais implementações. O que significa que no futuro se vc mudar o serviço o seu JSF não vai nem saber. Esta flexibilidade mostra que as responsabilidades estão bem separadas e isso singifica que é um melhor modelo que meter tudo na mesma classe.