[Resolvido] (Conceitual) Arq em Camadas / MVC + Primefaces + Hibernate

E ai galer blz? então, antes de mais nada, eu procurei já resposta para
a minha dúvida e não achei… existem vários tópicos parecidos,
mas nenhum que consiga sanar a minha dúvida…

Bom… eu estou desenvolvendo um sisteminha, que está funcionando…

segundo o livro “Programação Java para Web” eu estou seguindo
a “Arquitetura em camadas”:

Acesso a Banco de Dados (DAO) - Hibernate

public classUsuarioDao {
	public Usuario getUsuario(long id){...};
}

Regras de Negócio (RN)

@ManagedBean
@ViewScoped
public class UsuarioController {
	private Usuario usuario;
        private UsuarioDao usuarioDao = new UsuarioDao ();
       ...
}

e Apresentação (JSF)

<h:outputText value="#{usuarioController.usuario.nome}" />
...
  • Entidade:
@Entity
public class Usuario {
	private String login;
	private String senha;
}

até aqui tudo bem… sem problemas para mim…

ai no livro tem "Arquitetura MVC": (aqui que eu me confundi)
Model:
*Acesso a Banco de Dados (DAO)
*Regras de Negócio (RN)

Apresentação:
Controller:
*JSF e Managed Bean
Apresentação:
*JSP

MVC tem 3 camadas mas com 4 classes… no meu caso seria DAO, RN, Managed Bean e o JSF(pois estou usando Primefaces) certo?
pra eu passar o meu sistema pra essa arquitetura teria
que dividir a minha classe Controller em 2, RN e Managed Bean…

se até ai eu estou certo… a minha dúvida é a seguinte:
Como dividir minha classe controller que intermedia o DAO e o JSF,
e como funciona esse novo esquema? cada página jsf tem um Managed Bean
que aponta para um unico RN?

por exemplo:
manterUsuario.jsf > manterUsuarioMB.java > usuarioRN.java > usuarioDAO.java
listaDeUsuarios.jsf > listaDeUsuariosMB.java > usuarioRN.java > usuarioDAO.java

não sei se consegui explicar minha dúvida… mas espero que alguém consiga me ajudar…

valeu galera… :smiley:

Nunca, jamais, em tempo algum refira-se a algo que você cria como “sisteminha”. Ou você já foi a um médico fazer uma 'consultinha"? A um advogado fazer uma “petiçãozinha”? A um engenheiro fazer uma “plantinha”?

Se você conseguir responder sim a todas as perguntas, seu sistema está em camadas e bem implementado, se houver algum não, terá que corrigir.
1 - Se você quiser trocar o hibernate por jdbc na camada de persistência, consegue fazer sem afetar as classes de outra camada (controle)?
2 - Se você quiser trocar a camada de controle por outra tecnologia, irá conseguir fazer sem afetar a camada modelo ou a camada view?
3 - Se quiser trocar a camada visão por outra tecnologia, conseguirá sem afetar a camada de controle?

Repetindo, se uma das respostas for não, seu modelo MVC está com alto acoplamento e baixa coesão, ou seja, as camadas tem dependências maiores que as necessárias (a visão conhece demais da controle, a controle demais da visão e da persistência e/ou a persistência demais da controle).

[quote=drsmachado]1 - Se você quiser trocar o hibernate por jdbc na camada de persistência, consegue fazer sem afetar as classes de outra camada (controle)?
2 - Se você quiser trocar a camada de controle por outra tecnologia, irá conseguir fazer sem afetar a camada modelo ou a camada view?
3 - Se quiser trocar a camada visão por outra tecnologia, conseguirá sem afetar a camada de controle?[/quote]
As duas primeiras eu achei muito bem colocadas, agora a terceira eu não entendi muito bem.

Teria como (por exemplo) alterar meu sistema de JSF para Struts 2 sem mexer na camada de controle ?

[quote=digaoneves][quote=drsmachado]1 - Se você quiser trocar o hibernate por jdbc na camada de persistência, consegue fazer sem afetar as classes de outra camada (controle)?
2 - Se você quiser trocar a camada de controle por outra tecnologia, irá conseguir fazer sem afetar a camada modelo ou a camada view?
3 - Se quiser trocar a camada visão por outra tecnologia, conseguirá sem afetar a camada de controle?[/quote]
As duas primeiras eu achei muito bem colocadas, agora a terceira eu não entendi muito bem.

Teria como (por exemplo) alterar meu sistema de JSF para Struts 2 sem mexer na camada de controle ?[/quote]
Seguindo o que o MVC prega, é impossível.
Aliás, isso não seria possível nem com mentawai e struts 2, struts 2 e vRaptor e afins.
O que acontece é que, ao meu ver, os ManagedBeans (JSF2) e Actions (Struts e Mentawai) são parte da camada View e não da Control.
Eles estão diretamente ligados à tecnologia empregada para interação cm o usuário e são mais responsáveis pelo controle de elementos de tela que da própria regra de negócios.
Eu, quando posso, sempre adoto o uso de intermediação nas camadas, utilizando services.
Jogo a lógica do negócio nas classes services e consigo ter um isolamento maior.
Assim, consigo mudar de desktop para web e de um framework para outro, sem comprometer o que fiz nas demais camadas.

É uma solução muito ortodoxa? Talvez, mas desde que adotei essa abordagem o número de problemas foi se reduzindo.

[quote=drsmachado]Seguindo o que o MVC prega, é impossível.
Aliás, isso não seria possível nem com mentawai e struts 2, struts 2 e vRaptor e afins.
O que acontece é que, ao meu ver, os ManagedBeans (JSF2) e Actions (Struts e Mentawai) são parte da camada View e não da Control.
Eles estão diretamente ligados à tecnologia empregada para interação cm o usuário e são mais responsáveis pelo controle de elementos de tela que da própria regra de negócios.
Eu, quando posso, sempre adoto o uso de intermediação nas camadas, utilizando services.
Jogo a lógica do negócio nas classes services e consigo ter um isolamento maior.
Assim, consigo mudar de desktop para web e de um framework para outro, sem comprometer o que fiz nas demais camadas.

É uma solução muito ortodoxa? Talvez, mas desde que adotei essa abordagem o número de problemas foi se reduzindo.[/quote]
Entendi.

Eu sigo da mesma forma, tenho os ManagedBeans que servem para o controle da comunicação entre a View e a camada de negócio (Service), na qual as regras de negócio estão implementadas em EJBs.

Esse é o modelo que eu creio possuir acoplamento mais baixo, por isso também prefiro.

drsmachado

Obrigado por responder… como estou mexendo com JSF, Hibernate a pouco tempo,
não sei responder exatamente se estão corretas as camadas do meu projeto, pois
não fiz nenhum curso, estou estudando por conta…

a minha dúvida é exatamente como montar da melhor forma…
pois pelo q eu vi… no meu caso eu juntei a Regra de Negócio e a Managed Bean
em uma classe só…que é a Controller…

me disseram que a controller não pode acessar a DAO… só q eu não sei como
dividir a controller em 2… no caso na Regra de Negócio e a Managed Bean…

o sistema funciona na maneira que está, só que sinto que não está certo,
quando ficar maior acho que vou ter problemas…

tem algum link de artigo ou algum crud que explica como usar o hibernate/JSF da maneira
correta utilizando o padrão MVC com baixo acoplamento???

Não.

Divisão em camadas é uma coisa e mvc é outra. MVC não é separação em camadas ( isto deveria ser um topico no FAQ e fixo, é incrivel a quantidade de pessoas que vêm aqui com este conceito errado). Arquitetura MVC não existe. O que existe é Arquitetura ECB. Então esqueça MVC. Foquemos nas camadas que é o que interessa

O seu sistema está separado em 3 camadas. Integração (DAO) e Negocio (Entidades) e Apresentação (Controladores e páginas)

A sua camada de negocio é muito final - aliás práticamente inexistente. O controlador está chamando o dao. Vc está pulando a camada de negocio. à piori isto não é uma boa separação de camadas. O Controlador da apresentação não pode saber do DAO.

Assim funciona, mas está mais para 2 camadas com DTO do que 3 com entidades ( foi otimista na conta de cima).

Vc precisa realmente de uma melhor camada de negocio (implementa através de serviços. “Regra de Negócio” não é padrão nenhum.)
O controlador da apresentação chamará um serviço de fachada que por baixo dos panos irá chamar outros serivços e os daos.
Não precisa ser um controlador para um serviço. vc pode reutilizar o serviço, mas se tudo estiver bem desenhado vc não vai precisar.

[quote=darkan666]drsmachado

Obrigado por responder… como estou mexendo com JSF, Hibernate a pouco tempo,
não sei responder exatamente se estão corretas as camadas do meu projeto, pois
não fiz nenhum curso, estou estudando por conta…

a minha dúvida é exatamente como montar da melhor forma…
pois pelo q eu vi… no meu caso eu juntei a Regra de Negócio e a Managed Bean
em uma classe só…que é a Controller…
[/quote]
Essa forma é a primeira abordagem que se faz em casos de estudos.

Mentiram ou você entendeu errado.
A camada view só interage com o usuário e acessa a controller.
A camada controller interage com a view e com a model (DAO)
A camada model interage com a base de dados e com a camada controller.

A camada view NÃO pode acessar a camada model.
A camada model NÃO pode acessar a camada view.

[quote=darkan666]
o sistema funciona na maneira que está, só que sinto que não está certo,
quando ficar maior acho que vou ter problemas…

tem algum link de artigo ou algum crud que explica como usar o hibernate/JSF da maneira
correta utilizando o padrão MVC com baixo acoplamento???[/quote]
O uso de JSF ou qualquer framework para aplicativos web em java forçará você a ter um alto acoplamento entre view e model. Seja JSF, Struts ou mentawai, você estará amarrando a view (xhtml, jsp) a controller (managedbean, action).

Do que precisa, então?
Bom, primeiramente eu criaria uma nova camada para cuidar das regras de negócio.
Deixaria que o ManagedBean apenas fosse um “roteador”, recebendo e enviando dados da view para a camada de serviços.
Na camada de serviços eu aplicaria toda a lógica cabível (incluindo o controle de exceções).
Assim, isolo a camada view da camada de persistência (DAO, no caso) e, caso você queira estudar Struts 2, pode usar a mesma camada de serviço e persistência.

[quote=sergiotaborda][quote=darkan666]

MVC tem 3 camadas mas com 4 classes… no meu caso seria DAO, RN, Managed Bean e o JSF(pois estou usando Primefaces) certo?
[/quote]

Não.

Divisão em camadas é uma coisa e mvc é outra. MVC não é separação em camadas ( isto deveria ser um topico no FAQ e fixo, é incrivel a quantidade de pessoas que vêm aqui com este conceito errado). Arquitetura MVC não existe. O que existe é Arquitetura ECB. Então esqueça MVC. Foquemos nas camadas que é o que interessa

O seu sistema está separado em 3 camadas. Integração (DAO) e Negocio (Entidades) e Apresentação (Controladores e páginas)

A sua camada de negocio é muito final - aliás práticamente inexistente. O controlador está chamando o dao. Vc está pulando a camada de negocio. à piori isto não é uma boa separação de camadas. O Controlador da apresentação não pode saber do DAO.

Assim funciona, mas está mais para 2 camadas com DTO do que 3 com entidades ( foi otimista na conta de cima).

Vc precisa realmente de uma melhor camada de negocio (implementa através de serviços. “Regra de Negócio” não é padrão nenhum.)
O controlador da apresentação chamará um serviço de fachada que por baixo dos panos irá chamar outros serivços e os daos.
Não precisa ser um controlador para um serviço. vc pode reutilizar o serviço, mas se tudo estiver bem desenhado vc não vai precisar.

[/quote]
O que acontece é que sempre se associa MVC à construção em camadas, inclusive, forçando a imaginar, que uma arquitetura que usa camadas deve ter, sempre, 3 camadas.
Entities, boundaries e controllers são elementos pouco explorados para os exemplos.
E, o problema fica maior ainda quando vemos atrocidades do tipo “sou iniciante em java, to fazendo um projeto JSF 2 + hibernate” (tenho pesadelos com isso).
Qualquer tutorial de JSF 2, de Struts 2 ou de qualquer framework esquece que aquele sujeito que gerencia (controller) a camada view (boundary) é parte integrante da estrutura da camada de apresentação.
A regra é clara, substituir qualquer camada por outra semelhante não deve afetar a camada imediatamente superior e inferior se estas existirem.

drsmachado e sergiotaborda

o meu xhtml chama a classe controller… certo?
ai a controller faz todas as validações se estiver ok… chama quem?
a Dao ou a classe de Serviço (da qual eu não tenho a mínima ideia do que seja)?

nas ultimas repostas em relação a controller acessar ou não a Dao foi
divergente, não sei exatamente qual é a correta…

drsmachado esse é o problema… não sei como semapara a minha “controller” (Managed Bean)
em Managed Bean e Serviço

me desculpem o meu nível de iguinorância em relação a isso…

Veja só. Tua estrutura hoje é:

Note que se você quiser mudar de xhtml para jsp e usar Struts 2, precisará remover a camada view e control, certo?
Vamos supor que você crie uma nova camada, com classes de serviço.

Por exemplo, suponha que você tem um bean chamado Pessoa e você tem um CRUD de pessoas. Para isso, terá um PessoaDAO e um PessoaManagedBean, certo?
Agora, ao invés de colocar regras de negócio e chamadas à dao no managedbean, você cria a classe PessoaService e nela você coloca as chamadas à dao e toda regra de negócios aplicável a cada método que trata do bean pessoa.
Se um dia você mudar de web para desktop, pode construir as telas e chamar os métodos da classe PessoaService, pois eles não estão amarrados ao JSF 2, só à própria camada.

Ficou mais claro?

drsmachado

então na minha camada de controle(Managed Bean) vai ter SOMENTE os objetos que eu utilizo na tela (xhtml)
e as chamadas pra service…?
E na service toda parte lógica/validação e as chamadas Dao?

[quote=darkan666]drsmachado

então na minha camada de controle(Managed Bean) vai ter SOMENTE os objetos que eu utilizo na tela (xhtml)
e as chamadas pra service…?
E na service toda parte lógica/validação e as chamadas Dao?

[/quote]
Vamos supor que você tenha, no ManagedBean, um método para inserir pessoas.
Nele você faz toda validação de dados que não podem ser nulos (isso pode ser feito nesta camada) e, caso esteja tudo ok, chama o método correspondente do objeto da classe PessoaService que, para evitar problemas, geralmente tem o mesmo nome.

... private PessoaService pesSer; public String inserirPessoa(){ //validações pesSer = new PessoaService(); pesSer.inserirPessoa(getPes()); return "listarPessoas"; }

[quote=darkan666]drsmachado e sergiotaborda

o meu xhtml chama a classe controller… certo?
ai a controller faz todas as validações se estiver ok… chama quem?
a Dao ou a classe de Serviço (da qual eu não tenho a mínima ideia do que seja)?

nas ultimas repostas em relação a controller acessar ou não a Dao foi
divergente, não sei exatamente qual é a correta…

drsmachado esse é o problema… não sei como semapara a minha “controller” (Managed Bean)
em Managed Bean e Serviço

me desculpem o meu nível de iguinorância em relação a isso…[/quote]

Pense tomadas eletricas. Pense que cada camada tem um plug macho na chamada a ela só que cada plug é diferente. Cada um tem formatos de pinos diferentes.

O que vc precisa ?

Adaptadores.

A camada de apresentação onde está o jsf e os managed beans “termina” no managed bean. A camada a seguir (Dominio tb chamada “negocio”) começa com um service ( o DAO é um service também por isso que é possivel considerar que ele está na camada de negocio e ser acessado diretamente, mas na minha opinião é um tipo de serviço diferente é equivalente ao managed bean chamar um enviador de email, é um serviço, mas não é um serviço que ele deveria chamar).

Só que o service da camada de dominio tem pinos diferentes. Então vc precisa se um adaptador. Aqui vc tem 2 opções. Ou vc adapta a camada de apresentação a encaixar na de dominio, ou a de dominio a encaixar na de apresentação. Na primeira vc cria um objeto que existe na camada de apresentação, mas representa a camada de dominio. Este objeto é chamado pelo padrão “Business Delegate”. Na segunda vc cria um serviço que serve apenas para ser chamado da camada de apresentação. Estes são os Service Façade. Neste caso um controlador só pode chamar serviços que são service façade e nenhum outro tipo de service. Dito de outra forma, a camada de dominio só publica estes serviços. Só estes são publicos. O resto é privado e vc nem sabe como é.

O mesmo conceito é usado nas outras camadas. Entre a camada de dominio e a de integração vc pode usar um equivalente ao “business delegate” que seria o Domain Sotre ( que é o padrão do JPA e Hibernate) ou o 'façade" que seria o DAO. ( O DAO é um service façade da camada de integração)

Atualmente o padrão escolhido tende a dar mais importancia ao dominio. Isto porque é no dominio que estão as regras e as regras é que custam mais dinheiro implementar. então é dado preferencia ao Service Façade e ao DomainStore respetivamente em cada “ponta” da camda de dominio.

Uma forma de não confundir camadas com MVC é pensar em 5 camadas : Cliente ( o browser , applet ou swing dektop) , Apresentação (que dá suporte ao cliente, REST, SOAP ou frameworks action based ) , Dominio ( onde estão as entidades, os serviços, os repositorios, os validadores, etc… tudo o que tenha regra de negocio), Integração ( meio de campo com a persistencia que pode ser arquivo , banco de dados, outros sistemas etc… ) , Recursos (onde os dados estão de fato: SGDB , FileSystema, BigData, etc… ) Assim não dá para confundir com o MVC que só é usado no design na camada Cliente e na camada Apresentação.

Quando vc cria um serviço em um sistema muito simples de cadastro parece bobo porque o que ele realmente vai fazer é só delegar para o DAO. mas é assim mesmo.
O padrão só mostra o que vale em casos de uso que não são cadastros como relatorios, telas de processo, etc… ou seja, em algo que tenha realmente um processamento mais complexo do que simplesmente salvar. Contudo, mesmo num simples sabe o service irá validar os dados e só depois passar ao dao.

É que o seu exemplo é muito simples. Mas em termos de arquiteura e camadas ha que separar, não importa a complexidade real. Algumas pessoas acham bobagem simplesmente delegar - chamam isso de sobre-engenharia - mas a real é que isto é uma questão de Separação de Reponsabilidade , não temos culpa que as responsabilidade sejam simples. O que interessa é que estão separadas.

[quote=drsmachado][quote=darkan666]drsmachado

então na minha camada de controle(Managed Bean) vai ter SOMENTE os objetos que eu utilizo na tela (xhtml)
e as chamadas pra service…?
E na service toda parte lógica/validação e as chamadas Dao?

[/quote]
Vamos supor que você tenha, no ManagedBean, um método para inserir pessoas.
Nele você faz toda validação de dados que não podem ser nulos (isso pode ser feito nesta camada) e, caso esteja tudo ok, chama o método correspondente do objeto da classe PessoaService que, para evitar problemas, geralmente tem o mesmo nome.

... private PessoaService pesSer; public String inserirPessoa(){ //validações pesSer = new PessoaService(); pesSer.inserirPessoa(getPes()); return "listarPessoas"; }[/quote]

muitíssimo obrigado pela paciência drsmachado e sergiotaborda
consegui entender como faz a separação e qual a finalidade de cada camada :wink:

mto obrigado msm :smiley: abraços

Sem problemas.
Agora, não esqueça o que o sergiotaborda falou.
Quando tempos um CRUD parece desnecessário o uso de uma camada intermediária entre o DAO e o MB, mas, quando temos alguma complexidade na regra negocial, isso se torna indispensável.

Muito bom este post.
Parabens ao autor e aos colaboradores que responderam aqui.

Desculpa, postar em um tópico de 2 meses atrás, mas eu não posso deixar de elogiar.

Essa divisão já é clara para mim, mas vocês explicaram de forma sensacional.

O que me resta de dúvida é sobre o JSF, que eu pretendo estudar em breve.
Mas, vou pesquisar no forum e ver se encontro resposta. Se não, crio um novo post.

Mas com certeza alguém já deve ter respondidos minhas dúvidas sobre JSF.
Até por serem conceituais.

Bom, abraço.
Parabens :slight_smile: