Perguntas sobre MVC Desktop! Existe solução? (+ MVP,MVC WEB,Observer e Exception's)

270 respostas
pedromuyala

[size=15][color=red]ATENÇÃO NOVO VISITANTE:[/color][/size] Se a sua intenção é ajudar respondendo perguntas e não ficar confuso entre tantas perguntas e respostas no tópico, recomendo que inicie sua leitura a partir da data de 23/10/2009 (que está dos 160 posts para frente, página 11). Porém se a sua intenção é aprender, recomendo uma leitura cuidadosa de todo o tópico e dos outros já postados anteriormente aqui no GUJ. O tópico está grande justamente para que eu não fique abrindo tópicos novos a cada pergunta relacionada ao MVC. Quem quiser aproveitar o embalo do tópico (já que este está sendo acompanhando por uma boa galera) e postar perguntas novas RELACIONADAS AO MVC, fiquem avontade. Felicidades a todos! :smiley: (27/10/2009)

[size=14][color=blue]QUERO AGRADECER:[/color][/size] A todos que estão colaborando, mesmo com o tópico gigante estão acompanhando, mandando ajuda pelo MP (Mensagens Privadas, além que acho, na minha opinião, que as respostas devem ser postadas para todos) e os novos visitantes que também estão ajudando muito. Como disse desde o início sou um aprendiz em JAVA e se não fosse o GUJ para proporcionar essa rede maravilhosa com certeza para mim seria muito ruim aprender alguma coisa. Realmente não tenho palavras para agradecer. Muito Obrigado! :smiley: (13/07/2009)

[size=14][color=blue]QUERO ME DESCULPAR:[/color] Pela minha ausência ao fórum durante quase três meses (de início de Novembro até inicio de Fevereiro). Infelizmente passei por alguns problemas pessoais aos quais, graças a Deus, estou são e salvo. Foram os piores meses que passei longe das principais coisas que mais gosto na vida, mas não vou ficar aqui lamentando aos companheiros! Bola para frente.[/size] (21/03/2010)

[size=13][color=green]OUTROS TÓPICOS AUXILIARES:[/color][/size] Companheiros para ajudar ainda mais os usuários da comunidade vou relacionando outros tópicos encontrados durante as minhas pesquisas aqui dentro do GUJ com o assunto sobre MVC que trazem mais conteúdo a quem está aprendendo sobre o assunto. Espero que esses também possam colaborar com todos! Obrigado. (27/10/2009)

http://www.guj.com.br/posts/list/798.java - http://www.guj.com.br/posts/list/842.java -
http://www.guj.com.br/posts/list/1042.java - http://www.guj.com.br/posts/list/1176.java
http://www.guj.com.br/posts/list/1241.java - http://www.guj.com.br/posts/list/1278.java
http://www.guj.com.br/posts/list/10233.java - http://www.guj.com.br/posts/list/11147.java
http://www.guj.com.br/posts/list/16118.java - http://www.guj.com.br/posts/list/39725.java
http://www.guj.com.br/posts/list/60970.java - http://www.guj.com.br/posts/list/111072.java
http://www.guj.com.br/posts/list/113965.java - http://www.guj.com.br/posts/list/121777.java
http://www.guj.com.br/posts/list/121835.java - http://www.guj.com.br/posts/list/123397.java
http://www.guj.com.br/posts/list/123716.java - http://www.guj.com.br/posts/list/124530.java
http://www.guj.com.br/posts/list/124632.java - http://www.guj.com.br/posts/list/124887.java
http://www.guj.com.br/posts/list/124921.java - http://www.guj.com.br/posts/list/125045.java
http://www.guj.com.br/posts/list/125258.java - http://www.guj.com.br/posts/list/128080.java
http://www.guj.com.br/posts/list/128303.java - http://www.guj.com.br/posts/list/132839.java
http://www.guj.com.br/posts/list/132965.java - http://www.guj.com.br/posts/list/133175.java
http://www.guj.com.br/posts/list/134339.java - http://www.guj.com.br/posts/list/134345.java
http://www.guj.com.br/posts/list/134511.java - http://www.guj.com.br/posts/list/134678.java
http://www.guj.com.br/posts/list/134686.java - http://www.guj.com.br/posts/list/136825.java
http://www.guj.com.br/posts/list/140378.java - http://www.guj.com.br/posts/list/140788.java
http://www.guj.com.br/posts/list/141200.java - http://www.guj.com.br/posts/list/141376.java
http://www.guj.com.br/posts/list/141479.java - http://www.guj.com.br/posts/list/141545.java

OBS: Os tópicos antigos sobre MVC não serão mais “ressucitados” atendendo a um pedido da administração do fórum. (21/03/2010)

Muito simples: A visão pode alterar o modelo sem passar pelo controle, eu pergunto, direto? Ou o modelo para a visão é só reenderização :?:
Obrigado companheiros da programação :wink:

270 Respostas

M

a camada view serve somente para visualização se você manipular algo la dentro acredito que esteja saindo do padrão MVC.

Mas isso é puro achismo meu :slight_smile:

rodrigo.ferreira

Boa noite.

Não…

A visão “chama” o controle que atualiza o modelo… quando o modelo responder, o controle atualiza a visão… a “ponte” é o controle… ele deve fazer a transformação dos dados de uma camada para a outra… visão é só pra visualização e nada mais… assim você desacopla a lógica de negócios da lógica de visualização…

Abraço,

M

/spam on

“Tecnólogo em Informática com Ênfase em Gestão de Negócios - FATEC - Mococa - SP”
Mesmo curso que eu to fazendo ;x termino daqui 2 semanas -

/spam off

pedromuyala

markin1:
/spam on

“Tecnólogo em Informática com Ênfase em Gestão de Negócios - FATEC - Mococa - SP”
Mesmo curso que eu to fazendo ;x termino daqui 2 semanas -

/spam off

Que é isso? Spam!!! Meu Deus, aqui no nosso GUJ nãããããooooo!!! :shock:

pedromuyala

Mais uma simples: Devemos encapsular a visão?

Entendam: Tenho uma tela de cadastro onde os dados são informados em JTextField’s. Esses são atributos privados da classe Visão.
Para o controle recolher o valor dos JTextField’s, devo criar métodos GET/SET, procede?

Obrigado a todos os companheiros que estão colaborando! :wink:

M

Bom ^^ eu crio os Get/Set para os meus campos da classe View.

rodrigo.ferreira

:slight_smile: markin1, que legal que você também está fazendo este curso… ele é muito bom… mas esse negócio de “spam” pegou mal mesmo… rsrsrsrs

Pelas boas práticas, você deve sempre manter os atributos privados (protegidos de acesso externo direto) e criar métodos públicos para atribuir e obter os valores para estes atributos (especificação JavaBeans)… por que assim, você consegue centralizar a lógica para o controle dos valores que podem ser inseridos neles. Imagine um banco… imagine se um um usuário conseguisse acessar o objeto “ContaCorrente” e atribuir o valor saldo diretamente nele: poderia ser um baita de um estrago… mas se você tiver um único ponto de acesso (setSaldo(…), por exemplo) você pode colocar alguma lógica de validação de valores, log de operações, etc… aí… e resolve-se o problema…

Mas direto ao ponto, o controller precisa acessar seus JTextFields através de método publicos… portanto, você deve criá-los… Pesquise sobre encapsulamento para saber mais sobre esta e outras técnicas indispensáveis para o nosso dia-a-dia…

Abraço,

pedromuyala

Perfeito ferreira! :smiley:

Essas duas perguntas fiz realmente para acabar com dúvidas. Muita gente acaba fazendo confusão com elas, até mesmo porque tentam achar uma resposta exata e acabam achando 200 diferentes sobre essas perguntas. Quem quiser dar opiniões diferentes, pode postar! Estamos aqui para aprender e ajudar. :-o

Agora, mais uma simples: E se os métodos da visão mudarem/deixarem de existir, quem vai avisar a equipe do controle? O mesmo pergunto no caso do Modelo :?:

pedromuyala

Ninguém mesmo? Nem uma idéia?

rodrigo.ferreira

Bom dia!

O controle geralmente tem um modo de detectar os métodos da visão através de introspecção/reflection (ele abre o .class e detecta os atributos da view através dos métodos públicos “get e set” dele… então, esta atualização dá-se automaticamente) e quanto ao modelo, você deve projetar bem as interfaces, por que aí você pode mudar a implementação sem mudar a forma de acesso externo… caso haja uma mudança brusca neste ítem, você terá que atualizar todos os componentes que acessam a sua interface, e aí, você poderá ter vários problemas… portanto, novamente: projete bem as interfaces de acesso, por que se precisar alterar o “recheio”, ninguém que utiliza a sua interface ficará sabendo e não sofrerá nenhum problema.

Abraço,

pedromuyala

Legal Ferreira, parabéns por estar colaborando! :wink:

Mais uma pergunta: E as DAO’s, seram chamadas por métodos no modelo controle ou pelo bean no modelo? :idea:

L

Desculpem iniciar a discussão bem tarde, mas a definição acima não está correta. O controle não é “ponte” entre visão e modelo, o controle só existe para receber estímulos da visão (ou seja, quando o usuário mexe na tela), que invoca ações no modelo, nada mais. Quando, por exemplo, for o caso da visão que se renderiza “lendo” o model, não há controle intermediando, o acesso é direto mesmo, e não há nada de errado nisso. Entendam que a premissa do MVC é do modelo não depender da visão, porque este muda frequentemente. Mas o contrário não é verdadeiro, porque o modelo tende a ser mais estável.

A sim, não sei como se classificam modelo, visão e controle, mas, com certeza, não são camadas.

L

rodrigo.ferreira:
Pelas boas práticas, você deve sempre manter os atributos privados (protegidos de acesso externo direto) e criar métodos públicos para atribuir e obter os valores para estes atributos (especificação JavaBeans)… por que assim, você consegue centralizar a lógica para o controle dos valores que podem ser inseridos neles. Imagine um banco… imagine se um um usuário conseguisse acessar o objeto “ContaCorrente” e atribuir o valor saldo diretamente nele: poderia ser um baita de um estrago… mas se você tiver um único ponto de acesso (setSaldo(…), por exemplo) você pode colocar alguma lógica de validação de valores, log de operações, etc… aí… e resolve-se o problema…

Mas direto ao ponto, o controller precisa acessar seus JTextFields através de método publicos… portanto, você deve criá-los… Pesquise sobre encapsulamento para saber mais sobre esta e outras técnicas indispensáveis para o nosso dia-a-dia…

Eu sei que essa é a teoria corrente que sustenta a existência dos getters e setters. Mas na prática, os programadores tendem a deturpá-la. Por dois motivos:

  1. Métodos que começam com get|set podem até encapsular alguma coisa, mas não são os únicos, porque qualquer método com qualquer padrão de assinatura que manupula atributos privados está encapsulando alguma coisa sobre esse objeto. A vantagem de usar get e set não se sustenta.

  2. Por conta de geradores automáticos de getters e setters, as pessoas nunca, mas nunca mesmo, colocam lógica de validação, higienização ou log dentro de um getter ou setter. Pior, para muitos, a alteração de atributos implica na alteração de métodos, o que invalida o encapsulamento.

L

Resposta rápida:
DAOs são parte do modelo. Simples.

Resposta demorada:
DAOs são parte do modelo, mas, preferencialmente, é melhor eles serem invocados por algum objeto de serviço, que encapsula uma lógica de negócio. Os métodos do objeto de serviço são chamados pelo controle.

peczenyj

Se vc adotar uma abordagem DDD, o Repositorio faz parte do modelo e pode, internamente, usar um DAO para acessar o banco de dados.

pedromuyala

Desculpem iniciar a discussão bem tarde, mas a definição acima não está correta. O controle não é “ponte” entre visão e modelo, o controle só existe para receber estímulos da visão (ou seja, quando o usuário mexe na tela), que invoca ações no modelo, nada mais. Quando, por exemplo, for o caso da visão que se renderiza “lendo” o model, não há controle intermediando, o acesso é direto mesmo, e não há nada de errado nisso. Entendam que a premissa do MVC é do modelo não depender da visão, porque este muda frequentemente. Mas o contrário não é verdadeiro, porque o modelo tende a ser mais estável.

A sim, não sei como se classificam modelo, visão e controle, mas, com certeza, não são camadas.

Olá Leonardo3001, bem vindo ao tópico! :wink:

Rapaz, concordo sim com o que falou e essa era minha ideia inicial. Mas, me tira uma dúvida: Quando a visão vai saber o momento de se renderizar com as mudanças no modelo? Quem vai avisá-la?

pedromuyala

Fala Tiago Peczenyj, obrigado por estar colaborando conosco! :wink:

Dúvida: Nesse caso, a classe do modelo (Ex. Pessoa.class) que usar banco de dados deverá implementar um método para criação do objeto da classe Repositório?
E como elas se comunicarão?

Abração, aguardo pelas opiniões e sugestões companheiros! :idea:

pedromuyala

Nem uma idéia? :idea:
Nada mesmo… :frowning:

Vamos nos basear em que:

O controle não é “ponte” entre visão e modelo, o controle só existe para receber estímulos da visão (ou seja, quando o usuário mexe na tela), que invoca ações no modelo, nada mais. Quando, por exemplo, for o caso da visão que se renderiza “lendo” o model, não há controle intermediando, o acesso é direto mesmo, e não há nada de errado nisso. Entendam que a premissa do MVC é do modelo não depender da visão, porque este muda frequentemente. Mas o contrário não é verdadeiro, porque o modelo tende a ser mais estável.

Entende-se então que o controle não vai, de forma alguma, dar set’s (atualizar algo) na visão. Concorda?

Modelo model = new Modelo();   
Visao view = new Visao(model);   
Controle control = new Controle(view, model);

Se é assim realmente, tenho algumas dúvidas. São elas:

1ª Validar) Quando o controle pegar os dados vindos da visão (jtextfields.getText()) e validar (tipos, tamanho, validarCPF, etc…) se algum dados não passar na validação, como vou mostrar isso ao usuário, já que a view só se atualiza com base no modelo?

2ª Comunicar) Como e Quando a visão saberá que o modelo foi alterado?

Agradeço antecipadamente a colaboração, sugestão, opinião ou somente a leitura do tópico! :wink:
Fico no aguardo pelas respostas!

rodrigo.ferreira

Ola Pedro, pelo visto temos opiniões diferentes… porém, meu raciocínio é baseado no que uso no dia-a-dia e em obras publicadas de autores conceituadíssimos… como você mesmo disse, se o controle não atualiza a visão, quem avisa a visão de algo não passar na validação:: caímos no conceito de “espaguete” (imagine que você tenha vários servlets que respondem a solicitações de dezenas de JSPs… o que aconteceria se você alterasse uma JSP… você teria que ir em todos os servlets que apontam pra ela e mudar isso manualmente… olha o problema e o risco de erros que você teria… então, centraliza-se tudo no controller, aí, se mudar uma JSP, você muda no controller o resto já fica tudo resolvido… afinal, se pensarmos que o modelo pode atualizar a view sem passar pelo controller, logo percebemos que não precisamos do controller, ou precisamos:: rsrsrs…) . Mas como não sou o dono da verdade, também não digo que o raciocínio dos colegas está errado… apenas diferente… e podem estar certos, dentro de um certo contexto.

Por convenção de obras publicas (é claro que existem divergências), MVC (Model 2 - WEB) se reduz nisto:

Isto é pra web, que uso no dia-a-dia… Quanto à utilização em Swing, creio que seja a mesma coisa, mais não posso afirmar com exata certeza, pois não é a minha especialidade… porém, a sua dúvida presume a conclusão sobre MVC.

Bem, você pode estudar MVC através de vários links:

http://pt.wikipedia.org/wiki/MVC
http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/

e principalmente aqui: http://java.sun.com/blueprints/patterns/MVC.html (blueprint - Recomendação oficial da Sun Microsystems).

Muito bom o debate… porém, este assunto é muito divergente… e talvez não tenha fim… rsrsrs… portanto, tire uma conclusão própria.

Abraço,

L

Numa aplicação desktop, a visão muda assim que o model muda, só assim para ter uma consistência. (Imagine seu tocador de MP3, onde a informação de uma música está sendo exibida em duas janelas diferentes. Quando você renomeia o título da música em uma janela, a alteração deve aparecer no mesmo instante na outra janela.) Isso é feito através do padrão Observer, onde seu model é o “observado” que notifica, a quem estiver observando, alguma alteração. O observador é a view, que quando notificado, fara re-renderização da janela (e sem intermédio de controller).

Agora, numa aplicação Web, o que existe é um MVC degenerado, porque as telas NÃO são atualizadas quando ocorre alteração do model (se você consultar um registro numa página, um outro usuário faz update nesse registro e você, depois, não fizer nada, então continuará a ver o mesmo dado antigo na tela).

@Rodrigo

Nunca disse para atualizar model sem passar pelo controller. O que a view poderia fazer diretamente é a consulta, CON-SUL-TA, ao model. Ok?

Outra, imagine uma entidade chamada Produto (model). Aí, quando você consulta, muito provavelmente chamará o controller, que é classe ProdutoAction e método consulta(), certo? Pela lógica do framework, a view será direcionada para /WEB-INF/pages/produto/produto-consulta-ok.jsp, que seria mais ou menos assim:

<p>Produto selecionado: ${produto.nome} <br>Por apenas <span class="preco">${produto.preco}</span></p>

Repare, a view conhece o model, sabe que existe um produto e este tem nome e preco como atributos.

Isso todo mundo faz, mas esquecem que esta é a implicação de que a view conhece o model, manipulando-o apenas para a consulta.

pedromuyala

Fala Ferreira, obrigado por continuar atento acompanhando o tópico! :smiley:
Muito legal a explicação acima sobre MVC e suas variantes!

rodrigo.ferreira:
Isto é pra web, que uso no dia-a-dia… Quanto à utilização em Swing, creio que seja a mesma coisa, mais não posso afirmar com exata certeza, pois não é a minha especialidade… porém, a sua dúvida presume a conclusão sobre MVC.

Essa ficou em aberto agora hein! Já é mais uma nova pergunta para os programadores Java SE!
E o MVC em Desktop, devemos seguir o mesmo para o modelo WEB?
Acredito eu que sim, só que nesse caso usariamos interfaces entre modelo<->controle E modelo<->visão. Estou certo?

Esses links são bons realmente. O primeiro e o última já os conhecia. O segundo foi novidade!

Realmente agradeço Ferreira sua colaboração, espero que continue acompanhando o tópico!
E para todos que estão lendo, respondendo ou não, agradeço antecipadamente pelo tempo utilizado aqui. :wink:
E espero por mais sugestões, contradições, visões diferentes, críticas, opiniões, etc.

Ah as perguntas que fiz acima continuam em aberto aguardando mais respostas! Não deixem de dar sua opinião! Obrigado.

pedromuyala

Fala Leonardo, parabéns por estar aqui acompanhando o tópico!

Numa aplicação desktop, a visão muda assim que o model muda, só assim para ter uma consistência. (Imagine seu tocador de MP3, onde a informação de uma música está sendo exibida em duas janelas diferentes. Quando você renomeia o título da música em uma janela, a alteração deve aparecer no mesmo instante na outra janela.) Isso é feito através do padrão Observer, onde seu model é o “observado” que notifica, a quem estiver observando, alguma alteração. O observador é a view, que quando notificado, fara re-renderização da janela (e sem intermédio de controller).

Corretíssimo! O padrão Observer. É o que diz também grandes personalidades no mundo java sobre MVC Desktop.
Quero até deixar esse link que mostra um exemplo aplicado.
Não quero ser muito detalhista, mas o Observer usa a única herança disponível que temos na classe. Se for analisar bem, o Observer é o “controlador” entre modelo e visões.
Porque então não não implementar um método simples de atualização na visão na qual o controle chamaria toda vez que ele alterasse algo no modelo? (veja imagem em anexo) Quais problemas isso acaba gerando?

Veja como serão chamadas as classes:

Modelo model = new Modelo(); Visao view = new Visao(model); Controle control = new Controle(visão, modelo); Um problema (com ou sem Observer): Se o usuário do MP3 tentar colocar no nome da música caracteres inválidos. Como o usuário vai ficar sabendo disso, digo, como a visão mostrará o erro?

Leonardo3001:
Agora, numa aplicação Web, o que existe é um MVC degenerado, porque as telas NÃO são atualizadas quando ocorre alteração do model (se você consultar um registro numa página, um outro usuário faz update nesse registro e você, depois, não fizer nada, então continuará a ver o mesmo dado antigo na tela).

Interessante é o seguinte: E se agora eu quiser passar minha aplicação Desktop para a WEB? Se eu fizer o desktop com esse “MVC degenerado” talvez eu ganhe um bom tempo, tendo somente que mudar a visão, não acha?

Valew galera estarem contibuindo com o tópico!
Com certeza muitos que estão aprendendo estaram se beneficiando com as opiniões!
Obrigado Leonardo por estar conosco! :wink:
Não deixem de continuar lendo e participando. Obrigado.



rodrigo.ferreira

Pedro, bom dia! Agora você chegou no ponto certo! :slight_smile:

Diferença principal entre MVC 1 e 2:

“MVC1 it combines the presentation logic with the business logic where as MVC2 it seperates the presentation logic from business logic”

Pronto.

Este “MVC Degenerado” é utilizado, se não por todos, pela grande maioria dos sistemas web feitos em Java; ele é implementado por frameworks como: Struts 1x e 2, JSF (especificação oficial Java EE 5), Webwork, Spring MVC, VRpator etc… e utilizado em praticamente todos os projetos web feitos que em java que você possa usar (bancos, e-commerces, bolsas de valores, seguradoras, setor metalúrgico, de varejo, etc)… e permite o desacoplamento total da visão das outras camadas, logo, você pode facilmente trocar a visão, sem mudar nada no resto; este é o ponto…

Obs: SOA - ESB também utiliza praticamente este mesmo conceito, só que sem a visão (todas as chamadas são centralizadas num controller, e toda a parte de acoplamento é feito nele).

Resumindo: Em aplicações realmente corporativas (Java EE 5 - MVC-2), a visão não sabe nada sobre o modelo, e o modelo não sabe nada sobre a visão, o controle é a “ponte”… você pode utilizar a mesma interface do modelo para aplicações Web, Swing, batch ou até ME… a visão é desacoplada do restante, e isto, pode ter certeza, facilita e muito o trabalho (evitando retrabalho).

No final das contas, você deve utilizar o que se encaixar melhor no seu projeto. O MVC 1 é uma abordagem mais antiga de MVC (quando ainda não existiam muitos sistemas grandes e cheios de componentes), o MVC 2 é uma abordagem mais moderna (baseado no padrão Front Controller - http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html), para descoplar totalmente as camadas (o que não é possível utilizando o padrão Observer - que gera uma total depedência). MVC-2 é o padrão oficial da especificação JEE 5, implementado pelo framework JSF (http://java.sun.com/javaee/javaserverfaces/)

A abordagem de JEE para JSE é diferente, portanto reitero, não sei exatamente como esta abordagem pode ser aplicada em Swing.

A escolha para qual se encaixa melhor no seu projeto é exclusivamente sua…

Abraço,

fantomas

pedromuyala

Utilizar o padrão MVC em sistemas que envolvem swing + banco de dados ou web NA MAIORIA das vezes é muito difícil de implementa-lo na integra de forma que fique realmente satisfatório; por isso que causa bastante confusão. Porque vc implementa e no final fica aquela sensação de que está faltando alguma coisa ou o que foi feito não está correto.

Na minha opinião os seguintes aspectos complicam a implementação do MVC nestes sistemas (swing + bdo, web e etc… ).

  1. Eles necessitam da presença de vários outros padrões além do MVC.
  2. Na implementação do MVC existe a tendencia da utilzação do padrão Observer para se chegar na relação entre os 3 pontos (M, V e C) o que pode deixar a aplicação bastante complexa e dificultar muito o entendimento e a manutenção; muito embora alguns recursos tenham sido adicionados pela SUN para ajudar neste sentido.
  3. A busca da reação das ações e a baixa dependencia neste padrão muitas vezes gera fluxos bastante confusos.

O ideal seria adotar um framework para ajudar com este padrão, infelizmente para swing não tem muitos e os poucos que tem sempre tem algumas coisas esquisitas, mas é melhor que nada. Sem utilizar frameworks, geralmente é feita a implementação “parcial” do padrão na tentativa de organizar e facilitar as coisas assumindo que há limites.

flws

L

pedromuyala:
Corretíssimo! O padrão Observer. É o que diz também grandes personalidades no mundo java sobre MVC Desktop.
Quero até deixar esse link que mostra um exemplo aplicado.
Não quero ser muito detalhista, mas o Observer usa a única herança disponível que temos na classe. Se for analisar bem, o Observer é o “controlador” entre modelo e visões.

Não, nem tudo que controla é controlador, pelo menos não para o MVC. O controlador é estritamente para controle de eventos ou de entrada do usuário.

É um simples que acaba saindo caro. Imagine que eu tenha o model M, e eu tenha as views V1, V2 e V3 que a renderizam. Se quem as notificam for o controler C, então seus métodos explicitamente terão que chamar o método de atualização de V1, V2 e V3. Imagine que agora a view V4 também renderizará M, dái você terá que procurar todos os métodos do controler que já manda atualizar as views anteriores para atualizar também a V4. (Pior, e se você esquecer de algum?)

O Observer deixa as coisas meio complicadas a princípio, mas o benefício é que você não polui o Controller com código repetitivo.

L

Concordo. Quando disse “degenerado”, não quis menosprezar a implementação de MVC pela Web. Todos os frameworks web fazem um MVC “degenerado”, e isso não é nenhum demérito, pois a arquitetura cliente-servidor tem as suas limitações que precisam ser respeitadas.

A view não necessariamente é uma tela para um usuário, pode ser também um XML para consumo externo de outros aplicativos.

Não é. Se a visão não sabe do modelo, como ela se renderiza? Pela adivinhação? O controle sempre repassa o modelo pra view, e a view sempre conhece o model.

rodrigo.ferreira

Bom dia Leonardo… vamos aumentar um pouco mais o tópico… rsrsrs :slight_smile:

Em JEE 5, utilizando MVC com JSF, por exemplo, a JSP conhece um java bean chamado "Managed Bean" (uma Action no caso do Struts 1x), que fica do lado da visão, e nada tem haver com o modelo; a JSP interage única e exclusivamente com este bean (do lado da visão). Este bean faz o "binding", obtendo todos os dados da requisição e devolvendo os dados para o JSP, automaticamente. Ao solicitar dados do modelo, a JSP chama o ManagedBean, que utiliza geralmente os padrões (Business Delegate, Service Locator e Session Facade), encapsulando a chamada para o modelo real... quando o modelo real responder a chamada, então o Business Delegate devolve os dados formatados para o Backing Bean que devolve os dados para o JSP... é um processo um pouco complexo para ser eficazmente explicado aqui.

Um exemplo básico do tutorial oficial da JEE 5 (http://java.sun.com/javaee/5/docs/tutorial/doc/bnaqq.html) seria:

Onde “myForm.jsp” faz binding com o managed bean “myUi.java” e este sim faz a chamada para um Business Delegate que faz o restante do processo…
O ponto aqui é o seguinte: Todo o acoplamento fica encapsulado no Business Delegate; este é o responsável por chamar o modelo real e caso haja alguma alteração neste modelo, é somente com este componente que você precisará se preocupar.

Leonardo, é óbio que é possível chamar o modelo diretamente da visualização, mas isso não é comumente utilizado por questões já citadas nos tópicos anteriores… Estou citando o padrão utilizado em aplicações web corporativas.

Abraço,

L

rodrigo.ferreira:
Em JEE 5, utilizando MVC com JSF, por exemplo, a JSP conhece um java bean chamado “Managed Bean” (uma Action no caso do Struts 1x), que fica do lado da visão, e nada tem haver com o modelo; a JSP interage única e exclusivamente com este bean (do lado da visão). Este bean faz o “binding”, obtendo todos os dados da requisição e devolvendo os dados para o JSP, automaticamente. Ao solicitar dados do modelo, a JSP chama o ManagedBean, que utiliza geralmente os padrões (Business Delegate, Service Locator e Session Facade), encapsulando a chamada para o modelo real… quando o modelo real responder a chamada, então o Business Delegate devolve os dados formatados para o Backing Bean que devolve os dados para o JSP… é um processo um pouco complexo para ser eficazmente explicado aqui.

Um exemplo básico do tutorial oficial da JEE 5 (http://java.sun.com/javaee/5/docs/tutorial/doc/bnaqq.html) seria:

Onde “myForm.jsp” faz binding com o managed bean “myUi.java” e este sim faz a chamada para um Business Delegate que faz o restante do processo…
O ponto aqui é o seguinte: Todo o acoplamento fica encapsulado no Business Delegate; este é o responsável por chamar o modelo real e caso haja alguma alteração neste modelo, é somente com este componente que você precisará se preocupar.

Leonardo, é óbio que é possível chamar o modelo diretamente da visualização, mas isso não é comumente utilizado por questões já citadas nos tópicos anteriores… Estou citando o padrão utilizado em aplicações web corporativas.

Rodrigo, você mesmo disse: “Ao solicitar dados do modelo, a JSP chama o ManagedBean”, ou seja, o JSP precisa do modelo para renderizar. Não interessa pra view se precisa requisitar o model pro Controller, ou o model é automaticamente injetado nela. O fato é que a view, nos dois casos, conhece o model e, portanto tem dependência dele. E nesse caso, o model ser chamado pela view (não interessa se é direto ou indireto) é bastante comum de ser feito.

O Business Delegate é model, assim como são Service Locator e Service Delegate. Eles têm a função de concentrar alguma regra de negócio ou de acesso, mas não “encapsulam o acoplamento” como você mesmo disse. Coesão e acoplamento são características do sistema como um todo, não dá pra separá-los num módulo do sistema.

Outra, e suas Entities? Elas são parte do model e comumente são retornadas elo Service Delegate. Se houver alguma alteração num getter de uma Entity, as views precisam ser alteradas; o que contradiz sua teoria de que a view é desacoplada do model.

pedromuyala

Olá fantomas, boa tarde! Obrigado por estar participando conosco do tópico! :wink:

fantomas:
pedromuyala

Utilizar o padrão MVC em sistemas que envolvem swing + banco de dados ou web NA MAIORIA das vezes é muito difícil de implementa-lo na integra de forma que fique realmente satisfatório; por isso que causa bastante confusão. Porque vc implementa e no final fica aquela sensação de que está faltando alguma coisa ou o que foi feito não está correto.

Na minha opinião os seguintes aspectos complicam a implementação do MVC nestes sistemas (swing + bdo, web e etc… ).

  1. Eles necessitam da presença de vários outros padrões além do MVC.
  2. Na implementação do MVC existe a tendencia da utilzação do padrão Observer para se chegar na relação entre os 3 pontos (M, V e C) o que pode deixar a aplicação bastante complexa e dificultar muito o entendimento e a manutenção; muito embora alguns recursos tenham sido adicionados pela SUN para ajudar neste sentido.
  3. A busca da reação das ações e a baixa dependencia neste padrão muitas vezes gera fluxos bastante confusos.

O ideal seria adotar um framework para ajudar com este padrão, infelizmente para swing não tem muitos e os poucos que tem sempre tem algumas coisas esquisitas, mas é melhor que nada. Sem utilizar frameworks, geralmente é feita a implementação “parcial” do padrão na tentativa de organizar e facilitar as coisas assumindo que há limites.

flws


Exato. Por isso não estou utilizando nenhum framework, justamente por sentir essa sensação de perder o controle durante o desenvolvimento.
Agora você tocou em um ponto interessante sobre o uso de padrões além do MVC. Fora o Observer (Desktop) e pelo que tenho visto também o Singleton e até mesmo o Reflection, algum outro se aplica?
Os fluxos confusos que se refere são os Listener’s, procede? Registrá-los na visão para que as classes internas do controle zejam acionadas!

Abração, obrigado por estar participando! :smiley:
Fico no aguardo pela resposta! Abraço.

pedromuyala

Fala Leo, obrigado por continuar aqui discutindo esse assunto, na minha opinião, polemico! kkk.

Leonardo3001:
pedromuyala:
Corretíssimo! O padrão Observer. É o que diz também grandes personalidades no mundo java sobre MVC Desktop.
Quero até deixar esse link que mostra um exemplo aplicado.
Não quero ser muito detalhista, mas o Observer usa a única herança disponível que temos na classe. Se for analisar bem, o Observer é o “controlador” entre modelo e visões.

Não, nem tudo que controla é controlador, pelo menos não para o MVC. O controlador é estritamente para controle de eventos ou de entrada do usuário.

É um simples que acaba saindo caro. Imagine que eu tenha o model M, e eu tenha as views V1, V2 e V3 que a renderizam. Se quem as notificam for o controler C, então seus métodos explicitamente terão que chamar o método de atualização de V1, V2 e V3. Imagine que agora a view V4 também renderizará M, dái você terá que procurar todos os métodos do controler que já manda atualizar as views anteriores para atualizar também a V4. (Pior, e se você esquecer de algum?)

O Observer deixa as coisas meio complicadas a princípio, mas o benefício é que você não polui o Controller com código repetitivo.


Concordo com tudo isso aí. Acredito sim que realmente utilizando o Observer estaria implementando uma ótima solução para Desktop.
Tem uma forma (claro, um pouco complexa) de implementar usando Reflection (se não for isso que o Observer faz). Colocaria um método de atualização com o mesmo nome em todas as view’s e ao alterar o modelo, o controle por Reflection identifica as classes de visão e chama o método de atualização. Errado? Pode me corrigir se estou falando bobagem!
Pelo menos economizo a herança da classe. :idea:
Um outro detalhe: E se a visão é uma entrada de dados? E eu tiver várias visões para entrar dados. Como o controle vai “controlar” isso até esses dados chegarem na visão?

Obrigadão Léo por estar acompanhando o tópico, agradeço sem palavras! :wink:
Um abração! Não deixe de acompanhar!

pedromuyala

Será que não existe um paradigma no MVC entre WEB-SWING?
Ou seja, tenho que fazer dois sistemas mesmo. Um desktop e um web?

Ou posso fazer o sistema desktop no padrão MVC2 citado pelo companheiro Ferreira?
Como ele mesmo deixou em aberto, será que se aplica bem em Desktop?

Não deixe de opinar, criticar, dar sua sugestão, idéia, tudo aquilo que possa benefeiciar o aprendizado de todos aqui do GUJ! :idea:
Com certeza é um assunto polemico não esperava! Mas vai sim beneficiar e ajudar muita gente! :smiley:
Um abraço a todos que acompanham e desprendem do seu tempo aqui respondendo ou simplesmente lendo o tópico! Obrigado.

L

pedromuyala:

Concordo com tudo isso aí. Acredito sim que realmente utilizando o Observer estaria implementando uma ótima solução para Desktop.
Tem uma forma (claro, um pouco complexa) de implementar usando Reflection (se não for isso que o Observer faz). Colocaria um método de atualização com o mesmo nome em todas as view’s e ao alterar o modelo, o controle por Reflection identifica as classes de visão e chama o método de atualização. Errado? Pode me corrigir se estou falando bobagem!
Pelo menos economizo a herança da classe. :idea:
Um outro detalhe: E se a visão é uma entrada de dados? E eu tiver várias visões para entrar dados. Como o controle vai “controlar” isso até esses dados chegarem na visão?

O uso de Reflection apenas disfarça as dependências, com ou sem ela, o problema seria o mesmo. O padrão Observer é feito sem reflection.

É mais comum haver várias visões para visualizar dados do que para entrar dados. A razão é que formulários costumam aparecer em janelas modais (que bloqueiam a janela mãe) impedindo uma pessoa de visualizar dois formulários de inserção. Mas não havendo modal, poderia ocorrer de uma tela inadvertidamente atualizar uma outra tela que não deveria. Mas isso é exceção (normalmente queremos a propagação de atualização) e podemos tratar caso-a-caso.

pedromuyala

Fala Léo!

Leonardo3001:

O uso de Reflection apenas disfarça as dependências, com ou sem ela, o problema seria o mesmo. O padrão Observer é feito sem reflection.

É mais comum haver várias visões para visualizar dados do que para entrar dados. A razão é que formulários costumam aparecer em janelas modais (que bloqueiam a janela mãe) impedindo uma pessoa de visualizar dois formulários de inserção. Mas não havendo modal, poderia ocorrer de uma tela inadvertidamente atualizar uma outra tela que não deveria. Mas isso é exceção (normalmente queremos a propagação de atualização) e podemos tratar caso-a-caso.

Vamos tantar imaginar um sistema… esses sistemas pequenos de gestão, por exemplo, que estão no comércio (padaria, mercados, lojas, etc) que rodam localmente (Desktop).
Poderia estar até ligado a uma rede local (não deixa de ser Desktop). Concorda comigo que esses sistemas fazem forte uso de cadastro, digo formulários? Produto, cliente, pedidos, etc. Então pergunto: MVC se enquadra ao caso, não? Ou melhor usar MVC2? Se futuramente esses sistema precisar estar disponível na Internet?

Estou pegando um exemplo pequeno para que o novo desenvolvedor entenda melhor o conceito. Senão o assunto começa a ficar muito técnico e interesse do iniciante em aprender.

Já escutei algumas pessoas dizerem que a melhor solução é criar um sistema para a Internet, como a princípio não vai estar na Internet, fazer uma simulação de servidor WEB localmente, ou seja, o usuário já inicia no sistema trabalhando com ele em browser localmente e se no futuro pretender disponibilizá-lo na rede mundial nada precisaria ser alterado! Procede?

Ah pessoal, nem tenho mais palavras para agradecer aí o carinho de todos que estão acompanhando o tópico tentando ajudar de todas as maneiras. :roll:
Muito legal essa discussão, tenho certeza que estará beneficiando muita gente, isso é o mais bacana de tudo! Obrigado a todos.
Fico no aguardo por respostas. Quem não opinou, deu sua sugestão e/ou criticou ainda não tenha medo de estar atrasado! Poste no tópico. :wink:

fantomas

pedromuyala:
Vamos tantar imaginar um sistema… esses sistemas pequenos de gestão, por exemplo, que estão no comércio (padaria, mercados, lojas, etc) que rodam localmente (Desktop).
Poderia estar até ligado a uma rede local (não deixa de ser Desktop). Concorda comigo que esses sistemas fazem forte uso de cadastro, digo formulários? Produto, cliente, pedidos, etc. Então pergunto: MVC se enquadra ao caso, não? Ou melhor usar MVC2? Se futuramente esses sistema precisar estar disponível na Internet?

Na minha opinião pode e deve utilizar MVC.

Depende, as vezes utilizar só páginas pode não ser a melhor solução. Sim, se o sistema já for web facilita muito ao disponibilizar na rede, não importando qual seja.

P.S Normalmente quem diz como o sistema deve ser são os requisitos; devemos evitar ao máximo impor idéias mirabolantes.

flws

pedromuyala

Olá fantomas, obrigado por estar acompanhando o tópico! :smiley:

É acredito que seja melhor desenvolver um sistema já baseado na web mesmo rodando localmente, seguindo o MVC 2… e esquecer o MVC (aquele do Smalltalk).

Olha tenho três computadores em rede. Digamos que o computador 1 faz o papel de servidor. O computador 2 e 3 rodam o aplicativo que está no computador 1.
Nos computadores 2 e 3 estão com a view de um mesmo produto em aberto. Então o computador 3 altera a quantidade do produto e a sua view é atualizada.
Alguém sabe dizer se o computador 2 (lembrando que o aplicativo que está rodando no computador 1 foi implementado com MVC + Observer) vai atualizar a view para a quantidade correta ou computadores 2 e 3 terão view’s com quantidades diferentes? (assim como ocorreria em uma aplicação WEB)

Agradeço desde já todas as ajudas! São muito bem vindas! :wink:

fantomas

pedromuyala:
Olha tenho três computadores em rede. Digamos que o computador 1 faz o papel de servidor. O computador 2 e 3 rodam o aplicativo que está no computador 1.
Nos computadores 2 e 3 estão com a view de um mesmo produto em aberto. Então o computador 3 altera a quantidade do produto e a sua view é atualizada.
Alguém sabe dizer se o computador 2 (lembrando que o aplicativo que está rodando no computador 1 foi implementado com MVC + Observer) vai atualizar a view para a quantidade correta ou computadores 2 e 3 terão view’s com quantidades diferentes? (assim como ocorreria em uma aplicação WEB)

Como já disse antes, as vezes não dá ou até não é aconselhavel implementar o padrão na integra; mas vamos lá mesmo assim.

Considerando este seu contexto:

Se o sistema for web:

  1. A máquina 2 executa uma atualização.
  2. Na máquinas 3 haverá apenas PÁGINAS renderizadas pelo navegador e seus scripts (javascript), suas atualizações à principio são baseadas em request / response ou através de um objeto que fica de tempos em tempos executando o que muitos chamam de refresh. Ou seja, o que vc está chamando de view não recebe estimulos de uma coisa chamada controller ou algo do tipo.

Como fazer então: Existe um esquena em AJAX que vc pode incluir no script da página para se tornar um receptor da mensagem enviada pelo server quando ouver alguma atualização. Me parece que o framework ZK já tem uma mecanismo chamado pushing que resolve esta questão.

Se o sistema for swing:

  1. A máquina 2 executa uma atualização.
  2. Na máquina 3 haverá apenas os formulários swing (utilizando mvc) conectado ao servidor (máquina 1); tambem não receberá a atualização do servidor sem ter alguma coisa que fique de tempos em tempos executando uma consulta no servidor.

Como fazer então: Vc poderia utilizar um implementação JMS atrelada ao controller dos formulários da estação; quando o servidor fizer uma atualização ele envia uma mensagem para o client e a atualização será efetuada (é claro que isto é implementado por vc nas rotinas que recebem as mensagens).

É isso ai…o sistema sempre sofre influencia do meio em que será executado.

flws

pedromuyala

Olá fantomas! Estamos aí!

Então, como deve ter notado, não consigo enxergar o uso do padrão Observer.
Vamos tentar agora um exemplo diferente e que com certeza boa parte do pessoal vai entender:

Imaginem um sistema operacional como o Windows (vou pegar o Windows como exemplo, até porque o Linux é muito mais que um simples exemplo kkkk…). Se você está visualizando uma janela (janela nº1) com várias pastas e tiver uma outra janela (janela nº2) exibindo as mesmas pastas da nº1 e resolver deletar uma pasta da nº1 ou nº2 note que as duas janelas (nº1 e nº2) a pasta deletada também some, ou seja, ambas são atualizadas.

Podemos dizer (óbvio que o Windows nem de longe usa tecnologias boas como Java kkkk… Mais uma brincadeirnha! :D) que é um MVC DESKTOP COM OBSERVER?

Note também que se este mesmo caso estiver acontecendo em computadores diferentes ligados em rede (ou seja janela nº1 em uma estação e janela nº2 em outra estação) a atualização ocorre identica a do exemplo anterior citado.

Isso é MVC na camada de apresentação, ou estou enganado?
Valew pessoal, estou no aguardo por respostas! :wink: Obrigado.

fantomas

Olhando por fora parece que sim, o problema é que Observer é apenas o nome de um pattern. Como vc pode chegar no mesmo resultado por outros caminhos fica dificil dizer sem analizar o código utilizado.

pedromuyala:
Note também que se este mesmo caso estiver acontecendo em computadores diferentes ligados em rede (ou seja janela nº1 em uma estação e janela nº2 em outra estação) a atualização ocorre identica a do exemplo anterior citado.
Isso é MVC na camada de apresentação, ou estou enganado?

Eu acredito que sim, talvez a maneira com que foi implementado é que não seja como imaginamos.

flws

pedromuyala

Pois então, esse comportamento dos exemplos acima parecem ser bem interessante.

A grande dificuldade, acredito eu, não é entender a teoria mas sim a forma de implementação.
Como separar as coisas!

Veja:
Modelo é só os Beans?
Persistencia, os métodos ficam escritos dentro dos Beans?
E controle, só responde ações da visão?
A visão reenderiza o bean do Modelo para mostrá-lo. Mas e se a visão for um formulário? Como os dados vão chegar até o modelo?
Como desacoplo visão do modelo? Com Observer em Desktop. Mas e na WEB?
Encapsulamento: Deve ser usada no Modelo, no Controle e na Visão?
Essas são as dúvidas dos iniciantes… :wink:

Não deixem de participar respondendo essas perguntas básicas.
Sabemos que para grande parte do pessoal são coisas tão simples que ficam até difícil de responder.
Mas por favor, não deixem essas perguntas em aberto. Obrigado pessoal!



fantomas

Existem centenas de respostas para estas suas perguntas e dentro delas varios “depende”.

Uma coisa que ajuda bastante a “filtrar” a caisa é saber quais são os requisitos do sistema e em que contexto ele será executado.

Não existe uma fórmula única e muitas vezes nem exata para tudo (a tal bala de prata).

Se vc sugerir alguns requisitos e um contexto mais especifico a respeito de suas dúvidas acredito que poderemos fornecer respostas mais objetivas.

Por exemplo:

a) O sistema será client x server e tem tais e tais requisitos.
b) O sistema será web e tais requisitos.
c) Será swing porem poderá acessar um servidor web com tais requisitos.

A idéia do padrão MVC poderá mudar mesmo que ligieramente dependendo das opções acima.

flws

L

Model é o “resto”, o que não é view e nem controller. Beans, Entities, Value Objects, DAOs, Service Locators, Façades… tudo isso é model.

O MVC não diz tudo, não diz como o model deve se comportar, por exemplo. Então, tanto faz (do ponto de vista do MVC) como você faz a persistência.

Sim.

O Controller manda um bean vazio, por exemplo. É ele quem decide.

Observer serve para desacoplar o modelo da visão, não o contrário. Dado dois módulos A e B que precisam trabalhar em conjunto, você só tem duas alternativas: A está acoplado em B mas não o contrário; ou B está acoplado em A mas não o contrário. Não existe essa: “Ah, tanto a view quanto o model estão desacopladas entre si!”. Quem fala isso, não sabe o que diz.

Então, view fica acoplada ao model. Ponto. Já para desacoplar model da view, usa-se Observer no Desktop.

Na web, normalmente, não se faz essa ponta do Observer. Mas pode ser feito, usando técnicas de “AJAX Reverso” que tem por aí.

O que você entende por encapsulamento?

pedromuyala

fantomas:
Existem centenas de respostas para estas suas perguntas e dentro delas varios “depende”.

Uma coisa que ajuda bastante a “filtrar” a caisa é saber quais são os requisitos do sistema e em que contexto ele será executado.

Não existe uma fórmula única e muitas vezes nem exata para tudo (a tal bala de prata).

Se vc sugerir alguns requisitos e um contexto mais especifico a respeito de suas dúvidas acredito que poderemos fornecer respostas mais objetivas.

Por exemplo:

a) O sistema será client x server e tem tais e tais requisitos.
b) O sistema será web e tais requisitos.
c) Será swing porem poderá acessar um servidor web com tais requisitos.

A idéia do padrão MVC poderá mudar mesmo que ligieramente dependendo das opções acima.

flws

Olá fantomas, desculpa não responder antes passei por alguns problemas familiares, mas resolvidos! :smiley:

Imagine que seja um sistema de mala direta para divulgação de produtos de informática. Essas pessoas vão informar seus dados pessoais no atendimento. Então poderão receber via correio a divulgação do material. Agora esse sistema precisa também poder atualizar o cadastro e até excluir um pessoa na qual não deseja mais receber o informativo. Esses sistema futuramente (após um 1 ano aproximadamente) também disponibilizará um site na Internet na qual a pessoa poderá atualizar seus dados sem precisar ir no atendimento da empresa. Pronto é isso.

Existem 3 computadores do tipo PC. Eles estão conectados por um roteador. Um deles é que tem o programa instalado. Os outros dois chamam pela rede o sistema instalado no servidor. E a tela mostrando os dados de uma mesma pessoa poderá estar aberta nos três computadores ao mesmo tempo.

Fiz perguntas melhores, passando o problema? Ou agora eu compliquei tudo de vez mesmo? :?:
Valew fantomas, obrigado por estar aqui! Abraço. :wink:

fantomas

pedromuyala:
Olá fantomas, desculpa não responder antes passei por alguns problemas familiares, mas resolvidos!

Imagine que seja um sistema de mala direta para divulgação de produtos de informática. Essas pessoas vão informar seus dados pessoais no atendimento. Então poderão receber via correio a divulgação do material. Agora esse sistema precisa também poder atualizar o cadastro e até excluir um pessoa na qual não deseja mais receber o informativo. Esses sistema futuramente (após um 1 ano aproximadamente) também disponibilizará um site na Internet na qual a pessoa poderá atualizar seus dados sem precisar ir no atendimento da empresa. Pronto é isso.

Existem 3 computadores do tipo PC. Eles estão conectados por um roteador. Um deles é que tem o programa instalado. Os outros dois chamam pela rede o sistema instalado no servidor. E a tela mostrando os dados de uma mesma pessoa poderá estar aberta nos três computadores ao mesmo tempo.

Fiz perguntas melhores, passando o problema? Ou agora eu compliquei tudo de vez mesmo?
Valew fantomas, obrigado por estar aqui! Abraço.

Entendi…acho que ficou mais claro; ao menos para mim.

Acredito que vc já falou isto antes, mas só para ter absoluta certeza.

Supondo que as estações (os 2 micros q vc comentou) estejam com a mesma tela, e uma informação presente nesta tela seja alterada; a(s) outra(s) estação(ões) deverão ser atualizada, é isto?

flws

pedromuyala

Isso fantomas, exatamente isso! :smiley:

pedromuyala

Fala Leonardo, obrigado por estar atento aqui no tópico! :smiley:

Leonardo3001:
pedromuyala:

Persistencia, os métodos ficam escritos dentro dos Beans?

O MVC não diz tudo, não diz como o model deve se comportar, por exemplo. Então, tanto faz (do ponto de vista do MVC) como você faz a persistência.


Porque “do ponto de vista do MVC”? Por causa de outras arquiteturas?
Mas e no MVC, geralmente quando entra persistencia em BD, o que mais se usa no seu ponto de vista?

Leonardo3001:
pedromuyala:

A visão reenderiza o bean do Modelo para mostrá-lo. Mas e se a visão for um formulário? Como os dados vão chegar até o modelo?

O Controller manda um bean vazio, por exemplo. É ele quem decide.


Desculpa a minha ignorância, eu não entendi. :frowning:
A visão vai carregar os dados informados direto no bean? E pode a visão conhecer o modelo?

Observer serve para desacoplar o modelo da visão, não o contrário. Dado dois módulos A e B que precisam trabalhar em conjunto, você só tem duas alternativas: A está acoplado em B mas não o contrário; ou B está acoplado em A mas não o contrário. Não existe essa: “Ah, tanto a view quanto o model estão desacopladas entre si!”. Quem fala isso, não sabe o que diz.

Então, view fica acoplada ao model. Ponto. Já para desacoplar model da view, usa-se Observer no Desktop.

Na web, normalmente, não se faz essa ponta do Observer. Mas pode ser feito, usando técnicas de “AJAX Reverso” que tem por aí.

O que você entende por encapsulamento?

Por encapsulamento entendo atributos privados de uma classe que só podem ser acessados através de métodos set/get.

Tenho uma dúvida que não sai da cabeça: Se a visão é um formulário na qual recebeu um Bean vazio para ser preenchido a validação de tipos, por exemplo, vai ter que ser feita na VIEW. Imagine: Telefone é um atributo de tipo int. Mas o formulário tem um JTextField. Se o cara digitar caracteres no JTextField do telefone e eu não tratar esse problema é erro na certa.

No meu entender o controle recebe dois objetos: Visão e Modelo. É ele que intermedia OQ vai aparecer na visão e o que vai ser guardado no modelo. É ele quem cuida da validação de dados e tipos. Nele também são tratados os eventos da view. Estou errado?

  • Como deveria ser o fluxo?
  • Quem fala com quem?

Valew Léo, desculpa se estou tendo dificuldades para entender. :frowning:
Posso garantir que estou me empenhando ao máximo para tentar pegar a idéia real do MVC.
Não desista. Peço aos demais também para terem paciência. Tenho certeza que uma hora vou entender, não é possível! Obrigado. :smiley:

pedromuyala

Oi pessoal!
Acho que continuo não conseguindo expor o problema de forma que todos entendam, estou errado?
Mas realmente estou iniciando por isso minhas dúvidas são bem básicas. :slight_smile:

Tentei expor a situação do problema nas respostas anteriores. Mas vejo que até o próprio pessoal que vem contribuindo na tentativa de ajudar já está cansando de mostrar soluções boas e o problema continuar. Peço que não desistam e, quem estiver olhando o tópico pela primeira vez que não deixe de dar sua opinião, ajuda, idéia, sugestão ou crítica.
Agradeço antecipadamente a atenção que todos vem dispensando aqui neste tópico. Obrigado mesmo! :wink: :smiley:

pedromuyala

Olá pessoal, estou de volta com uma pergunta nova. :smiley:
Li o livro do Deitel (4ªed.) e prestei muita atenção no exemplo do elevador.
Reparei que ele coloca no controle dois JButton que quando acionados alteram alguma coisa na visão do elevador.

Então fico com uma pergunta a ser feita: O formulário para cadastrar uma pessoa no sistema, ou seja, seus JTextField’s (onde entro com os dados da pessoa) e seu JButton (para efetuar o cadastro ao final do preenchimento) devem estar dentro do controle e não na visão, procede? Alguém contra?

Outro detalhe: Ele não usa Observer em nada. Faz uso massivo de Listener’s. Toda comunicação entre o Modelo e a Visão é feito por classes que estão em um pacote denominado por ele “event”. Porque? Qual a vantagem disso em não usar o Observer?

Abraço pessoal novo e antigo que está aqui no tópico já a mais de um mês!
Felicidades a todos. :wink:

tnaires

Creio que não. Tudo aquilo que representar interface gráfica está na visão. O que o controle recebe são apenas os dados que foram inseridos nos componentes, e não os componentes em si.

Ué, mas um listener é um observer! Quando um listener é registrado para um determinado componente, ele passa a observar os eventos que ocorrem no componente.

pedromuyala

Olá tnaires, obrigado em responder!

É realmente é difícil entender né esse MVC. Cada um tem uma resposta diferente não existe um padrão por sí só.
Minha idéia era desenvolver um sistema de forma que qualquer outro programador que fizer manutenção nele tenha como entender de forma fácil, ou seja, perceptível a arquitetura que nele está aplicada. Mas já percebi que é praticamente impossível. kkkkk.
A solução é fazer do jeito que eu entendo ser o melhor jeito, o mais prático, o mais fácil, sem seguir absolutamente nada.
Um abração a todos que ajudaram nesse tópico. Obrigado.

pedromuyala

Olhem o exemplo abaixo, acho que isso deixa bem claro a minha dúvida:

"…
Ainda que existam diferentes formas de MVC, o controle de fluxo geralmente funciona como segue:

  1. O usuário interage com a interface de alguma forma (por exemplo, o usuário aperta um botão)
  2. O Controller manipula o evento da interface do usuário através de uma rotina pré-escrita.
  3. O Controller acessa o Model, possivelmente atualizando-o de uma maneira apropriada, baseado na interação do usuário (por exemplo, atualizando os dados de cadastro do usuário).
  4. Algumas implementações de View utilizam o Model para gerar uma interface apropriada (por exemplo, mostrando na tela os dados que foram alterados juntamente com uma confirmação). O View obtém seus próprios dados do Model. O Model não toma conhecimento direto da View.
  5. A interface do usuário espera por próximas interações, que iniciarão o ciclo novamente."

A pergunta: Interface do usuário é diferente de view?
Se sim, então Qual a função da interface do usuário e qual a função da view? Como elas interagem?
Abraço a todos, aguardo resposta nessa última tentativa PQ está difícil.

pedromuyala

kkkk… desistiram de mim! Mas mesmo assim valew a todos!

luistiagos

fantomas:
pedromuyala:
Olha tenho três computadores em rede. Digamos que o computador 1 faz o papel de servidor. O computador 2 e 3 rodam o aplicativo que está no computador 1.
Nos computadores 2 e 3 estão com a view de um mesmo produto em aberto. Então o computador 3 altera a quantidade do produto e a sua view é atualizada.
Alguém sabe dizer se o computador 2 (lembrando que o aplicativo que está rodando no computador 1 foi implementado com MVC + Observer) vai atualizar a view para a quantidade correta ou computadores 2 e 3 terão view’s com quantidades diferentes? (assim como ocorreria em uma aplicação WEB)

Como já disse antes, as vezes não dá ou até não é aconselhavel implementar o padrão na integra; mas vamos lá mesmo assim.

Considerando este seu contexto:

Se o sistema for web:

  1. A máquina 2 executa uma atualização.
  2. Na máquinas 3 haverá apenas PÁGINAS renderizadas pelo navegador e seus scripts (javascript), suas atualizações à principio são baseadas em request / response ou através de um objeto que fica de tempos em tempos executando o que muitos chamam de refresh. Ou seja, o que vc está chamando de view não recebe estimulos de uma coisa chamada controller ou algo do tipo.

Como fazer então: Existe um esquena em AJAX que vc pode incluir no script da página para se tornar um receptor da mensagem enviada pelo server quando ouver alguma atualização. Me parece que o framework ZK já tem uma mecanismo chamado pushing que resolve esta questão.

Se o sistema for swing:

  1. A máquina 2 executa uma atualização.
  2. Na máquina 3 haverá apenas os formulários swing (utilizando mvc) conectado ao servidor (máquina 1); tambem não receberá a atualização do servidor sem ter alguma coisa que fique de tempos em tempos executando uma consulta no servidor.

Como fazer então: Vc poderia utilizar um implementação JMS atrelada ao controller dos formulários da estação; quando o servidor fizer uma atualização ele envia uma mensagem para o client e a atualização será efetuada (é claro que isto é implementado por vc nas rotinas que recebem as mensagens).

É isso ai…o sistema sempre sofre influencia do meio em que será executado.

flws

O que é este tal framework ZK?

fantomas

http://www.zkoss.org/

flws

pedromuyala

Vou tentar deixar bem claro, acho que agora a galera vai conseguir entender a pergunta (MVC DESKTOP/SWING).
Antes de tudo quero também deixar claro que estou com dúvida mesmo e não querendo fazer com que os outros trabalhem para mim ok? Quero aprender mesmo.

Sendo assim, aí vai:

Tenho que fazer um cadastro de cliente com o nome e CPF do cidadão. (Até esse momento vamos ignorar persistencia, validação, etc…).
Até aí simples. Mas como implementar isso na arquitetura do MVC, ou seja, onde cada coisa vai ficar em uma das três letras?

Primeira coisa :lol: (“coisa”… só rindo mesmo):
1-> Formulário de entrada de dados;

No formulário, vamos ter campos JTextField e o botão adicionar (Formulário é Visão “View”, procede?):

class ClienteView extends JPanel {

   private JButton botaoCadastrar;
   private JTextField nome;
   private JTextField cpf;

   ClienteView() {
      nome = new JTextField(10);
      add(nome);
      cpf = new JTextField(10);
      add(cpf);
      botaoCadastrar = new JButton("Cadastrar");
      add(botaoCadastrar);
   }
   
   public void cadastrar(ActionListener event) {
      botaoCadastrar.addActionListener(event);
   }

   String getCPF() {
      return cpf.getText();
   }
			
    void setCPF(String text) {
      cpf.setText(text);
   }

   String getNome() {
      return nome.getText();
   }
			
    void setNome(String text) {
      nome.setText(text);
   }
}

… e no Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

   class CadastrarCliente implements ActionListener {
      cli.setCPF(cv.getCPF());
      cli.setNome(cv.getNome());
      JOptionPane...("Cliente cadastrado");
   }
}

E a classe main:

public class Cadastro extends JFrame{
   
   Cadastro() {
      Cliente cli = new Cliente(); // Este é o bean do Cliente!
      ClienteView cv = new ClienteView();
      ClienteControl con = new ClienteControl(cli, cv);
      add(cv);
      setVisible(true);
   }

    public static void main (String args[]) {
      Cadastro cadastrar = new Cadastro();
   }
}

Então a pergunta: Essa ligação entre as classes está correta? Existe alguma forma melhor de comunicar Visão c/ Controle e Controle c/ Modelo?

(Volto a deixar claro não quero que as pessoas que estão lendo pensem “ah esse cara quer é que eu faça o código para ele”… não é isso. Eu realmente quero aprender a fazer. Sou sozinho e mesmo com todas as dificuldades luto em tentar entender e aprender. Não quero fazer ninguém de empregado, por favor longe disso!)
Eu particularmente vejo a visão completamente acoplada ao controle (na minha simples e humilde opinião de iniciante).

Tenho mais perguntas mas para evitar um monte de pergunta ao mesmo tempo e confundir as pessoas vou aguardar a resposta por esta!
Um abração a todos que vem colaborando com este tópico. [color=red]Obrigado![/color] :wink:

pedromuyala

Entenderam o post anterior ou estou complicando as coisas? :frowning:
Estou sentindo que o pessoal está querendo me matar… :expressionless:

pedromuyala

Xííí esse silêncio está me assustando! :shock:

fantomas

Oi pedromuyala,

Então…o exemplo que vc descreveu anteriormente está bom na minha opinião, ao menos ficou bem mais organizado do que se fosse tudo misturado, colocado em uma única classe. É claro que este tipo de idéia funciona bem quando vc tem uma quantidade razoavel de campos em um formulário para serem preenchidos.

Você perguntou se dá para fazer melhor que isto. Na minha opinião eu acho que dá mas para isso teria que apelar para um framework que implementa esse padrão (mvc) no swing. Ex. http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-tikeswing.html, tem o genesis https://genesis.dev.java.net/nonav/3.2/maven-site/pt-BR/index.html que é brasileiro e muito bacana também muito embora o ponto central deste framework seja facilitar o desenvolvimento do software em várias partes ele pode ajudar bastante ao implementar o padrão mvc com suas anotações e injeção de dependencia.

Além disso, tem a idéia de que vc não constroi um software apenas com um padrão. Ou seja, dizer que um software web foi construido totalmente utilizando o padrão MVC não transmite um verdade completa na minha opinião porque ao desenvolver vc acaba tendo que aplicar vários padrões. Quanto mais radical for o contexto da aplicação, mais problemas (desafios) aparecem e logo vários outros padrões acabam tendo que ser aplicados.

Implementar totalmente um padrão muitas vezes pode não ser uma boa idéia, tem que ter bom senso e saber aplicar o necessario (estou tentando aprender isso rsrsr) parece que existe o momento certo, a maneira certa e a intensidade correta de se aplicar as coisas; portando muita calma nessa hora.

Este livro http://www.livrariacultura.com.br/scripts/cultura/resenha/resenha.asp?nitem=766140&sid=189859771171634497628532&k5=2C6DF477&uid= (tem em português também) é de um cara que acreditou por um bom tempo que o bom éra aplicar padrões para tudo da “melhor” forma possível e depois mudou de opinião. Neste livro vc verá um “Hello World” que deve ter umas 15 ou 20 linhas, cheio de patterns. O autor chama nossa atenção para o fato de que talvez isso não seja o que queremos e nem o que precisamos. Vale a pena dar uma olhada neste livro, fica aí então a dica.

flws

pedromuyala

Olá fantomas, obrigado pela atenção dada aqui ao tópico!

Com certeza muitos padrões provavelmente vão se encaixar no sistema. Gostei muito do artigo do JavaWorld sobre “High-Level MVC”!
O livro a hora que tiver a oportunidade de poder comprar um com certeza vou ler sim!
Como sou iniciante meu entendimento é um pouco mais lento quando leio os artigos mas consigo entender boa parte! :smiley:

Que bom que meus primeiros passinhos de aplicação do MVC estão, na sa opinião, indo bem! Para mim já é um enorme passo!
Então deixa perguntar: Veja o controle (ClienteControl). Após passar os dados da visão para o modelo ele emite um JOptionPane. Gostaria que a mensagem seja mostrada em um JLabel da visão. A visão tem um método “void setStatus(String status);”

Então o novo controle seria:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

   class CadastrarCliente implements ActionListener {
      cli.setCPF(cv.getCPF());
      cli.setNome(cv.getNome());
      cv.setStatus("Cliente cadastrado com sucesso"); // A ÚNICA LINHA QUE MUDOU DO CONTROLE ANTERIOR!
   }
}

Então vem a pergunta: Repare que o controle recebe dados da visão e envia dados para ela também. Não estou acoplando demais visão com controle ou é natural mesmo essa amarração? E só para completar, me deixou curioso: Porque para poucos campos está boa a comunicação? E se fossem uns 50 campos?

Um abração fantomas, obrigadão mesmo cara, está me ajudando muito!

fantomas

Sim! Neste seu caso o forte acoplamento existe, porque na verdade o que vc fêz foi uma separação de código, uma parte vc chamou de model, outra de view e outra de controller; isto é uma implementação completa do padrão MVC? Eu diria que não por causa de coisas como esta que vc falou, o acoplamento. Mas por que ficou interessante? Porque você deixou o código mais organizado, mais fácil de executar manutenções e introduziu uma estratégia de construir seus códigos o que deixa bem mais fácil de entender o sistema.

No exemplo que vc passou (o último) vc poderia utilizar exceptions para deixar a mensagem dentro da view. Por exemplo, de dentro da view ao clicar no botão confirmar vc executa o código que faz atualização no “controller” e este código por sua vez retorna uma resposta positiva ou negativa atravez de uma exception. Assim vc consegue deixar detalhes que são relacionados a “view”, dentro da view.

Talvez eu tenha cometido um erro ao me expressar, eu quiz dizer que este esquema é bom para vários campos, para poucos talvez não compense muito. Imagine uma janela com 2 campos com nada de muito especial, vc iria criar 3 classes para isto. Será que compensa? Talvez não.

Voltando ao papo do acoplamento, os frameworks para MVC atuam justamente nestas àreas, baixo acoplamento e automatização dos eventos.

flws

pedromuyala

Oi fantomas! Nossa cara não sabe como estou feliz de ouvir isso de você! :smiley: :smiley: :smiley: Muito bom!

Poxa que legal a ideia cara! Eu vou estudar direitinho o exception para não postar qualquer coisa aqui de qualquer jeito e assim que conseguir implementá-lo eu volto e mostro como ficou, ok? Não vou sumir e deixar o tópico inacabado.
Também entendi a respeito dos campos… com certeza dou razão no caso de poucos campos é exagero mesmo dividir tanto. Mas para exemplo acho que ficou legal (acredito que você também ache), ainda mais que é um exemplo de cadastro. Mas foi bom notificar isso, até mesmo para os demais usuários iniciantes (como eu) do GUJ ficarem atentos!

Poxa não tenho nem palavras para agradecer pela atenção que está disponibilizando do seu tempo em ajudar. Muito legal mesmo! :smiley:
Sucesso rapaz, tú merece! [color=red]Obrigadão![/color] Até mais. :wink:

pedromuyala

Oi fantomas! Como prometido, voltei! :smiley:

pedromuyala:
fantomas:

No exemplo que vc passou (o último) vc poderia utilizar exceptions para deixar a mensagem dentro da view. Por exemplo, de dentro da view ao clicar no botão confirmar vc executa o código que faz atualização no “controller” e este código por sua vez retorna uma resposta positiva ou negativa atravez de uma exception. Assim vc consegue deixar detalhes que são relacionados a “view”, dentro da view.

Poxa que legal a ideia cara! Eu vou estudar direitinho o exception para não postar qualquer coisa aqui de qualquer jeito e assim que conseguir implementá-lo eu volto e mostro como ficou, ok? Não vou sumir e deixar o tópico inacabado.

Então passei esses últimos quatro dias tentando implementar Exception no código mas infelizmente não consegui. :oops:
Não sei se estou fazendo certo (alias acho que estou fazendo uma bela asneira), até porque nunca trabalhei com exception. Mas não consigo implementar no código do controle, como havia escrito na citação… dá erro na compilação :frowning:

Veja só as mudanças…

na Visão:

class ClienteView extends JPanel {

   private JButton botaoCadastrar;
   private JTextField nome;
   private JTextField cpf;
   private JLabel lblcad; // JLABEL PARA NOTIFICAR ERRO NO CADASTRO.

   ClienteView() {
      nome = new JTextField(10);
      add(nome);
      cpf = new JTextField(10);
      add(cpf);
      botaoCadastrar = new JButton("Cadastrar");
      add(botaoCadastrar);
      lblcad = new JLabel(); // CRIADO JLABEL PARA NOTIFICAR ERRO!
      add(lblcad); // ADICIONADO AO PAINEL.
   }
   
   public void cadastrar(ActionListener event) { // ALTERAÇÃO DO MÉTODO PARA RECEBER EXCEÇÃO!
      try {
         botaoCadastrar.addActionListener(event);
      }
      catch (Exception e) {
         lblcad.setText("Cliente cadastrado com sucesso!");
   }

   String getCPF() {
      return cpf.getText();
   }
			
    void setCPF(String text) {
      cpf.setText(text);
   }

   String getNome() {
      return nome.getText();
   }
			
    void setNome(String text) {
      nome.setText(text);
   }
}

e no Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

   class CadastrarCliente implements ActionListener { // MÉTODO ALTERADO PARA CRIAR EXCEÇÃO!
      public void actionPerformed(ActionEvent event) throws Exception { // Linha do problema!
         try {
            cli.setCPF(cv.getCPF());
            cli.setNome(cv.getNome());
            throw new Exception();
         }
         catch(Exception e) {
            throw e;
         }
      }
   }
}

No Main nada no código foi alterado mantendo igual!

Mas o problema que ocorre no compilador é o seguinte: ClienteControl.java:13: actionPerformed(java.awt.event.ActionEvent) in ClienteControl.CadastrarCliente cannot implement actionPerformed(java.awt.event.ActionEvent) in java.awt.event.ActionListener; overridden method does not throw java.lang.Exception

Estou fazendo besteira ou será que existe outra forma de fazer a exception para que possa funcionar corretamente?
Tentei várias maneiras diferentes que fui olhando na net mas não estou conseguindo enxergar o erro (como disse, nunca trabalhei com exceptions!).
[color=blue]Obrigado fantomas e todos que estão ajudando![/color] :smiley:

pedromuyala

Estou no aguardo por novas respostas! :smiley:

pedromuyala

Nada mesmo pessoal? Está muito ruim assim? :shock: :oops:

fantomas

Vc poderia fazer assim:

class ClienteView extends JPanel {

   private JButton botaoCadastrar;
   private JTextField nome;
   private JTextField cpf;
   private JLabel lblcad; // JLABEL PARA NOTIFICAR ERRO NO CADASTRO.

   ClienteView() {
      nome = new JTextField(10);
      add(nome);
      cpf = new JTextField(10);
      add(cpf);
      botaoCadastrar = new JButton("Cadastrar");
      add(botaoCadastrar);
      lblcad = new JLabel(); // CRIADO JLABEL PARA NOTIFICAR ERRO!
      add(lblcad); // ADICIONADO AO PAINEL.
   }
   
   public void cadastrar(ActionListener event) { // Alterei aqui!
       botaoCadastrar.addActionListener(event);
   }

   String getCPF() {
      return cpf.getText();
   }
			
    void setCPF(String text) {
      cpf.setText(text);
   }

   String getNome() {
      return nome.getText();
   }
			
    void setNome(String text) {
      nome.setText(text);
   }

   void displayMsgSucesso() { // Alterei aqui!
         lblcad.setText("Cliente cadastrado com sucesso!");
   }

   void displayMsgErro() { // Alterei aqui!
         lblcad.setText("Erro ao cadastrar o cliente!");
   }
}
public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

  class CadastrarCliente implements ActionListener { 
      public void actionPerformed(ActionEvent event) { // Alterei aqui, este método não espera uma exception.
         try {
            cli.setCPF(cv.getCPF());
            cli.setNome(cv.getNome());

            cv.displayMsgSucesso(); // Alterei aqui

         } catch(Exception e) {

	    cv.displayMsgErro();  // Alterei aqui

            e.printStackTrace();
         }
      }
   }
}

flws

pedromuyala

Olá fantomas, boa noite! Desculpa não responder durante a tarde. :smiley:
Muito legal a idéia de deixar a visão já com os métodos de sucesso/insucesso que são acionados pelo controle através de Exception’s.

Sim! Neste seu caso o forte acoplamento existe, porque na verdade o que vc fêz foi uma separação de código, uma parte vc chamou de model, outra de view e outra de controller; isto é uma implementação completa do padrão MVC? Eu diria que não por causa de coisas como esta que vc falou, o acoplamento. Mas por que ficou interessante? Porque você deixou o código mais organizado, mais fácil de executar manutenções e introduziu uma estratégia de construir seus códigos o que deixa bem mais fácil de entender o sistema.

Uma simples pergunta: Como dito, frameworks MVC ajudam e muito a minimizar o forte acoplamento. Isso significa que esse último código postado (o que faz uso correto do Exception) ainda pode ser “melhor desacoplado” ou ele já está, no mínimo, satisfatório. Se existe ainda formas de desacoplar (ou seja, torná-lo um MVC real), pode me dar uma dica para que estude o caso :?:

Como havia escrito no primeiro post com código-exemplo, ainda tenho algumas dúvidas mas para não “tumultuar” o tópico com perguntas, assim que se esclarece uma posto a outra. E a pergunta de hoje já é uma dúvida que tenho desde que começei a estudar MVC, que é sobre a validação de dados!
Tentei hoje implementar o que eu consegui entender sobre “validação no modelo do MVC”. Para isso, faço validação do CPF informado. Veja nos códigos abaixo:
[color=orange]* Limpei os comentários antigos, para ficar só os novos! :wink:[/color]
Visão

class ClienteView extends JPanel {

   private JButton botaoCadastrar;
   private JTextField nome;
   private JTextField cpf;
   private JLabel lblcad;

   ClienteView() {
      nome = new JTextField(10);
      add(nome);
      cpf = new JTextField(10);
      add(cpf);
      botaoCadastrar = new JButton("Cadastrar");
      add(botaoCadastrar);
      lblcad = new JLabel();
      add(lblcad);
   }
   
   public void cadastrar(ActionListener event) {
       botaoCadastrar.addActionListener(event);
   }

   String getCPF() {
      return cpf.getText();
   }
			
    void setCPF(String text) {
      cpf.setText(text);
   }

   String getNome() {
      return nome.getText();
   }
			
    void setNome(String text) {
      nome.setText(text);
   }

   void displayMsgSucesso() {
         lblcad.setText("Cliente cadastrado com sucesso!");
   }

   void displayMsgErro() {
         lblcad.setText("Erro ao cadastrar o cliente!");
   }

   /* Método para exibição do resultado da validação! */
   void displayCPFErro() {
         lblcad.setText("Erro no CPF do cliente!");
   }
   /* Fim da exibição */

}

Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;

    ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }

  class CadastrarCliente implements ActionListener { 
      public void actionPerformed(ActionEvent event) {
         try {
            cli.setCPF(cv.getCPF());
            
            /* Código de validação do CPF no CONTROLE! */
            if (!Util.validaCPF(cv.getCPF())) { // Util é uma class abstrata e valida o CPF ("true" se validar ou "false" se invalidar).
               cv.displayCPFErro();
               cli.setCPF(null);
            }
            /* Fim da validação */
            else {
               cli.setNome(cv.getNome());
               cv.displayMsgSucesso();
            }
         } 
         catch(Exception e) {
            cv.displayMsgErro();
            e.printStackTrace();
         }
      }
   }
}

Minha pergunta então é: Está visivelmente correto a forma como ficou implementada a validação do CPF? Sempre vou ter que criar métodos com mensagens já prontas na visão para cada situação?
E se eu tiver mais campos para validar, como RG, CEP? Não existe uma forma para que no momento da validação caso ela retorne inválida (false) o try seja interrompido de forma que não chame o método displayMsgSucesso()? Acredito eu que seja gerando uma exceção… mas onde? Na Util? Ou no próprio controle?

Só uma obs: Entende porque perguntei logo no começo sobre o acoplamento? Eu vejo que cada vez mais que o sisteminha vai aumentando o controle vai se acoplando mais à visão. Ou será um engano meu. Que parece dar essa sensação de acoplamento, parece.

Fantomas, rapaz eu estou me sentindo já envergonhado :oops: com a atenção que tem dado ao tópico. Já já você vira as 1000 mensagens no GUJ, está de parabéns. Tenho certeza que muita gente você já ajudou e continua ajudando. Espero com toda certeza ainda um dia saber que se tornou, por exemplo, um moderador do fórum. :smiley:
Você merece e vai ser com enorme alegria que vou receber essa notícia o dia que se tornar um moderador. [color=red]Obrigado fantomas![/color] :wink:

pedromuyala

Ninguém arrisca uma opinião? :frowning: Nem do código nem do acoplamento… :cry:

Andre_Fonseca
pedromuyala:

Minha pergunta então é: Está visivelmente correto a forma como ficou implementada a validação do CPF? Sempre vou ter que criar métodos com mensagens já prontas na visão para cada situação?
E se eu tiver mais campos para validar, como RG, CEP? Não existe uma forma para que no momento da validação caso ela retorne inválida (false) o try seja interrompido de forma que não chame o método displayMsgSucesso()? Acredito eu que seja gerando uma exceção... mas onde? Na Util? Ou no próprio controle?

Oi Pedro,

Não li todos os seus posts, mas no caso da classe utilitaria eu faria o seguinte:

o método da classe Util que valida o CPF relança uma excesão e não gera log

a camada que chamou recupera a excessão e faz o log

algo parecido

class Util {

   Boolean validaCPF(String cpf) throws ValidationCPFException {

     try {
      //valida
     } catch(Exceptions.... e) {
       // aqui eu handle - trato - todas as excessões possiveis
       throw new ValidationCPFException(VALIDATION_CPF, e.getStackTrace());
     }
   }

class Utiliza {
 
  void metodoValida(String cpf) {

    try {
      Util.validaCPF(cpf);
    } catch (ValidationCPFException v) {
      log.error('erro validando"+e....); 
      // posso deixar correr o erro ou então tentar recuperar o que aconteceu..
    }
  }
}

resumindo, na minha opinião classes utilitárias não devem ser reponsáveis por saber o que fazer quando uma excessão ocorre, elas apenas retornam, pode até retornar um null ou 0, um valor default.. etc
na camada de business, ou outra que utilize a classe, eu só tenho uma excessão do tipo ValidaCPFException.. fica mais facil tratar assim..

pedromuyala

[color=blue]Olá André, boa noite![/color] Obrigado por iniciar sua participação aqui no tópico. :smiley:
Sim legal a idéia, entendi certinho. Para deixar ainda melhor implementei no controle sua ideia para dar continuidade ao código-exemplo. Veja como ficou:

Na Visão, nada mudou.

No Controle:

public class ClienteControl {
    
   private Cliente cli;
   private ClienteView cv;
   
   ClienteControl(Cliente cli, ClienteView cv) {
      this.cli = cli;
      this.cv = cv;
      cv.cadastrar(new CadastrarCliente());
   }
   
   class CadastrarCliente implements ActionListener { 
      public void actionPerformed(ActionEvent event) {
         try {

         /* NOVO Código de validação do CPF no CONTROLE! */
            Util.validaCPF(cv.getCPF());
            cli.setCPF(cv.getCPF());
         /* FIM do Código de validação do CPF! */

            cli.setNome(cv.getNome());
            cv.displayMsgSucesso();
         }
         catch (Exception e) {
            cv.displayMsgErro();
            e.printStackTrace();
         }

         /* NOVO Código de validação do CPF no CONTROLE! */
         catch (ValidationCPFException v) {
            cv.displayCPFErro();
         }
         /* FIM do Código de validação do CPF! */

      }
   }
}

No meu entender ficou legal! :smiley:

:?: Três perguntas ainda estão em aberto:

Em seguida vou postar a próxima pergunta! Enquanto isso se alguém quiser arriscar responder a citada… agradeço. [color=red]Obrigado![/color] :wink:

pedromuyala

Estou fazendo perguntas sem respostas né? :cry:
Acho que estou perguntando “besteiras”. :frowning:

fantomas
1) Sempre vou ter que criar métodos com mensagens já prontas na visão para cada situação? Não! Você pode mudar um pouco esta abortagem fazendo o seguinte:
public class View {
    private Controller controller = null;
    private JButton btnExecute = new JButton("Executar");
    ...
    public View(Controller controller) {
          this.controller = controller;
          this.initialize();
    }

    private void initialize() {
          btnExecute.addActionListener(new ActionListener() {
               View.this.executar();
          });
    }

    private void executar() {
        try {
             this.controller.executar();
              WindowUtil.showMessage("Sucesso ao executar!");
        } catch( Exception e ) {
             WindowUtil.showMessage("Erro ao executar!");
             e.printStackTrace();
        }
    }
}

2) Uma simples pergunta: Como dito, frameworks MVC ajudam e muito a minimizar o forte acoplamento. Isso significa que esse último código postado (o que faz uso correto do Exception) ainda pode ser "melhor desacoplado" ou ele já está, no mínimo, satisfatório. Se existe ainda formas de desacoplar (ou seja, torná-lo um MVC real), pode me dar uma dica para que estude o caso?

Tem esse framework aqui: [url]http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-tikeswing.html[/url].
Tem tambem o genesis (brasileiro): [url]https://genesis.dev.java.net/nonav/3.2/maven-site/pt-BR/index.html[/url], o objetivo principal deste não é implementar o padrão MVC, mas ajuda bastante quem está querendo fazer isto.

Não deixe de ler este conteúdo também: [url]http://java.sun.com/developer/technicalArticles/javase/mvc/[/url]

3) Só uma obs: Entende porque perguntei logo no começo sobre o acoplamento? Eu vejo que cada vez mais que o sisteminha vai aumentando e o controle vai se acoplando mais à visão. Ou será um engano meu? Que parece dar essa sensação de acoplamento, parece.

Reduzir acoplamento nem sempre é simples e pode causar esta impressão mesmo. Mas dá para vc testar o nível de acoplamento de uma forma até simples na minha opinião. Basta vc observar o seu código e fazer as seguintes perguntas para vc mesmo:

1) Eu consigo utilizar este controller em uma outra situação (em um sistema web por exemplo) sem modificar nada?
2) Eu consigo utilizar esta view com um controller que possua comportamentos diferentes?
3) Eu consigo utilizar este model em uma situação bem diferente desta?

Sim for sim para todas estas perguntas significa que vc está no caminho certo.

Lembrando que interfaces são o caminho para um bom desacoplamento, independente de qualquer situação ou padrão; portanto faça uma revisão.

flws

pedromuyala

Boa noite fantomas, obrigado mais uma vez em estar acompanhando o tópico. :smiley:
Legal a última idéia. Dessa forma percebo um desacoplamento geral do controle com a visão e vice-versa, até porque b[/b] o método executar() poderia ter parametros que levariam os dados da visão ao controle. Estou certo? E um detalhe que está fazendo uma enorme diferença é o uso de exceções. Nunca imaginei a importancia das exceções em códigos JAVA.

Vou aproveitar o embalo e colocar mais uma pergunta:b[/b] E se eu precisar informar o usuário na visão do tipo de exceção que ocorreu ao executar o controle nessa nova abordagem apresentada?
Ex: Data inválida -> “Erro: Informe corretamente a data de nascimento!” ou Ex2: “Erro: CPF inválido”. Como o usuário vai saber que só “tal” campo está com problema?
Acredito eu que será com o uso e tratamento de Exceptions, ou não? :shock:

Vou aguardar pela resposta para implementar essa nova abordagem (desacoplamento) no código-exemplo que vinha sendo mostrado. Vou aproveitar também e incluir novos atributos para ficar melhor perceptível a solução. :wink:

[color=green][size=16]Muito obrigado galera do GUJ![/size][/color] :thumbup: Aguardo pela resposta, opinião, sugestão, crítica…
fantomas obrigado cara por estar praticamente diariamente respondendo neste tópico e como você diz: flws

fantomas

Certo.

pedromuyala:

Vou aproveitar o embalo e colocar mais uma pergunta:(2) E se eu precisar informar o usuário na visão do tipo de exceção que ocorreu ao executar o controle nessa nova abordagem apresentada?
Ex: Data inválida -> “Erro: Informe corretamente a data de nascimento!” ou Ex2: “Erro: CPF inválido”. Como o usuário vai saber que só “tal” campo está com problema?
Acredito eu que será com o uso e tratamento de Exceptions, ou não?

Em alguns casos vc consegue retornar resultados sem utilizar exceptions retornando apenas um código ou um valor true ou false; algumas abordagens sugerem vc criar exceptions customizadas quando vc está em um contexto mais complexo como os encontrados em sistemas web, que é bacana também. Quando vc executa uma validação em um controller sem envolver mais nada é mais tranquilo, mas quando a validação ocorre em um servidor muitas podem acontecer, a validação pode retornar positiva, negativa ou pode ocorrer um problema de acesso a base de dados ou até na rede; nestes casos a estratégia de utilizar exceptions pode começar a ficar interessante.

Aqui no forum existem algumas discuções sobre este tema, vê se consegue encontrar.

Lidar com exceptions requer boas práticas, portanto é bom fazer uma pesquisa sobre o assunto; tem bastante na net, eis aqui um link bacaninha: http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html não deixe de lêr e entender.

[]

pedromuyala

Olá fantomas, obrigado por continuar acompanhando o tópico! :wink:
Maravilha! Vou entender direitinho as exceções antes de fazer as modificações no código.
Uma dica também para quem está atrás de aprender exceções é a revista MundoJava nº36.
Assim que estiver ciente das exceções, volto a postar o código para mostrar como ficou já implementando a nova abordagem sugerida (desacoplamento)!
[color=red]OBRIGADO A TODOS![/color] Não deixem de opinar, criticar…

pedromuyala

Olá pessoal do GUJ! :smiley:
Como prometido, passei esses últimos três dias estudando Exception para tentar chegar a melhor solução cabível no código-exemplo que estamos criando.
Tentei ao máximo possível seguir os conselhos do fantomas e André Fonseca para implementar as Exception. Importante também o artigo deste mês da revista MundoJava no aprendizado. :thumbup:

Vamos ao código-exemplo, que sofreu muita mudança dos últimos exemplos postados, aplicando a nova abordagem (desacoplamento entre visão <-> controle) e o uso de Exception’s.

CLASSES PARA TRATAR EXCEÇÃO:

Superclasse:

public class CadastraException extends Exception {
   
   private String msg;
   
   public CadastraException(String msg) {
      super(msg);
      this.msg = msg;
   }

   public String getMessage() {
      return msg;
   }
}

Subclasse:

public class CPFException extends CadastraException {
   
   public CPFException() {
      super("CPF Inválido");
   }
}

CLASSES DO MVC:

No BEAN CLIENTE (modelo), nada mudou.

Controle:

public class ClienteControl {   
       
   private Cliente cli = null;   
   
   ClienteControl(Cliente cli) {   
      this.cli = cli;   
   }
   
   public void executar(String nome, String cpf) throws Exception {
      try {
         if(!Util.validaCPF(cpf))
            throw new CPFException();
         cli.setCPF(cpf);
         cli.setNome(nome);
      }
         catch(Exception e) {
            throw e;
         }
   }    
}

*OBS: Util.validaCPF(cpf) retorna valor booleano!

Visão:

public class ClienteView extends JPanel {
	 
   private ClienteControl controller = null;
   private JButton btnCadastrar;
   private JTextField nome;   
   private JTextField cpf;   
   private JLabel lblCad; 
 
   public ClienteView(ClienteControl controller) {
      this.controller = controller;
      this.initialize();
   }
   
   private void initialize() {
      nome = new JTextField(10);   
      add(nome);   
      cpf = new JTextField(10);   
      add(cpf);   
      btnCadastrar = new JButton("Cadastrar");   
      btnCadastrar.addActionListener(
             new ActionListener() {
                public void actionPerformed(ActionEvent e) {		     
                  ClienteView.this.executar();
               }
            });
      add(btnCadastrar);   
      lblCad = new JLabel();   
      add(lblCad);   
   }
   
   private void executar() {
      try {
         this.controller.executar(nome.getText(), cpf.getText());
         lblCad.setText("Cadastro realizado com sucesso");
      }
          catch (CadastraException e) {
            lblCad.setText(e.getMessage());
         }
          catch (Exception e) {
            lblCad.setText("Problemas ao cadastrar. Tente novamente!");
         }
   }  
}

main:

public class Cadastro extends JFrame{
   
   Cadastro() {
      Cliente cli = new Cliente(); 
      ClienteControl con = new ClienteControl(cli);
      ClienteView cv = new ClienteView(con);
      add(cv);
      setVisible(true);
   }

    public static void main (String args[]) {
      Cadastro cadastrar = new Cadastro();
   }
}

Reparem que a visão finalmente está (na minha humilde opinião de aprendiz) muito bem desacoplada do controle. O código do controle está mais legível também. :smiley:

Bem, a minha primeira dúvida com esse novo código é a seguinte: b A hierarquia das classes que compõe as Exception está correta?[/b] (Veja a imagem em anexo!)

Repare que criei uma superclasse CadastraException que é herdada pelas subclasses necessárias para avisar sobre exceções de validações que possam ocorrer durante o cadastro do cliente. Também não descartei a opção de tratar demais exceções que possam ocorrer, como conexão com BD, rede, etc… Repare na visão que se a exceção for de validação ela diz onde ocorreu o erro (qual dado de qual campo gerou uma Exception) e se a exceção for de outro tipo (não conhecido até este momento) só informa com uma mensagem que “ocorreu um problema se possível tente novamente”! (Veja o método [color=blue]executar() na linha 31[/color] do ClienteView). Na imagem exemplo coloquei até uma classe CEPException e OutraException para mostrar a hierarquia. Está correto o procedimento?
O que mais preocupa-me nessa situação é que a mensagem da exceção está sendo tratada fora da visão, o que vai contra o que o fantomas me ensinou em uma postagem anterior quando explicou “que é para deixar detalhes da View dentro da View”. :shock:

A minha segunda dúvida é a seguinte: b A Util.validaCPF(cpf) retorna um valor booleano para o controle que caso seja “false” lança uma CPFException (cria e lança no controle). Eu poderia fazer a Util.validaCPF(cpf) criar e lançar a CPFException() ao invés de retornar um boolean?[/b] Ou seja, aquilo que o André Fonseca propos em uma postagem anterior. (Veja linhas [color=blue]11 e 12[/color] do ClienteControl!)

[color=red]Pessoal[/color], VALE PARA TODOS, não deixem de opinar. Sua opinião/sugestão/crítica é muito importante para manter o tópico vivo e contribuir com todos os companheiros do GUJ! :wink:
Se você acredita que algo deve mudar no código-exemplo também não deixe de postar. :idea: E não deixe de selecionar a opção para acompanhar o tópico. Talvés nesse momento não possa ajudar, mas pode surgir uma dúvida que você poderá contribuir!

[size=16][color=green]OBRIGADO GUJ[/color] por proporcionar essa comunidade linda![/size] :arrow: O Brasil inteiro ganha com isso!

Fico no aguardo por novas respostas. Assim que estiver com essas questões solucionadas lançarei nova pergunta para não embolar muitas perguntas com muitas respostas e acabar ficando uma coisa sem começo nem fim, sem lógica entre pergunta e resposta!
Um abraço especial aí para o fantomas, futuro moderador do GUJ, :lol: ele merece!

B

Eu preferiria estender de RuntimeException, para evitar a lixarada de throws que as checked exceptions precisam.

Outra coisa é que você não está seguindo o princiípio de atirar a exception mais específica, de fora do teu método vai parecer que é tudo Exception. Remova os “throws Exception”

Sobre a segunda pergunta, se quiser que o teu método de checagem também atire uma exception, crie um método tipo validaCPFComException, e deixe o validaCPF em paz. Pelo menos vai ter as duas opções, não se obrigando a fazer ou de um jeito ou de outro.

pedromuyala

Olá Bruno Laturner, obrigado por iniciar sua participação no tópico! :wink:

Bruno Laturner:
Eu preferiria estender de RuntimeException, para evitar a lixarada de throws que as checked exceptions precisam.

Outra coisa é que você não está seguindo o princiípio de atirar a exception mais específica, de fora do teu método vai parecer que é tudo Exception. Remova os “throws Exception”

Mas e no caso de ocorrer uma exceção, por exemplo, ao conectar-se ao BD, na rede ou uma outra que não conheço?
Se eu remover “throws Exception” do controle (pelo que estou entendendo) teria que substituir por “throws CadastraException”.
Aí como ficariam as exceções que não estendem CadastraException?

Opinem, não deixem de opinar! Fico no aguardo pela resposta! :smiley:
[color=red]OBRIGADO![/color]

B

Viraria um throws CadastraException, SQLException, IOException, ParseException, ClassNotFoundException, IllegalAccessException, e outras exceptions…

Vai atirando até vc perceber que a tua classe virou um Mega Zord, e que você está dando responsabilidades demais para ela.

Há um tempo atrás teve uma discussão no arquitetura de sistemas que também conversamos sobre isso. Uma maneira de evitar é saber que as camadas que chamaram o teu código não querem saber o que você está usando, nem as exceções que essas APIs atiram. Converta as exceções de camadas mais abaixo para exceções da sua camada, isso quando forem exceções que você não pode tratar e continuar com a tua vida.

Dito isso, continue a atirar um CPFException, dê um throws CadastrarException, e quando for mudar pro código do cliente, transforme para algum MinhaAplicaçãoException.

Com isso dito, nada te impede de repassar um SQLException ou qualquer outra lá para cima, se essa for a maneira que você trata a tua aplicação. Só há diversas maneiras de fazer a mesma coisa, nenhuma é absoluta.

pedromuyala

Olá Bruno, boa noite! Obrigado por continuar acompanhando o tópico! :smiley:

Viraria um throws CadastraException, SQLException, IOException, ParseException, ClassNotFoundException, IllegalAccessException, e outras exceptions…

Vai atirando até vc perceber que a tua classe virou um Mega Zord, e que você está dando responsabilidades demais para ela.

Há um tempo atrás teve uma discussão no arquitetura de sistemas que também conversamos sobre isso. Uma maneira de evitar é saber que as camadas que chamaram o teu código não querem saber o que você está usando, nem as exceções que essas APIs atiram. Converta as exceções de camadas mais abaixo para exceções da sua camada, isso quando forem exceções que você não pode tratar e continuar com a tua vida.

Dito isso, continue a atirar um CPFException, dê um throws CadastrarException, e quando for mudar pro código do cliente, transforme para algum MinhaAplicaçãoException.

Com isso dito, nada te impede de repassar um SQLException ou qualquer outra lá para cima, se essa for a maneira que você trata a tua aplicação. Só há diversas maneiras de fazer a mesma coisa, nenhuma é absoluta.

Me desculpa mas vamos ver se entendi: No ClienteControl você está me sugerindo para continuar atirando CPFException e fazer o throws de CadastrarCliente? Isso para não quebrar o princípio de atirar a Exception mais específica, correto? Veja o código:

Controle

public class ClienteControl {   
       
   private Cliente cli = null;   
   
   ClienteControl(Cliente cli) {   
      this.cli = cli;   
   }
   
   public void executar(String nome, String cpf) throws CadastraException { // AQUI FOI ALTERADO era: throws Exception
      try {
         if(!Util.validaCPF(cpf))
            throw new CPFException();
         cli.setCPF(cpf);
         cli.setNome(nome);
      }
         catch(CadastraException e) { // AQUI FOI ALTERADO era: catch(Exception e)
            throw e;
         }
   }    
}

Então, a dúvida: Mas e se no try{} do código acima eu tiver uma chamada CliDAO.cadastrar() e ele me retornar uma exceção? Como vou tratá-la?
No CPF eu recebo um boolean e a partir dele gero a exceção correta. Mas e se o restorno for uma exceção, como vou fazer?

Desculpa a minha ignorância Bruno é que realmente sou um aprendiz em JAVA meu conhecimento é mínimo! Tento fazer o possivel para entender lendo tutoriais, artigos mas realmente muitas vezes empaco! :frowning: Peço desculpa antecipadamente e se puder continuar ajudando, fico muito feliz! :smiley:

E A TODOS QUE QUISEREM PARTICIPAR, participem! :wink: [color=blue]Obrigado.[/color]

B

Eu me considero um aprendiz também. Acho que vou chegar até o final da vida ainda achando que não sei o suficiente. :slight_smile:

Não. Considere como seu código fosse um framework, no sentido que as pessoas utilizam a API do teu aplicativo para poder rodar as coisas delas. O que estou falando é que haverá pelo menos uma exceção genérica da tua aplicação que encapsulará a maioria das outras. Enquanto você estiver dentro da tua própria aplicação, você pode usar as exceções que quiser, em qualquer quantidade, porém esta exceção genérica é mais utilizada para marcar “fronteira entre nações”.

Outro sentido que dou para utilizar “API do teu aplicativo”, é o exemplo da fronteira entre a interface e o núcleo da aplicação, seja a interface web, desktop, webservice, ou outro cliente, o núcleo é sempre o mesmo. Em termos MVC, é a fronteira entre o View+Controller com a do Model.

Note que uma coisa que eu não estou falando é que o cliente deverá se contentar com a exceção genérico, e ficar sem opções. Dá muito bem para descobrir qual foi a exceção específica lançada, desde que não a escondemos. Fala isso por que ainda dá para o teu controller decidir o que ele quer fazer dependendo da exceção lançada.

pedromuyala:

Controle

public class ClienteControl {   
       
   private Cliente cli = null;   
   
   ClienteControl(Cliente cli) {   
      this.cli = cli;   
   }
   
   public void executar(String nome, String cpf) throws CadastraException { // AQUI FOI ALTERADO era: throws Exception
      try {
         if(!Util.validaCPF(cpf))
            throw new CPFException();
         cli.setCPF(cpf);
         cli.setNome(nome);
      }
         catch(CadastraException e) { // AQUI FOI ALTERADO era: catch(Exception e)
            throw e;
         }
   }    
}

Então, a dúvida: Mas e se no try{} do código acima eu tiver uma chamada CliDAO.cadastrar() e ele me retornar uma exceção? Como vou tratá-la?
No CPF eu recebo um boolean e a partir dele gero a exceção correta. Mas e se o restorno for uma exceção, como vou fazer?

1º, remova o try/catch, não servem de nada se você não está tratando alguma coisa.
2º, este código faz parte do model, não do controller. Digo isso por que você está implementando de regras de negócio.

Sobre como tratar, pode fazer do jeito que quiser 8) A pergunta é, o que você quer fazer? Encapsular as exceções em outra? Deixar ela passar? Tratar e tentar se recuperar do que aconteceu? Há algo que você não quer fazer? Não há uma resposta certa, só há decisões, ou pelo menos um objetivo final.

B

Sobre o código, ele ficaria melhor se você der mais responsabilidade à eles:

public class Cliente
{
  Documento doc;
  String nome;

  ClienteDao dao = DaoFactory.get(Cliente.class);

  public Cliente(Documento doc, String nome)
  {
     this.doc = doc;
     
     if (nome = null)
       throw new IllegalArgumentException("O nome não pode ser nulo.");

     nome = nome.trim();
     if (nome.isEmpty())
       throw new IllegalArgumentException("O nome não pode estar em branco.");

     this.nome = nome;
  }

  public void cadastrar() throws CadastroDeClienteException
  {
     try
     {
       if (dao.jaEstaCadastrado(this))
         throw new ClienteJaCadastradoException();

       dao.cadastrar(this);
     }
     catch (PersistenciaException ex)
     {
       throw new CadastroDeClienteException(ex);
     }
  }
}

public abstract class Documento {}

public class CPF extends Documento {
  String numero;
  public CPF(String numero)
  {
    if(!Util.validaCPF(numero))  
      throw new IllegalArgumentException("CPF inválido.");
    this.numero = numero;
  }
}
pedromuyala

[color=blue]Fala Brunão[/color], boa noite! Desculpa a demora para postar a resposta é que precisei ler com calma para entender! :smiley:
Obrigado por continuar atento ao tópico, sua ajuda está sendo muito importante. Agradeço muito! :wink:

Entendi a explicação e também o código. Legal ter criado a classe abstrata Documento, pois assim a classe CPF pode estende-la e futuramente uma classe RG, CNPJ ou qualquer outra relasionada a um documento também poderá. Também gostei muito da separação de responsabilidade nas exceções, ou seja, onde cada uma deve estar!

Como postou anteriormente, arrumei o ClienteControl (controle). Veja como ficou:

Controle

public class ClienteControl {     
         
   private Cliente cli = null;     
     
   ClienteControl(Cliente cli) {     
      this.cli = cli;     
   }   
     
   public void executar(String nome, String cpf) throws CadastroDeClienteException { 
         CPF doc = new CPF(cpf);
         this.cli = new Cliente(doc, nome);
         this.cli.cadastrar();
   }       
}

Modelo: Está a classe Cliente implementada pelo Bruno na sua postagem anterior! NADA ALTERADO!

Visão

import javax.swing.*;
   import java.awt.event.*;

    public class ClienteView extends JPanel {
    
      private ClienteControl controller = null;
      private JButton btnExecute;
      private JTextField nome;   
      private JTextField cpf;   
      private JLabel lblCad; 
   
       public ClienteView(ClienteControl controller) {
         this.controller = controller;
         this.initialize();
      }
   
       private void initialize() {
         nome = new JTextField(10);   
         add(nome);   
         cpf = new JTextField(10);   
         add(cpf);   
         btnExecute = new JButton("Cadastrar");   
         btnExecute.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                     View.this.executar();
                  }
               });
         add(btnExecute);   
         lblCad = new JLabel();   
         add(lblCad);   
      }
   
       private void executar() {
         try {
            this.controller.executar(nome.getText(), cpf.getText());
            lblCad.setText("Cadastro realizado com sucesso");
         }
             catch (CadastroDeClienteException e) {
               lblCad.setText(e.getMessage());
            } 
      }  
   }

Pronto, então a pergunta de hoje: (1) Como a mensagem da exceção que ocorrer no modelo deverá ser mostrada ao usuário na visão?
Ou seja, como o JLabel lblCad de ClienteView vai receber a mensagem [color=blue]“O nome não pode ser nulo.”[/color] caso ela seja lançada no Cliente?
Ou como o mesmo JLabel vai receber a mensagem [color=blue]“CPF inválido.”[/color] caso ela seja lançada na classe CPF?
Lembrando que ambas são [color=red]IllegalArgumentException[/color] e quando ocorrem são mostradas no console!

Outra pergunta: (2) A classe CadastroDeClienteException estende RuntimeException, Exception ou não estende nada? E ClienteJaCadastradoException, estende alguém?

Fico no aguardo pelas respostas, volto a agradecer a todos que estão colaborando. É incrível a magia que o grupo de usuários do GUJ realiza. Só participando mesmo para descobrir. Vejo em todos os posts o esforço do pessoal para tentar chegar a melhor forma de responder as perguntas. Estão todos de parabéns. E não deixem de opinar, mesmo sendo a primeira vez que está lendo o tópico (no primeiro post deixo algumas orientações, se necessário para não se perder no tópico). [color=red][size=18]OBRIGADO GALERA![/color][/size]

B

pedromuyala:

Pronto, então a pergunta de hoje: (1) Como a mensagem da exceção que ocorrer no modelo deverá ser mostrada ao usuário na visão?
Ou seja, como o JLabel lblCad de ClienteView vai receber a mensagem [color=blue]“O nome não pode ser nulo.”[/color] caso ela seja lançada no Cliente?
Ou como o mesmo JLabel vai receber a mensagem [color=blue]“CPF inválido.”[/color] caso ela seja lançada na classe CPF?
Lembrando que ambas são [color=red]IllegalArgumentException[/color] e quando ocorrem são mostradas no console!

Mude os tipos das exceções para alguma do domínio da tua aplicação, ou dê um catch nesse IllegalArgumentException, ou mesmo em Exception. Esses dois últimos não recomentdo.

ClienteJaCadastradoException é uma CadastroDeClienteException. Este, por sua vez, pode ser o que você quiser, desde ele seja algo que faça parte da hierarquia de Exception (Throwable para falar a verdade).

pedromuyala

[color=red]Boa noite Bruno,[/color] tudo beleza por aí? :smiley: MUITÍSSIMO OBRIGADO por continuar colaborando com o tópico!

Bruno Laturner:
pedromuyala:

Pronto, então a pergunta de hoje: (1) Como a mensagem da exceção que ocorrer no modelo deverá ser mostrada ao usuário na visão?
Ou seja, como o JLabel lblCad de ClienteView vai receber a mensagem [color=blue]“O nome não pode ser nulo.”[/color] caso ela seja lançada no Cliente?
Ou como o mesmo JLabel vai receber a mensagem [color=blue]“CPF inválido.”[/color] caso ela seja lançada na classe CPF?
Lembrando que ambas são [color=red]IllegalArgumentException[/color] e quando ocorrem são mostradas no console!

Mude os tipos das exceções para alguma do domínio da tua aplicação, ou dê um catch nesse IllegalArgumentException, ou mesmo em Exception. Esses dois últimos não recomentdo.

:arrow: Portanto, vamos ao código-exemplo, na maneira que entendi:
[color=red]OBS IMPORTANTE:[/color] Como ainda não quero entrar na persistencia dos dados, não estou aplicando até este momento nenhuma chamada as classes de persistencia no código-exemplo, limitando o entendimento somente entre a comunicação M-V-C com Exception’s, ok?

MODELO: abstract Documento

public abstract class Documento {}

MODELO: CPF

public class CPF extends Documento {   
      String numero;   
       public CPF(String numero)   
      {   
         if(!Util.validaCPF(numero))     
            throw new CPFException();   
         this.numero = numero;   
      }   
   }

MODELO: Cliente

public class Cliente {
   
      private String nome;
      private Documento cpf;
   
       public Cliente() {
      }
   	
       public Cliente(Documento cpf, String nome)   
      {   
         this.setCPF(cpf);       
         this.setNome(nome);   
      }   
   
       Documento getCPF() {
         return this.cpf;
      }
   			
       void setCPF(Documento cpf) {
         this.cpf = cpf;
      }
   
       String getNome() {
         return this.nome;
      }
   			
       void setNome(String nome) {
         if (nome == null)   
            throw new ClienteException("O nome não pode ser nulo.");   
         nome = nome.trim();
         if (nome.isEmpty())
            throw new ClienteException("O nome não pode estar em branco.");
         this.nome = nome;
      }
   }

CONTROLE:

public class ClienteControl {       
           
      private Cliente cli = null;       
       
       ClienteControl(Cliente cli) {       
         this.cli = cli;       
      }     
       
       public void cadastrar(String nome, String cpf) throws CadastrarClienteException {
         try {      
            CPF doc = new CPF(cpf);
            this.cli = new Cliente(doc, nome);
         }
             catch(CPFException e) {
               throw new CadastrarClienteException(e.getMessage());
            }
             catch(ClienteException e) {
               throw new CadastrarClienteException(e.getMessage());
            }				
      }         
   }

VISÃO:

public class View extends JPanel {
    
      private ClienteControl controller = null;
      private JButton btnExecute;
      private JTextField nome;   
      private JTextField cpf;   
      private JLabel lblCad; 
   
       public View(ClienteControl controller) {
         this.controller = controller;
         this.initialize();
      }
   
       private void initialize() {
         nome = new JTextField(10);   
         add(nome);   
         cpf = new JTextField(10);   
         add(cpf);   
         btnExecute = new JButton("Cadastrar");   
         btnExecute.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                     View.this.cadastrar();
                  }
               });
         add(btnExecute);   
         lblCad = new JLabel();   
         add(lblCad);   
      }
   
       private void cadastrar() {
         try {
            this.controller.cadastrar(nome.getText(), cpf.getText());
            lblCad.setText("Cadastro realizado com sucesso");
         }
             catch (CadastrarClienteException e) {
               lblCad.setText(e.getMessage());
            } 
      }  
   }

ClienteJaCadastradoException é uma CadastroDeClienteException. Este, por sua vez, pode ser o que você quiser, desde ele seja algo que faça parte da hierarquia de Exception (Throwable para falar a verdade).

Exceções: CPFException

public class CPFException extends RuntimeException{
       public CPFException() {
         super("CPF Inválido");
      }
   }

Exceções: ClienteException

public class ClienteException extends RuntimeException {
   
        public ClienteException(String msg) {
         super(msg);
      }
   }

Exceções: CadastrarClienteException

public class CadastrarClienteException extends RuntimeException {
   
       public CadastrarClienteException(String msg) {
         super(msg);
      }
   }

:arrow: OQ EU FIZ: Tentei seguir o conselho de usar RuntimeException no lugar de Exception e de separar “fronteiras entre nações” ([color=blue]Ver linhas vermelhas na imagem em anexo[/color])
Dessa forma, ClienteException trabalha para a classe Cliente e CPFException trabalha para a classe CPF. No controle, como é ele quem transfere os dados da visão para o modelo (cadastra os dados informados nos campos da visão para o BEAN Cliente no modelo) então é encapsulada as mensagens das exceções que aparecerem entre o try{}…catch(){} como CadastrarClienteException. A visão, por sua vez, faz a leitura final de CadastrarClienteException mostrando as mensagens ao usuário, caso elas ocorram.

Agora a pergunta é, com toda humildade do mundo: Estou causando confusão na cabeça dos programadores ou realmente dessa vez ficou certo? Estou fazendo má prática em algum lugar? :shock:

Volto a pedir a todos muita calma e paciência comigo. É uma coisa que estou fazendo todo esforço possível para conseguir entender e não sair por aí vida afora desenvolvendo aqueles famosos códigos que nem o cara que desenvolveu vai entender! :frowning: Como já havia dito em postagens anteriores eu quero mesmo aprender e não me aproveitar da boa vontade das pessoas que estão ajudando fazendo essas como “empregados”. Pode ter certeza que a sua ajuda aqui será importante não só para mim mas para muitas pessoas que sofrem em entender o padrão MVC. :wink:
[size=15]
Obrigado a todos que estão lendo ou tentando ajudar no tópico! Não deixem de opinar, criticar, sugerir… é muito importante sua participação!
Um abração especial aí para o pessoal do GUJ, para os usuários fantomas, Bruno Laturner, André e todos aqueles que postaram também no início do tópico!
[/size]

B

Antes de começar, uma opinião:

Eu acho um pouco de exagero fazer uma exceção para cada coisa, por mim só atirar um MinhaAplicacaoException bem genérica já resolveria a maioria dos problemas. Não acho que valha a pena criar várias exceções a menos que você vá fazer algo com elas. A especialização é boa quando você precisa tratar casos especiais de forma diferente, que fogem à regra de tratamento da exceção principal. Não é isso que temos ainda.
Com isto dito, vamos continuar com o que já foi feito.

Fazendo todas elas estender diretamente de RuntimeException faz com que você tenha que dar um catch RuntimeException para pegar todos de maneira uniforme. Isso não é bom.

MinhaAplicacaoException é a exceção do domínio da aplicação que marca a fronteira. Todo o resto das exceções estendem dela, e também implementam os mesmos construtores.
package minhaaplicacao.exception;

public class MinhaAplicacaoException extends RuntimeException
{
    public MinhaAplicacaoException() {
        super();
    }

    public MinhaAplicacaoException(String message) {
        super(message);
    }

    public MinhaAplicacaoException(Throwable cause) {
        super(cause);
    }

    public MinhaAplicacaoException(String message, Throwable cause) {
        super(message, cause);
    }
}
private void cadastrar() {
         try {
            this.controller.cadastrar(nome.getText(), cpf.getText());
            lblCad.setText("Cadastro realizado com sucesso");
         }
             catch (MinhaAplicacaoException e) {
               lblCad.setText(e.getMessage());
            } 
      }

Eu tinha mais umas coisas pra falar, mas o sono está atrapalhando a organizar as idéias hehe. ^_^ ;O

pedromuyala

Opa Bruno… magina cara não quero atrapalhar seu sono! :smiley:
Mas fiquei curioso com a frase final que avisou! Fico no aguardo, abração!

B

Acho que era só isso mesmo.

Quando for atirar uma nova exceção a partir de outra, use os construtores da classe que recebem um Throwable, ao invés de mandar só a String com uma mensagem. Daí dá para saber de onde veio a exceção.

Na maioria dos casos eu preferiria deixar a exceção se propagar até o final, sem encapsular uma dentro da outra. Não dou um catch quando não tenho nada para fazer com a exceção. Polui menos o código também.

pedromuyala

Fala Bruno, beleza, boa tarde! :smiley:
Acho que agora sim eu entendi a essência da Exception! Ou seja, CPFException, ClienteException, OutraExeption… estendem MinhaAplicacaoException e no controle, no método cadastrar(), eu deixo só o throws MinhaAplicacaoException para passar até a visão e aí sim finalmente uso o try{}… catch(){} para colocar a mensagem no JLabel. É isso? Agora acertei? :roll: Por favor Bruno, não deixe de confirmar se é isso mesmo para que eu possa implementar e mostrar o código aqui para todos. [color=red]Obrigadão Bruno, fico no aguardo[/color]!

B

É isso mesmo.

O próximo passo é tratar erros que você não esteja esperando.

Tente lançar de propósito RuntimeException que não seja um MinhaAplicaçãoException, lá de dentro do model, para ver o comportamento da aplicação quanto à essas exceções.

pedromuyala

Opa Bruno, é o Pedro. [color=olive]Fiz como mandou e realmente ficou 100% a implementação![/color] :wink:
Antes de postar o código, vou responder a pergunta que me fez:

A exceção apareceu no console e não na visão. Até entendi o porque pois essa throw new RuntimeException("…"); no modelo não estende a classe MinhaAplicacaoException.

Vixe, mas e agora… como vou tratar as exceções (erros) que não conheço?

Já sei que não é para ficar atirando qualquer coisa senão vou acabar criando um Mega Zord Exception no método do controle. :lol: Mas a princípio acredito que não vou poder ficar mostrando na visão qualquer tipo de exceção que vier das camadas de baixo nível até para que não apareçam mensagens que um simples usuário do sistema não vai entender. Ex: NullPointerException, RuntimeException ou qualquer outra que estende a classe Exception. Porém não posso simplemesmente ignorar o erro pois aí estaria cometendo uma “infração de sete pontos na carteira”, principalmente nas Exception’s checadas. Imaginem o problemão caso ignore uma SQLException na hora de cadastrar um cliente… Acredito eu que agora sim vai entrar uma espécie de encapsulamento ou voltei a falar abobrinhas? Desculpem se for o caso. :oops:

Mas estou ficando muito feliz! :smiley: :smiley: :smiley: Até porque é a primeira vez que estou entendendo como escrever códigos de forma legível ao mundo dos javeiros.
Realmente é muito legal a magia do Java quando bem escrito, bem estruturado!

[size=15]Fico no aguardo pela resposta. Volto a agradecer a todos que estão acompanhando o tópico, sejam os veteranos como os novos, e ao pessoal do GUJ que mantém essa comunidade maravilhosa! Volto a dizer, sei que estou sendo repetitivo, mas não deixe de opinar, sugerir mudanças, criticar, perguntar, doar idéias, reclamar… enfim tudo aquilo que possa colaborar com o tópico. Tenho a absoluta certeza que muita gente, principalmente o pessoal novo na linguagem JAVA estará aprendendo muito aqui.[/size] :thumbup:

Um abração para todos, [color=blue][size=15]OBRIGADO![/size][/color]

pedromuyala

Ninguém mesmo? Mas fico no aguado. :smiley:

B

Exceções que você não conhece são as unchecked, Errors ou RuntimeExceptions. Errors não tem muito o que fazer a não ser fechar o programa(e tentar logar o erro). RuntimeExceptions geralmente são erros de programação, também o que dá para fazer é logar a exceção e dar desculpas.

Em ambos os casos você se previne escrevendo bons códigos com boas práticas.

pedromuyala

Fala Brunão, boa tarde! :smiley:

Então se ocorrer um erro/exception que por ventura venha ocorrer e não estende MinhaAplicacaoException, no máximo, deve ser logado e só?

Bruno, você acha que estou fazendo certo o MVC se comunicar através de Exceções?

Eu gostei da idéia porque todas as letras do (M-V-C) interagem sem precisar instanciar uma a outra. Até aí, legal, afinal: É um cadastro. Ou seja, a informação transita da visão -> controle -> modelo. Se algum problema ocorre nesse meio (Exception) ela facilmente chega a visão. :smiley:

Mas e se eu fizer uma busca que retornara clientes? Aí o fluxo é invertido (visão <- controle <- modelo). Não vou trazer informações do modelo até aparecer na visão através de Exception’s, estou errado? :frowning:

Obrigado Bruno, fico no aguardo pela resposta! :wink:

pedromuyala

pedromuyala:
Fala Brunão, boa tarde! :smiley:

Então se ocorrer um erro/exception que por ventura venha ocorrer e não estende MinhaAplicacaoException, no máximo, deve ser logado e só?

Bruno, você acha que estou fazendo certo o MVC se comunicar através de Exceções?

Eu gostei da idéia porque todas as letras do (M-V-C) interagem sem precisar instanciar uma a outra. Até aí, legal, afinal: É um cadastro. Ou seja, a informação transita da visão -> controle -> modelo. Se algum problema ocorre nesse meio (Exception) ela facilmente chega a visão. :smiley:

Mas e se eu fizer uma busca que retornara clientes? Aí o fluxo é invertido (visão <- controle <- modelo). Não vou trazer informações do modelo até aparecer na visão através de Exception’s, estou errado? :frowning:

Obrigado Bruno, fico no aguardo pela resposta! :wink:

[color=red]Opa pessoal, estou postando o código já implementado (qua havia prometido) já com as exceções para ficar viável o entendimento da pergunta acima.[/color]

Classes do Modelo: [abstract Documento, Cliente e CPF]

abstract Documento:

public abstract class Documento {}

CPF:

public class CPF extends Documento {   
      String numero;   
       public CPF(String numero)   
      {   
         if(!Util.validaCPF(numero))     
            throw new CPFException();   
         this.numero = numero;   
      }   
   }

Cliente:

public class Cliente {
   
      private String nome;
      private Documento cpf;
   
       public Cliente() {
      }
   	
       public Cliente(Documento cpf, String nome)   
      {   
         this.setCPF(cpf);       
         this.setNome(nome);   
      }   
   
       Documento getCPF() {
         return this.cpf;
      }
   			
       void setCPF(Documento cpf) {
         this.cpf = cpf;
      }
   
       String getNome() {
         return this.nome;
      }
   			
       void setNome(String nome) {
         if (nome == null)   
            throw new ClienteException("O nome não pode ser nulo.");   
         nome = nome.trim();
         if (nome.isEmpty())
            throw new ClienteException("O nome não pode estar em branco.");
         this.nome = nome;
      }
   }

Classe do Controle:

public class ClienteControl {       
           
      private Cliente cli = null;       
       
       ClienteControl(Cliente cli) {       
         this.cli = cli;       
      }     
       
       public void cadastrar(String nome, String cpf) throws CadastroDeClienteException {
         CPF doc = new CPF(cpf);
         this.cli = new Cliente(doc, nome);
      }
   }

Classe da Visão:

import javax.swing.*;
   import java.awt.event.*;

    public class View extends JPanel {
    
      private ClienteControl controller = null;
      private JButton btnExecute;
      private JTextField nome;   
      private JTextField cpf;   
      private JLabel lblCad; 
   
       public View(ClienteControl controller) {
         this.controller = controller;
         this.initialize();
      }
   
       private void initialize() {
         nome = new JTextField(10);   
         add(nome);   
         cpf = new JTextField(10);   
         add(cpf);   
         btnExecute = new JButton("Cadastrar");   
         btnExecute.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                     View.this.cadastrar();
                  }
               });
         add(btnExecute);   
         lblCad = new JLabel();   
         add(lblCad);   
      }
   
       private void cadastrar() {
         try {
            this.controller.cadastrar(nome.getText(), cpf.getText());
            lblCad.setText("Cadastro realizado com sucesso");
         }
             catch (CadastroDeClienteException e) {
               lblCad.setText(e.getMessage());
            } 
      }  
   }

Classes de Exceções: [CadastroDeClienteException, ClienteException e CPFException]

CadastroDeClienteException:

public class CadastroDeClienteException extends RuntimeException {
    
       public CadastroDeClienteException() {   
         super();   
      }   
   
       public CadastroDeClienteException(String message) {   
         super(message);   
      }   
   
       public CadastroDeClienteException(Throwable cause) {   
         super(cause);   
      }   
   
       public CadastroDeClienteException(String message, Throwable cause) {   
         super(message, cause);   
      }   
   }

ClienteException:

public class ClienteException extends CadastroDeClienteException {
   
       public ClienteException(String msg) {
         super(msg);
      }
   }

CPFException:

public class CPFException extends CadastroDeClienteException {
       public CPFException() {
         super("CPF Inválido");
      }
   }

[size=16]A pergunta é a citada nesta mensagem.[/size]
Agradeço a todos do GUJ que estão ajudando e colaborando com o tópico! :smiley:
Agradeço também aqules que disponiblizam de seu tempo simplesmente lendo o tópico e mesmo não postando, de alguma maneira, tentou ajudar!
Não deixe de opinar, dar sugestões, criticar… [color=orange][size=20]OBRIGADO![/size][/color]

pedromuyala

Meu Deus esse silêncio me assusta! :shock:
Devo estar fazendo perguntas sem sentido… :frowning:

pedromuyala

Pessoal se estiver existindo alguma dificuldade para entender a pergunta por favor não deixem de avisar que eu tento expor melhor o problema para vocês.
Qualquer coisa também se preferir mandar a pergunta por MP pode mandar.
Peço antecipadamente desculpa se estou formulando mal a pergunta…é que realmente tenho muita dificuldade às vezes até para formular as perguntas.
Não me levem a mal… qualquer situação de dúvida pode falar!
Obrigado pessoal, um abraçopara todos e para o Bruno que me ajudou bastante nessas últimas postagens. Sucesso! :smiley:

pedromuyala

Boa Tarde pessoal!

Sério mesmo que não existe nada na qual possa me ajudar para resolver o caso? :slight_smile:
Nada mesmo, uma dica, uma opinião, uma pergunta, uma crítica…??? :oops:
Ou estou pedindo algo impossível e insustentável??? :frowning:
Que vontade de chorar… :cry: :cry: :cry:

fantomas

Não, vc não está errado! Vc não vai utilizar exceptions para transportar dados.

visão <- controle <- modelo

A idéia do padrão MVC tem que ficar isolado no cliente sem envolver diretamente o servidor ou outro tipo de coisa. Significa que o controle é quem irá executar qualquer ação externa ao módulo (MVC).

Existe uma variação desta idéia chamada MVP, dá uma lida no conteúdo deste link http://www.javafree.org/artigo/871446/Apresentando-ModelViewPresenter-o-MVC-focado-na-visualizacao.html.

flws

pedromuyala

Fantomas, boa tarde! Desculpa na demora ao responder!
Mais uma vez muitíssimo obrigado por continuar atento ao tópico, sem palavras!

Vou implementar neste final de semana o exemplo do artigo com calma e volto a postar! :wink:
Um abração!

B

Pedro, dê uma lida no Mundo Java nº 36 que saiu este mês, nele tem um artigo do Eduargo Guerra que resume exatamente o que explicamos aqui sobre exceções. É bem mais claro e diz algumas coisas que não falamos aqui.

pedromuyala

Olá Bruno, boa tarde!
Obrigado pela indicação mas eu já havia visto a matéria do Eduardo. Até cheguei a dizer em posts anteriores indicando para quem estivesse também interessado para ler! :smiley:

Ainda estou tentando entender o MVC. Ainda tenho muitas dúvidas que, ao meu ver são perguntas simples mas como cada desenvolvedor tem um hábito (um jeito) na qual de familiariza mais acabo ficando perdido nesse meio, infelizmente. Gostaria muito de desenvolver o MVC em uma forma que qualquer desenvolvedor que vier a ler o código entenda sem muitas dificuldades. Meu problema que realmente está me “travando” é o MVC. :frowning: Mas vou tentar formular minha pergunta de uma forma abstrata que fique fácil as pessoas entenderem e poderem colaborar! :slight_smile:

Muito obrigado mesmo por não ter se esquecido do tópico, fico muito contente! :smiley:
[color=red]Um abração Bruno, felicidades.[/color]

luistiagos

É uma pessima pratica usar exceções para tudo… vc pode usar exceções para mensagens de negocio tranquilamente até é mais facil de manipular a app assim… pode ser feito o seguinte: criar somente 1 classe de excecao de negocio onde vc passe a menssagem tipo: cpf invalido, cnpj invalido, qualquer coisa invalida, dai caso for sua exceção de negocio ele a mostra na sua view como uma mensagem normal, e caso for um erro como um Nullpointer, ou uma exceção de banco de dados ele vai para uma pagina de erro… assim é bem mais facil de controlar isto…

B

Eu vou pela receita que a minha vó me ensinou: Nem oito nem oitenta.

É ruim ter quase nada, também é ruim ter em excesso. O ideal é o caminho do meio, saber medir.

Digo o mesmo para o próprio MVC, ele não é a solução para todos os problemas. Muita coisa é melhor resolvida sem ele, então não tente aprender tudo só trilhando esse caminho. É até bom que esteja travado, tente seguir por outros métodos de fazer a mesma coisa, uma visão diferente pode até te ajudar a entender melhor o que você estava vendo. Basta tempo e paciência.

pedromuyala

Olá pessoal, boa noite! :smiley:

Luistiagos, obrigado pela dica da Exception. Também pensei exatamente isso que falou!
Achei legal sobre os exception’s em geral. Como o controle seleciona a visão, caso uma exceção que não conheço ocorra, ele pode solicitar uma nova visão acusando um erro. Muito legal! :idea:
Porém quanto ao uso de uma Exception para tudo força que as informações de erro (menssagens) fiquem fora da visão e aparentemente seria melhor deixar detalhes da visão na visão, ou não?

Acho que o Laturner tem razão quando diz que estou muito “mente fechada” só para MVC. Mas estou estudando o caso do MVP também que o fantomas indicou em um post anterior e até mesmo o uso de frameworks postados bem anteriormente… até porque a teoria do MVC não diz nada sobre validações, banco de dados, exceções… Acredito que essa parte é livre para cada um implementar da forma que achar melhor como no nosso caso real de utilizar exceções para validações.

Assim sendo, tenho uma pergunta bem amadora: Quais as responsabilidades do controle no MVC para Desktop [color=red](não WEB)[/color]? O que ele de fato deverá fazer? :shock:

  • Sabemos que a visão é quem mostra o estado do modelo ao usuário. (ou várias visões)
  • Sabemos que é no modelo que estão os dados a serem exibidos.
  • E o controle??? Essa foi uma pergunta feita no início do tópico que gerou muita discussão. :? Mas com o andar da carroagem a essa altura gostaria de saber de vocês o que entendem nesse momento que é dever do controle? :slight_smile:

Opine, não deixe de opinar, seja veterano no tópico ou um novo leitor! Tem dúvidas, pergunte aqui também, sem se acanhar!
[color=orange][size=16]Obrigado a todos, sem exceções![/size][/color] (kkkk… :thumbup: )

pedromuyala

Nem uma ídéia? :idea:
A pergunta está mal formulada? :?

B

Não respondi pq nunca trabalhei com Desktop. Umas perguntas retóricas:

Que diferença você vê entre Desktop e Web? Qual a diferença da View Web da View Desktop? Qual a diferença do Controller Web do Controller Desktop? Há diferenças entre Model Web e Model Desktop?

Também sou um aluno aqui :slight_smile:

pedromuyala

Boa tarde Bruno!
Vou responder aquilo que sei, pois WEB sou muito ruim. Mas vamos lá:

Desktop não precisa usar servlet’s como controlador. Porém para mim no Desktop o controlador só é uma “ponte” para visão e modelo se comunicarem.
Não faz validações, não trata eventos da visão… Não faz nada a não ser criar uma instancia do modelo para poder alterá-lo ou passar dados da visão para ele. E dependendo do que for solicitado na visão, pode trocar a visão ou alterar a visão sem fazer nada no modelo.

Desktop usa Swing/AWT.

Não existe, a não ser usar servlet.

Não existe, ao meu ver, é o mesmo.

Valew Bruno! :smiley:

B

Uma situação:

Você tem uma aplicação desktop, e você move o model para um servidor remoto, numa máquina diferente. Não querendo que a cara da aplicação mude, você mantém a mesma view. Neste caso tem que mudar somente o Controller, considerando que eles mantém a mesma interface e tratamento de eventos da view?

pedromuyala

Bruno, olá!

Bruno Laturner:
Uma situação:

Você tem uma aplicação desktop, e você move o model para um servidor remoto, numa máquina diferente. Não querendo que a cara da aplicação mude, você mantém a mesma view. Neste caso tem que mudar somente o Controller, considerando que eles mantém a mesma interface e tratamento de eventos da view?

:arrow: Então Bruno até aí entendi a situação! Só uma coisa que fiquei na dúvida: A visão deve ter uma interface e o controle um implements dessa interface da visão?

pedromuyala

Na verdade, a pergunta é a seguinte:

A visão conhece o modelo para se reenderizar;
O modelo é o domínio do sistema. Não conhece ninguém.
O controle recebe eventos da visão e altera o modelo. É aí que surge a dúvida: Quando diz: “O controle recebe eventos da visão” significa que quando eu clicar em um botão da visão ela chamará um método do controle?

Ex:

Botão adicionar da visão chama controle.adicionar(par1, par2, par3);

Botão remover da visão chama controle.remover();

Aguardo pela resposta! :smiley:
Quero deixar um abraço para o Bruno que tem me ajudado bastante aqui no fórum! :wink:

Andre_Fonseca

pedromuyala:
Na verdade, a pergunta é a seguinte:

A visão conhece o modelo para se reenderizar;
O modelo é o domínio do sistema. Não conhece ninguém.
O controle recebe eventos da visão e altera o modelo. É aí que surge a dúvida: Quando diz: “O controle recebe eventos da visão” significa que quando eu clicar em um botão da visão ela chamará um método do controle?

Ex:

Botão adicionar da visão chama controle.adicionar(par1, par2, par3);

Botão remover da visão chama controle.remover();

Aguardo pela resposta! :smiley:
Quero deixar um abraço para o Bruno que tem me ajudado bastante aqui no fórum! :wink:

Oi Pedro,

Deixa eu intrometer um pouco… hehe…

Na verdade é o contrário, pelo menos como eu entendo - me corrigam se estiver errado - , é responsabilidade do controle avisar a visão quando alguma coisa mudar

Para entender melhor dê uma lida no pattern observer que vai te esclarecer bem

t+

pedromuyala

Olá André, obrigdo por estar atento ao tópico! :smiley:

Então o Observer avisa as visões sobre a mudança do modelo para que elas sejam reenderizada.
Até aí 100%. Porém, o controle recebe os eventos emitidos pela visão. Aí que eu quero entender que eventos são esses?
Ou seja, essa ligação dos eventos da visão com o controle é feita assim:

import javax.swing.*;
   import java.awt.event.*;

    public class View extends JPanel {
    
      private ClienteControl controller = null;
      private JButton btnExecute;
      private JTextField nome;   
      private JTextField cpf;   
      private JLabel lblCad; 
   
       public View(ClienteControl controller) {
         this.controller = controller;
         this.initialize();
      }
   
       private void initialize() {
         nome = new JTextField(10);   
         add(nome);   
         cpf = new JTextField(10);   
         add(cpf);   
         btnExecute = new JButton("Cadastrar");   
         btnExecute.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                     View.this.cadastrar();
                  }
               });
         add(btnExecute);   
         lblCad = new JLabel();   
         add(lblCad);   
      }
   
       private void cadastrar() {
         try {
            this.controller.cadastrar(nome.getText(), cpf.getText());
            lblCad.setText("Cadastro realizado com sucesso");
         }
             catch (CadastroDeClienteException e) {
               lblCad.setText(e.getMessage());
            } 
      }  
   }
public class ClienteControl {       
           
      private Cliente cli = null;       
       
       ClienteControl(Cliente cli) {       
         this.cli = cli;       
      }     
       
       public void cadastrar(String nome, String cpf) throws CadastroDeClienteException {
          // ALTERA O MODELO!
      }
   }

Fico no aguardo pela resposta! Obrigado André e a todos que estão acompanhando!

pedromuyala

Na verdade a pergunta é: Os eventos que o controle recebe da visão também usam Observer?

pedromuyala

Ninguém arrisca responder essa última pergunta?

fantomas

Utilizar o Observer é UMA das maneiras de se implementar o MVC, muitos não são favoráveis ao uso dele por adicionar complexidade e dificultar o debug da aplicação.

Nos seus exemplos não foi utilizado este padrão, ou seja, foi adotada uma outra abordagem (sem o uso do observer).

Resumindo…tenho a impressão que a idéia do observer está fazendo o assunto mudar um pouco a direção, confirma?

E respondendo sua pergunta: sim, já que o padrão faz com que as 3 partes fiquem de certa forma associadas.

flws

pedromuyala

Boa tarde fantomas, desculpa não responder antes!

fantomas:
Utilizar o Observer é UMA das maneiras de se implementar o MVC, muitos não são favoráveis ao uso dele por adicionar complexidade e dificultar o debug da aplicação.

Nos seus exemplos não foi utilizado este padrão, ou seja, foi adotada uma outra abordagem (sem o uso do observer).

Resumindo…tenho a impressão que a idéia do observer está fazendo o assunto mudar um pouco a direção, confirma?

E respondendo sua pergunta: sim, já que o padrão faz com que as 3 partes fiquem de certa forma associadas.

flws

Então realmente fizemos sem o uso do Observer e que na minha opinião ficou muito bom!
Está bem definido o que é visão, controle e modelo. A aplicação da propagação de Exception do modelo até a visão nas validações e erros também ficou muito legal, super bacana e muito fácil de entender.

Porém se eu tiver várias visões, como elas se atualizarão com uma mudança no modelo?

E percebo que existe um acoplamento fortíssimo entre as 3 partes. Por isso pensei no uso do Observer afim de libertar as partes para que fiquem flexíveis.
Na verdade, se for olhar o esquema da comunicação entre as partes, repare que o modelo avisa a visão sobre mudanças sem se associar diretamente a visão e o mesmo ocorre com a visão avisando o controle sobre mudanças feitas (Ex: botões clicados). Outra coisa que reparei é que o “controle é quem recebe o objeto visão e objeto modelo” e a “visão recebe o objeto modelo” (associação direta).

Lembro que a primeira postagem do código-exemplo que postei tinha a visão completamente desacoplada do controle (a visão podia receber qualquer tipo de controlador). Porém o controlador fazia uma “ponte” entre visão e modelo na hora de atualizar a visão, o que sabemos não ser correto! Aí então surgiu a idéia de aplicar o observer para que a visão se atualize com o estado do modelo, as Exception’s para o caso de problemas de validação e erros e a visão transmitindo ao controle somente eventos sem conhecer nada sobre ele (o controle recebe a visão e se registra nela - acho que é assim que se fala).

Entenderam a idéia? Acredito que assim teriamos uma implementação bem flexivel, ou seja, posso alterar a visão (V) sem alterar nada no resto (C,M) que é o ponto chave aí da questão. Já o modelo não tem jeito se for alterado a visão e o controle vão sofrer impacto (isso digo no caso de mudar os métodos existentes na interface do modelo).

Tem lógica o que estou falando ou estou “dirigindo completamente embriagado sem direção alguma”? ( SE BEBER NÃO DIRIJA! :wink: )

Um abraço a todos do GUJ é um prazer estar aqui com todos vocês trocando essas idéias. :wink:
Um abração aí para fantomas, Bruno Laturner e o André Fonseca que evoluiram muito o tópico!
Obrigado fico no aguardo pelas respostas!

fantomas

O que vc está falando tem sentido sim.

A questão é a seguinte: Tem que ver o quanto vc está disposto a “pagar” para chegar no objetivo almejado.

  1. O que foi feito até agora é uma abstração que timidamente se aproxima da definição do padrão MVC. Porem oferece menos complexidade e maior controle sobre o fluxo dos eventos.

  2. O Observer é um elemento intermediador que oferece maior independencia fazendo com que os resultados fiquem praticamente iguais aos da proposta dos padrão MVC. Porem a complexidade aumenta bastante e o controle do fluxo dos eventos fica também mais dificil (claro que isto está diretamente ligado as condições técnicas de quem está desenvolvendo, logo para alguns pode ser até simples de operar).

Na internet tem vários exemplos que aplicam o Observer para implementar o MVC http://csis.pace.edu/~bergin/mvc/mvcgui.html dá uma olhada e vc perceberá melhor o que estou dizendo.

P.S Tente aplicar o Observer no exemplo para vc ver como é que fica.

Resumindo…o treco é como quase tudo, uma questão de escolha.

flws

pedromuyala

Bom dia fantomas!

Vou tentar implementar sim escolhendo a opção 2 para tentar manter a visão associada indiretamente com o controle e tentar manter o modelo associado indiretamente com a visão. Não vou usar o padrão java.util.Observer (igual ao do exemplo do termômetro do link) e sim o Source e Listener. Concordo quanto a complexidade, realmente vai complicar, mas acredito que será útil e importante esse desacoplamento futuramente.

Obigado vou estudar e qualquer coisa volto a postar :wink:

pedromuyala

Boa noite pessoal, estou de volta! :lol:
Passei um tempo afastado mas estamos aí! :expressionless:

Tenho uma pergunta bem simples, ainda dentro do MVC (DESKTOP)!

Já aprendi os seguintes passos:

  • Para a visão reenderizar o modelo devo implementar o pattern Observer;
  • A função do controle é de alterar o estado do modelo e/ou a visão para que esta seja apresentada de forma apropriada;
  • O controle somente recebe eventos para tomar a atitude correta na hora de alterar o modelo (somente eventos);

Pergunta: Mas para o controle receber um evento ele deve estar preparado para isso, ou seja, ele deve ser um observador (listener) de eventos que ocorrem na visão?

Obrigado galera! Um abração para todos, fico no aguardo pelas respostas! :thumbup:

pedromuyala

Olha só pessoal, para servir como auxilio no entendimento da pergunta anterior a imagem abaixo representa bem a situação:

Veja que na linha “notificação de atualização” o pattern Observer é ao meu ver a melhor solução do problema.
Mas e na “User Gestures” uso Observer também?

Obrigado pessoal estou no aguardo! :smiley:

sergiotaborda

Para o gesture a visão tratará sozinha.Se usa swing, o AWT fará esse papel.
se usa web, o browser/javascript fará esse papel.

O MVCé a soma de um conjunto de padrões que é maior que as partes.

pedromuyala

Boa tarde Sergio, obrigado por estar colaborando com o tópico! :smiley:

Entendi quando disse que o gesture quem trata é a própria visão. Legal! É Swing sim.
Porém o tratamento das gestures que ocorrem na visão deverão chamar métodos do controle quando necessário alterar o modelo, estou certo?
A visão vai se associar diretamente com o controle? Ou seja, vai ter um atributo de controle?

OBRIGADO a todos que estão colaborando! Agradeço muito e fico no aguardo pela resposta! :wink:

sergiotaborda
Não. A visão envia gestos do tipo clique no botão X, duplo clique no label Z, mouse movendo sobre imagem H

Isto não significa nada para o negocio/dominio. A visão envia estes gestos pelo padrão Observer para o controlador. (note que no swing o componente swing é o controlador MCV do swing. Por exemplo JButton é um controlador.)

O Controlador pode responder se se trata de um evento de visão (aumentar painel num JSplitPane) , mas se for um evento de negocio ele terá que responder diferente. NO swing, os eventos da visão são interceptado para reconhecer eventos de nogocio (ou seja,vc coloca um action listener no JButton para poder dar save.Save é de negocio.)

Aqui temos duas opções , ou invocamos um objeto que sabe resolver o evento (no caso do save chamar um objeto.save(instancia))

ou delegamos a um outro objeto. O primeiro caso, dentro do listener são lidas as informações necessárias e ativadas as acções no banckend. Isso é um pesadelo.

Com um outro objeto vc lança um evento / chama um método de um outro objecto.Ele conhece o negocio.

Então o controler do MVC de apresentação chama um outro objecto.

Este cara conhece como ler um formulário, por exemplo. então quando ele recebe o comando de salvar ele sabe onde ler as informações da tela , colocar num bean e invocar um objeto para fazer o real serviço de salvar.

Este objeto pode ser o model ou um outro objeto fora do MVC.

Quem é o model ? O model é por exemplo um TableModel ou um Action ou algum objeto associado ao Controlador do swing.
Este objeto é comandado pelo controlador (de dentro do listener). Por exemplo, um botão pode ser desabilitado com action.setEnable(false). Isto irá ativar um evento na view para que ela se re-renderize e por consequencia mostre o botão desativado vc não deve fazer butto.setEnable(false).

So que controlar codigo dento do model ou do listener vira uma sopa. a solução é usar um presenter
Um Presenter é um objeto que responde a eventos de negocio que interessam. Assim o listener irá invocar presenter,save()
e o presenter ser vira. Ele tem acesso aos modelos da tela para ler informações de formulário ,etc… e depois invocar o save em algum outro objeto . Ele também atualiza algum dos modelos do swing para apresentar estado visual. (por exemplo é comum apresentar um JProgress enquanto a ação está sendo feita.

Utilizar um Presenter é mais comodo. Repare que do pronto de vista do seu design todo o swing é a sua view embora ele ,lá dentro tenha três partes) e o Presenter atua como controlador e modelo. Este padrão é chamado MVP

Repare que é este o padrão real para coisas como JSF, Spring MVC e qualquer framework “MVC” por ai.
Vc sempre é encarregado de modificar um componente , mas ele não é a view , nem o controlador,nem o modelo.
(a view é o HTML/browser , o controlador é o proprio framework, e modelo são os beans onde estão os dados)

pedromuyala

Olá pessoal, eu novamente!

Até entendi a teoria que o Sergio citou no post anterior. Estudei sobre MVP mas acabo caindo nas mesmas dúvidas que tinha no MVC! :smiley: Chato né?

  1. A visão gera eventos para o presenter ou a visão chama métodos explicitamente do presenter?
  2. O presenter gera eventos para a visão ou o presenter chama métodos explicitamente da visão?
  3. O modelo, quando alterado, avisa o presenter gerando eventos para ele (pattern Observer)?

Até onde tenho visto, o presenter chama os métodos do modelo explicitamente (objetoModelo.metodo()), ou seja, presenter conhece o modelo.

Obrigado pessoal que vem colaborando com este longo tópico… :smiley:
Reparem que venho postando com menos freqüência para poder estudar a fundo tudo o que vocês se esforçam tentando ajudar!
Espero que não desistam, já se tornou um sonho para mim aprender corretamente uma arquitetura (pelo menos uma) e implementa-la.
Agradeço demais a todos, sem exceções, pelos esforços! Fico no aguardo pelas respostas. :smiley:

pedromuyala

Nada mesmo? Nem uma opinião? :shock:

pedromuyala

Estou conseguindo expressar corretamente a pergunta ou ficou ruim de entender?
Qualquer coisa pergunta que eu tento expor melhor ainda o problema pessoal!
Agradeço antecipadamente a todos que estão de alguma forma ajudando ou até mesmo desprendendo do seu tempo lendo para tentar ajudar. Muito obrigado! :wink:
Fico no aguardo pela resposta!

edmarr

Nao precisa , floodar , por favor Aguarde !!!

B

pedromuyala:
Estou conseguindo expressar corretamente a pergunta ou ficou ruim de entender?
Qualquer coisa pergunta que eu tento expor melhor ainda o problema pessoal!
Agradeço antecipadamente a todos que estão de alguma forma ajudando ou até mesmo desprendendo do seu tempo lendo para tentar ajudar. Muito obrigado! :wink:
Fico no aguardo pela resposta!

Até entendi a pergunta, mas a resposta que tenho é “Não sei”. Pelo menos ainda não trabalhei com este modelo para saber.

Estas tuas perguntas seriam melhor respondidas no fórum de Arquitetura de Sistemas.

pedromuyala

Olá edmarr, boa tarde! :smiley:
Obrigado por participar conosco no tópico!

Rapaz, desculpa mas não entendi o que você falou…
Procurei por flood mas nada encontrei… :frowning:
Isso tem a ver com eventos?

Valew, fico no aguardo pela resposta. Obrigadão por estar colaborando :wink:

sergiotaborda

pedromuyala:
Estou conseguindo expressar corretamente a pergunta ou ficou ruim de entender?

Ficou ruim de entender. Em java o modelo de eventos é feito chamando métodos…

vc tem que pensar que

eventos = broadcast : difusão
chamada directa = acoplamento

Se A chama B directamente A depende de B.
Se A lança eventos e B se registra como ouvinte, B depende de A (na realidade do listener de A).
No modelo de evento vc tem uma relação 1-produtor para N-consumidores.

A view chama 1 controlador ou N ? Chama 1. então, ela chama directamente e não pelo modelo de eventos.

Só que, detalhe, a chamada é feita em resposta a um evento (por exemplo,clique do mouse). então, tecnicamente é um evento, embora esse evento vá apenas para um objeto.

Por exemplo, entre o model e o view a relação é inversa. Um model pode alimentar vários views.
portanto alterações no model se propagam via eventos.

pedromuyala

Olá Bruno, tudo bem? Obrigado por continuar atento aí mesmo depois de bastante tempo! :smiley:

Bruno Laturner:

Até entendi a pergunta, mas a resposta que tenho é “Não sei”. Pelo menos ainda não trabalhei com este modelo para saber.

Estas tuas perguntas seriam melhor respondidas no fórum de Arquitetura de Sistemas.

Antes de mais nada quero agradecer muito toda ajuda que escreveu neste tópico. Sua participação foi extremamente importante para deixar bem exclarecida as dúvidas que apareceram.
E mais uma vez mostra-se uma pessoa sincera, ética e profissional. Assim como eu e muitas outras pessoas não sabemos a resposta para a pergunta. É essa sinceridade que engrandece o ser humano. Por que digo isso? Porque você vem acompanhando e ajudando sempre que consegue e chegou um momento que infelizmente não sabemos a resposta mas mesmo assim não deixou de dar uma SATISFAÇÃO mostrando aos demais usuários do GUJ que se alguém souber a resposta, por favor, postem sem receio de atrapalhar ou intrometer-se com o andamento do tópico. Isso é ético e profissional. Meus parabéns mais uma vez como disse anteriormente muitíssimo obrigado por tudo que fez pelo tópico. :smiley: E espero ainda juntos conhecer a resposta em breve aqui mesmo.

Sobre o fórum de arquitetura já havia percebido isso hà um tempo atrás mas para evitar duplicar o tópico mantive o assunto aqui mesmo. Na verdade esse tópico começou com o título “Simples pergunta de MVC” mas olha como ficou o simples kkkk… Mas mesmo assim agradeço pelo toque! :wink:

Um abração Brunão, felicidades rapaz!

pedromuyala

Olá Sergio, muito obrigado por continuar atento ao tópico! :smiley:

Você entendeu sim minha pergunta e respondeu muito bem explicado, uma aula mesmo.
Porém é bem aí que está a minha dúvida principal. Vou tentar explicar o mais detalhado possível para ficar bem transparente:

Quando começar a desenvolver as view’s vou ter várias chamadas aos métodos do controlador (que é um atributo da visão instanciado incialmente). Exemplo disso é o JButton.addActionListener(…), JTextField.addActionListener(…), veja:

botao1.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                        controlador.tipoEscolhido(botao1.getText());
                  }
               });
          //...
         botao2.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                        controlador.tipoEscolhido(botao2.getText());
                  }
               });
          //...
         textfield1.addActionListener(
                new ActionListener() {
                   public void actionPerformed(ActionEvent e) {		     
                        controlador.tipoEscolhido(textfield1.getText());
                  }
               });

Por isso quando observo no desenho do MVC com a linha tracejada (indicando um evento) nomeada “User Gestures” no sentido View—>Controller eu fico sem entende-la!

Se a resposta é o quote acima, me desculpa Sergio pela minha ignorância, mas tem como mostrar isso melhor? :oops: É que não consigo visualizar, ou seja, quando olho para essa seta vejo ela continua (chamada de métodos) e não tracejada (Eventos). Outra coisa que não consigo entender é o controlador chamar métodos na visão (linha continua “Seleciona a View”). 100% acoplamento! :?

Agora um problema pior ainda é:
Suponhamos que o método tipoEscolhido do controlador venha a ser retirado/alterado. Vou ter que alterá-lo em todas as visões (isso se eu não esquecer de nenhuma).
Se não me engano no seu penúltimo post você citou isso (ou pelo menos eu entendi isso) como acabar se tornando um pesadelo. Até foi recomendado o uso do MVP.
Assim como o controlador é acoplado ao modelo, a visão também acaba acoplada ao controlador. A diferença é que o controlador acoplado ao modelo é muito mais fácil de ser corrigido quando necessário realizar mudanças do que a visão acoplada ao controlador, visto que o número de visões é muito maior.
Existe uma solução para isso ou uma outra forma que evite isso?

[size=16][color=red]Mais uma vez quero dizer a todos [/color]obrigado [color=red]por todo o tempo dedicado em ajudar.[/color][/size] :thumbup:
[color=orange]Muito mais do que palavras só mesmo a realidade presente aqui neste tópico de todas as pessoas que vem colaborando.[/color]
Fico no aguaro de respostas, é um prazer e uma honra estar com vocês.

sergiotaborda

O problema é o seguinte: vc está tentando entender MVC usando Swing. Só que para o swing o view é o Look and Feel. Você raramente irá criar um look and feel. JComponent é a raiz do swing. Este objeto é um controlador,não é a view. Este equivoco é comum. Quando vc aperta um botão e é lançado um actionEvent o pedaço do diagrama view-controller já foi executado. Vc não mexe com isso. Vc nem tem controle disso. (cof cof, ter até tem, mas isso é Swing super avançado, então vamos esquecer aqui).

Bom então o controlador já recebeu o evento vindo da view. Agora ele está lançando eventos para o modelo. A classe Action é um modelo tal como TableModel. Isto não é obvio pelo nome pois parece que Action seria um Comand object, mas não é.

Repare que é o Modelo, sempre o Modelo, que contém a regra especifica para a aplicação. Apertar botões é muito genérico. É a aplicação que tem que decidir o que fazer. então, é na action que a gente coloca o codigo relativo à aplicação em si. Mas pq um controlador uitilizar o mecanismo de eventos ? um botão pode realizar mais do que uma tarefa ? Pode. embora seja meio complicado e impráticável. A razão real é o desacoplamento que permite que um listener possa responder a eventos de mais de um controlador. Isto sim é prático. O exemplo classico é o “sair” A opção “sair” pode ser ativada de duas formas : escolhendo opção Sair no menu ou escolher o botão sair da toolbar. As duas lançam actionEvent, que podem ser pegas pelo mesmo listener (basta registrar o mesmo listener nos dois objetos) .

A action parece não ter atributos que possam “mudar o estado” como descreve a figura , mas tem. ela tem o estado enabled. se vc mudar isto, todos os botões que usam aquela action serão habilitados/desabilitados. No nosso caso o menu e o botão da toolbar serão habilitados/desabilitados ao mesmo tempo e apenas pelo fato que têm o mesmo modelo. Simples assim.

Modelos mais complexos têm outros tipos de dados. Por exemplo TableModel é bem completo , assim como TreeModel.

Qualquer mecanismo MVC já tem as coisas orquestradas. Vc só precisa extender cada uma das partes. Ou o model ou o controler ou a view. No Swing o component é o controler e ele tem uma view livre que é definida pelo look and feel. Mas vc pode compor componentes para compor telas diferentes. Como a view é componentizada, vc consegue um mecanismo de compomentes visuais.
Mas isso é algo que o swing oferece que não tem relação com MVC - isso é o padrão Composite - mas que graças ao mecanismo desacoplado do MVC funciona às mil maravilhas.

pedromuyala

Olá pessoal sou eu novamente!
Vou acabar louco com tentando entender a arquitetura do MVC. Pior é que parece ser uma coisa tão simples e natural…

Não consigo entender como a visão se atualiza através do modelo sem conhecer o modelo…
Digo assim: o evento notifica a visão que houve uma alteração… mas para ela reenderizar o modelo ela precisa ter uma instancia do modelo ativa nela ou os dados são enviados dentro do evento?

Agradeço antecipadamente a paciência, me desculpem a perturbação e a insistênca eu sei que já está se tornando uma coisa chata mas por favor peço que não desistam.
Minha intensão mesmo é aprender! Um abração a todos companheiros. Muito obrigado.

pedromuyala

pedromuyala:
Olá pessoal sou eu novamente!
Vou acabar louco com tentando entender a arquitetura do MVC. Pior é que parece ser uma coisa tão simples e natural…

Não consigo entender como a visão se atualiza através do modelo sem conhecer o modelo…
Digo assim: o evento notifica a visão que houve uma alteração… mas para ela reenderizar o modelo ela precisa ter uma instancia do modelo ativa nela ou os dados são enviados dentro do evento?

Agradeço antecipadamente a paciência, me desculpem a perturbação e a insistênca eu sei que já está se tornando uma coisa chata mas por favor peço que não desistam.
Minha intensão mesmo é aprender! Um abração a todos companheiros. Muito obrigado.

Vou tentar explicar melhor nesse passo-a-passo:

  • Classe Carro faz parte do modelo. Um objeto carro é então criado;
  • Classe CarroControl faz parte do controle. Um objeto carrocontrol é criado;
  • O objeto carro então é agregado ao objeto carrocontrol;
  • Por força maior, o objeto carrocontrol recebe um evento para modificar o objeto carro;
  • Então o objeto carro é alterado e lança o evento “carroevent” (classe CarroEvent) aos Listener’s (visões) informando a alteração.

Nesse momento as visões que recebem o evento “carroevent” devem se reenderizar, mas aí vem o X da questão: A visão se atualizará com os valores que estão no evento “carroevent” usando os métodos get() [Ex: carroevent.getCor(), carroevent.getRoda(),…] ou vai usar o objeto carro agregada a ela e chamar os métodos get() de carro [Ex: carro.getCor(), carro.getRoda(),…] para tal? E pergunto ainda se essa segunda opção realmente existe, ou seja, um obejto do modelo deve ser agregado a visão para atualização ou isso não existe?

Obrigado pessoal já estou me sentindo completamente envergonhado :oops: com a situação são mais de 140 postagens com ajuda de muitas pessoas que tenho a certeza de estarem doando o possível e o impossível tentando ajudar muitas vezes desprendendo do seu tempo limitado para isso. São pessoas que valem muito mais que elogios… realmente sem palavras.

Muito obrigado, fico no aguardo das respostas e FELIZ DIA DAS CRIANÇAS!
[size=10][color=red]" Se você é jovem ainda, jovem ainda, jovem ainda
Amanhã velho será, velho será, velho será
Ao menos se o coração, se o coração sustente
A juventude que nunca morrerá "[/color] (Chaves)[/size]

pedromuyala

Nada mesmo pessoal? :shock: :idea:

pedromuyala

Esse silêncio é assustador!! :? :shock:

pedromuyala

Pessoal estou perguntando um coisa que não existe?
Ou a pergunta está mal formulada?

Olhem só:

  • Classe Carro faz parte do modelo. Um objeto carro é então criado;
  • Classe CarroControl faz parte do controle. Um objeto carrocontrol é criado;
  • O objeto carro então é agregado ao objeto carrocontrol;
  • Por força maior, o objeto carrocontrol recebe um evento para modificar o objeto carro;
  • Então o objeto carro é alterado e lança o evento “carroevent” (classe CarroEvent) aos Listener’s (visões) informando a alteração.

Nesse momento as visões que recebem o evento “carroevent” devem se reenderizar, mas aí vem o X da questão: A visão se atualizará com os valores que estão no evento “carroevent” usando os métodos get() [Ex: carroevent.getCor(), carroevent.getRoda(),…] ou vai usar o objeto carro agregada a ela e chamar os métodos get() de carro [Ex: carro.getCor(), carro.getRoda(),…] para tal? E pergunto ainda se essa segunda opção realmente existe, ou seja, um obejto do modelo deve ser agregado a visão para atualização ou isso não existe?

joca_java

Não se preocupe que com 68704684013684068 mensagens que sua pergunta tem, o pessoal entendeu direitinho sua dúvida.
Só não precisa todo santo dia “floodar” seu tópico criando tentando “forçar” alguém a responder.

Isso pega mal pra você e o moderador pode até tomar a decisão extrema de te banir do guj ou apagar este tópico.

Seja paciente… se você reparar, o número de visitas ao seu tópico aumenta. Isso significa que o pessoal está olhando sua pergunta mas não sabe a resposta… então pelo amor de Deus aguarde que quando alguém souber, com certeza irá solucionar seu problema.

Fica aí o toque.

pedromuyala

Oi Joca_java, obrigado por participar do tópico! :smiley:

Nossa que vergonha!!! :oops: :oops: :oops:

Quero antes de mais nada realmente pedir minhas sinceras desculpas pelo desconforto que tenha lhe causado.
Àlias, quero pedir desculpas a todos os usuários do GUJ que na minha opinião é a mais importante e respeitada comunidade brasileira sobre Java.

Conheci o GUJ através da revista MundoJava a qual não perco uma edição. Cito a revista porque boa parte dos moderadores aqui do GUJ já escreveram diversas matérias importantes nela e por isso não quero que eles tenham uma imagem ruim da minha pessoa de forma alguma. Sei que são profissionais qualificados e que não estão aqui brincando e fazem o máximo para que os usuários evitem fraudar as regras de boa conduta no fórum.

Podem ter a certeza absoluta que de forma alguma eu quis causar qualquer tipo de transtorno aos usuários, em nenhum momento. :frowning:
Como sou novo em Java muitas vezes eu acredito estar formulando mal as perguntas (tanto é verdade que, se puder claro, leia as respostas e veja como a pergunta inicial de meses atrás foi mutável até a data atual) e por isso acabo depois de um determinado tempo sem respostas reperguntando se há um entendimento da questão e até tento melhorar reformulando a mesma para ficar ainda melhor.

Mas nada justifica o meu erro que considerou. :cry: Dou toda a razão pela reclamação, entendo o seu lado também.
Volto a pedir desculpas e fico triste em saber que prejudiquei pessoas no lugar de estar colaborando com elas. :frowning:

O que mais me envergonha :oops: (porém aprendi algo novo) é que “floodar” significa ficar reenviando pergunta. Eu pensei que era outra coisa ligada a questão de MVC. Se puder ler alguns tópicos anteriores o usuário edmarr havia postado algo com a palavra “flooder”. Mas se colocar no Google “MVC flooder” veja os resultados malucos que aparecem! :? :? :?
Mas agora já entendi o que significa, disfarça. :roll: Pode ter certeza que vou aguardar muito mais tempo por pelo menos uma resposta antes de perguntar se está ocorrendo algum problema com a pergunta!

Ah você falou sobre o número de visitas ir aumentando né? Se você digitar no Google “Pergunta MVC” olha lá o primeiro link que aparece.
Então acredito que muitas dessas visitas provavelmente devem ser de usuários que ainda não estão participando do GUJ e ficam limitados somente a ler, sem poder responder.
Por um lado incentiva a participação de novos usuários, eu espero! :smiley:

Repetindo só posso lamentar e pedir desculpas a todos os companheiros Gujeiros.
E joca, mais uma vez agradeço pelo toque e pela força tentando ajudar. Quero que continue acompanhando o tópico. Espero que o inconveniente não atrapalhe no andamento do tópico. :thumbup:

É aquilo que eu sempre disse em tópicos anteriores: Uma crítica, opinião, sugestão, idéia serão sempre, sempre muito bem vindas! :wink:
Estou aqui com vocês porque realmente gosto do GUJ. Já visitava vocês a muito tempo antes de me cadastrar nele. As edições da MundoJava a muito tempo já divulgava o fórum.

[size=16]Fico no aguardo pelas respostas a pergunta que fiz nos dois tópicos anteriores a esse. Peço de coração, por favor, se souber orientar o mínimo que for sobre como resolver o problema não deixe de participar. Uma ajuda vale muito mais que mil explicações.[/size]
[color=red]
Agradeço muito o carinho e atenção de todos. Quero mandar um abraço aos companheiros fantomas, Bruno Laturner, André Fonseca, Sergio Taborda, Luis Tiagos, Tnaires, Leonardo Veríssimo, Marcos Henrique, Rodrigo Ferreira e todos que já colaboraram com o andamento do tópico e a todos que desprendem do seu tempo lendo e acompanhando na intensão de ajudar.[/color]

[color=blue][size=18]Obrigado! [/size].·.[/color]

marcio0

pedromuyala:
Pessoal estou perguntando um coisa que não existe?
Ou a pergunta está mal formulada?

Olhem só:

  • Classe Carro faz parte do modelo. Um objeto carro é então criado;
  • Classe CarroControl faz parte do controle. Um objeto carrocontrol é criado;
  • O objeto carro então é agregado ao objeto carrocontrol;
  • Por força maior, o objeto carrocontrol recebe um evento para modificar o objeto carro;
  • Então o objeto carro é alterado e lança o evento “carroevent” (classe CarroEvent) aos Listener’s (visões) informando a alteração.

Nesse momento as visões que recebem o evento “carroevent” devem se reenderizar, mas aí vem o X da questão: A visão se atualizará com os valores que estão no evento “carroevent” usando os métodos get() [Ex: carroevent.getCor(), carroevent.getRoda(),…] ou vai usar o objeto carro agregada a ela e chamar os métodos get() de carro [Ex: carro.getCor(), carro.getRoda(),…] para tal? E pergunto ainda se essa segunda opção realmente existe, ou seja, um obejto do modelo deve ser agregado a visão para atualização ou isso não existe?

</blockquote>

Infelizmente não li o tópico todo, entrei apenas de passagem, mas vou tentar ajudar.

Acredito que as visões recebem do controle um objeto carro (elas tem que conhecer o objeto, ou então receberão um monte de argumentos relativos aos valores alterados) e com esse objeto elas atualizam seus valores.

Algo tipo:

visão.update( carro );

Se as visões que necessitam dessa atualização não conhecerem a classe, terá que ficar assim:

visão.update( cor, placa, roda,  );

Procure pelo padrão de projeto observer (ou publish-subscribe). É exatamente o que você quer saber.

Espero ter ajudado, mesmo entrando no tópico aos 45 do segundo tempo e lendo  a última mensagem :-o
pedromuyala

Olá Marcio0, obrigado por iniciar a sua participação no tópico! :smiley:
Não se preocupe em estar respondendo depois de 17162813836183 respostas.
Toda ajuda é muito bem vinda. Imagine se fossem 2726302323962423 omissões de respostas? :roll: Não existiria essa força que é hoje o Gujão. :lol:

Então eu entendo que isso seria o mais simples em termos de desenvolvimento inicial, ou seja, a “visão conhece o modelo” mas o “modelo não conhece a visão”. Sendo assim se o modelo notificar (Observer) a visão sobre mudança de estado ela simplesmente se atualiza através dos gets do objeto do modelo. [Ex: carro.getCor(), carro.getPlaca(),…]

Só que dessa forma a minha visão estaria completamente acoplada ao modelo sendo que se algo for alterado na classe do modelo a visão sofre um impacto direto.
Lembrando que visões eu posso ter n de vários tipos diferentes. Imagine modificá-las! :shock:

:idea: Para garantir um bom desacoplamento das partes é que então me surgiu a idéia de transmitir as mudanças do modelo para a visão através do próprio evento de notificação. E usado junto com interfaces acredito que torna-se muito bom. Na verdade, a classe do evento implenta o EventObject que recebe como source o próprio objeto criador do evento [this].
Nesse evento existiram os métodos gets() necessários para realizar a atualização da visão(Listener) que recebe-lo. [Ex: carroEvent.getCor(), carroEvent.getPlaca(),…]

Mas como o pessoal tem muuuuuuuito mais experiência no mercado de trabalho e estudo que eu, o que estou aí dizendo pode ter consequências futuras desastrosas!!! :? :x :?

É complicado entender assim só com palavras. Vou acabar deixando os companheiros nervosos! :x Vou realizar uma implementação e postá-la para ficar ainda melhor de entender. :wink:

[size=16]Mas se alguém já tem alguma opinião, crítica tipo “nossa esse cara tá viajando, é um louco sem noção”, idéia, sugestão sobre a última postagem peço por favor não deixe de expressar sua reação enviando uma resposta. Sua resposta é muito importante, não se acanhe.[/size]

Para quem acredita que eu quero é ter audiência se engana eu prefiro ter um tópico com 100 visitas e 100 respostas do que ter um tópico com 1 milhão de visitas e sem nenhuma resposta mesmo que seja criticando. [color=darkred]Obrigado companheiros gujeiros vou implementar a idéia e posta-la! Volto a agradecer a todos que desprendem do seu limitado tempo aqui no tópico colaborando. Valew![/color] :thumbup:

marcio0

pedromuyala:
Olá Marcio0, obrigado por iniciar a sua participação no tópico! :smiley:
Não se preocupe em estar respondendo depois de 17162813836183 respostas.
Toda ajuda é muito bem vinda. Imagine se fossem 2726302323962423 omissões de respostas? :roll: Não existiria essa força que é hoje o Gujão. :lol:

Então eu entendo que isso seria o mais simples em termos de desenvolvimento inicial, ou seja, a “visão conhece o modelo” mas o “modelo não conhece a visão”. Sendo assim se o modelo notificar (Observer) a visão sobre mudança de estado ela simplesmente se atualiza através dos gets do objeto do modelo. [Ex: carro.getCor(), carro.getPlaca(),…]

Só que dessa forma a minha visão estaria completamente acoplada ao modelo sendo que se algo for alterado na classe do modelo a visão sofre um impacto direto.
Lembrando que visões eu posso ter n de vários tipos diferentes. Imagine modificá-las! :shock:

:idea: Para garantir um bom desacoplamento das partes é que então me surgiu a idéia de transmitir as mudanças do modelo para a visão através do próprio evento de notificação. E usado junto com interfaces acredito que torna-se muito bom. Na verdade, a classe do evento implenta o EventObject que recebe como source o próprio objeto criador do evento [this].
Nesse evento existiram os métodos gets() necessários para realizar a atualização da visão(Listener) que recebe-lo. [Ex: carroEvent.getCor(), carroEvent.getPlaca(),…]


Eu entendo o que você disse.
Mas acho que esse acoplamento realmente deve existir. Se a visão trabalha com aquele modelo (a tela exibe as informações do carro), uma alteração no modelo tem que acontecer na tela também (a classe carro agora tem o numero de portas, a tela terá que apresentar isso).
Acho que entendi o que você sugeriu, mas nesse seu exemplo, se o modelo mudar, como a visão vai refletir isso?

Andre_Fonseca

oi Pedro,

Concordo com o Márcio, bom a minha opinião é a seguinte: (pensando bem alto nível, sem código nem nada)

A visão deve ser acoplada ao modelo, mas o modelo não deve ser acoplado a visão… pois acho que a visão, ou seja, a camada que se mostra ao usuário do software, apenas reflete o modelo, e neste caso ela está sim acoplada ao modelo.

Ja em contra-partida o modelo não deve ser acoplado a visão, pois se algum dia você precisar mudar a sua camada de apresentação você vai ter essa independência …

Lembrando que o modelo nada mais é do que uma representação dos objetos do dominio do mundo real, ou seja, se o seu dominio muda todo o resto deixa de fazer sentido, por isso o acoplamento…

t+

pedromuyala

Olá Márcio, muitíssimo obrigado por continuar ajudando aqui no tópico! :smiley:

marcio0:
Eu entendo o que você disse.
Mas acho que esse acoplamento realmente deve existir. Se a visão trabalha com aquele modelo (a tela exibe as informações do carro), uma alteração no modelo tem que acontecer na tela também (a classe carro agora tem o numero de portas, a tela terá que apresentar isso).

É realmente nesse caso de acrescentar atributos ao modelo teremos que implementar na visão, pode ser a visão conhecendo o modelo ou recebendo um evento. Nesse caso de acrescentar poderia fazer uso de Reflection. Mas acredito que estaria construindo um “canhão” para pegar uma formiguinha. Acho que estou começando a entender: O acoplamento é ruim quando ele foge de um contexto, estou certo? O desacoplamento é importante para reusar as partes mas se for pensar bem de nada adianta eu ter uma visão que mostra dados de uma pessoa desacoplada do modelo pessoa, até porque a visão pessoa não poderá ser usada no modelo do carro, concorda? :roll:

Então estava achando legal no evento pelo seguinte: Se eu alterar ou excluir algum método do modelo eu precisaria mudar somente na classe do evento sem precisar mexer nas n visões.
Porém não teria sentido nenhum um atributo da visão estar lá presente se ele não receberá nunca mais nenhum valor. Pior ainda a visão dizer “Vem com CD-Player? -> Sim” mas por alterações realizadas no modelo na verdade ele está dizendo sim não para um CD-Player mas sim para um Blu-Ray! :twisted: Do capeta essa última hein!

Entendi perfeitamente porque as partes devem estar acopladas no MVC e isso não é erro nenhum. :lol:
Legal Marcio eu tenho mais uma pergunta mas para não atropelar a resposta do André vou responde-la primeiro e volto a postar. É em relação ao controle já postarei. Um abração, muitíssimo obrigado, acredito eu que deixou bem claro essa interação entre Visão<->Modelo. Valew! :wink:

pedromuyala

Opa André, puxa muito obrigado por continuar atento ao tópico! :smiley:

André Fonseca:
oi Pedro,

Concordo com o Márcio, bom a minha opinião é a seguinte: (pensando bem alto nível, sem código nem nada)

A visão deve ser acoplada ao modelo, mas o modelo não deve ser acoplado a visão… pois acho que a visão, ou seja, a camada que se mostra ao usuário do software, apenas reflete o modelo, e neste caso ela está sim acoplada ao modelo.

Ja em contra-partida o modelo não deve ser acoplado a visão, pois se algum dia você precisar mudar a sua camada de apresentação você vai ter essa independência …

Lembrando que o modelo nada mais é do que uma representação dos objetos do dominio do mundo real, ou seja, se o seu dominio muda todo o resto deixa de fazer sentido, por isso o acoplamento…

t+

André, deixa eu entender uma coisa: Você falou em “objetos do domínio do mundo real”. O MVC é uma arquitetura para construção de um sistema (no meu caso Desktop mas se aplica outros) ou ele faz parte da arquitetura Layers (camadas)? Porque eu até este momento entendo que o domínio (Bean’s, DAO’s,…) é o M do MVC. [Ex: Pessoa.class, Carro.class, Guitarra.class]. Estou errado né? O certo é eu pensar em camadas não é?

Muito obrigado André, fico no aguardo pela resposta! E fico no aguardo de todos que quiserem participar! :smiley:
[color=red]Obrigado[/color]

maior_abandonado

pedromuyala:
Opa André, puxa muito obrigado por continuar atento ao tópico! :smiley:

André Fonseca:
oi Pedro,

Concordo com o Márcio, bom a minha opinião é a seguinte: (pensando bem alto nível, sem código nem nada)

A visão deve ser acoplada ao modelo, mas o modelo não deve ser acoplado a visão… pois acho que a visão, ou seja, a camada que se mostra ao usuário do software, apenas reflete o modelo, e neste caso ela está sim acoplada ao modelo.

Ja em contra-partida o modelo não deve ser acoplado a visão, pois se algum dia você precisar mudar a sua camada de apresentação você vai ter essa independência …

Lembrando que o modelo nada mais é do que uma representação dos objetos do dominio do mundo real, ou seja, se o seu dominio muda todo o resto deixa de fazer sentido, por isso o acoplamento…

t+

André, deixa eu entender uma coisa: Você falou em “objetos do domínio do mundo real”. O MVC é uma arquitetura para construção de um sistema (no meu caso Desktop mas se aplica outros) ou ele faz parte da arquitetura Layers (camadas)? Porque eu até este momento entendo que o domínio (Bean’s, DAO’s,…) é o M do MVC. [Ex: Pessoa.class, Carro.class, Guitarra.class]. Estou errado né? O certo é eu pensar em camadas não é?

Muito obrigado André, fico no aguardo pela resposta! E fico no aguardo de todos que quiserem participar! :smiley:
[color=red]Obrigado[/color]

bom… eu ja li algumas coisas de gente que intende mais do que eu, vi umas contribuições legais aqui mesmo no guj… acho que da pra eu dar meu pitaco…rs

vamos diferenciar um pouco, eixste o 3-tier e o MVC. 3-tier seria programação em 3 camadas, MVC possue 3 camadas, mais assim mesmo não são iguais. Respondendo a sua pergunta, sim, em MVC você deve pensar um pouco em camadas mas isso apenas para separar o comportamento, a visão é o cara que vai exibir o output para o user, o controle é o cara que vai decidir para onde a aplicação vai, qual vai ser o modelo chamado, qual view vai ser apresentada depois disso… modelo basicamente é o resto (persistencia, regras de negocio, log, envio de emails…) mas apesar de estar separado em camadas, o foco ao menos na minha opinião seria você pensar em comportamentos, em responsabilidades, e separar cada uma destas 3 principais em uma camada. Acreditoque isso responderia a sua ultima pergunta se deve pensar em camadas, elas são uma forma de você manter a sua aplicação de um jeito que permita mais facil manutenção, que facilite vocÊ a portar a aplicação de desktop para web ou vice versa, esse tipo de coisa, mais procure ter um foco no comportamento…

o 3 tier que me parece levar mais em consideração o uso de “camadas”, serie apresentação - regras de negocio - persistencia, no MVC o modelo fica com as 2 ultimas do 3 tier, mais denovo, no MVC se preocupe mais com o “como” do que com o “onde”, claro que sempre respeitando boas praticas também no que esta relacionado ao onde…

estes exemplos de classes que você deu são entidades, ou VOs, ficam no modelo. Beans e DAOs também…

bom…espero ter ajudado… depois eu tendo um pokinho mais de tempo eu volto e comento um poco mais isso.

pedromuyala

Olá Maior_Abandonado, muito obrigado por participar do tópico! :smiley:

Entendi sim, agora ficou bem legal. Devo focar o comportamento. As camadas me ajudam a separar cada uma das letras do MVC, mas o comportamento entre elas é o foco. :slight_smile:

Então essa teoria do controlador que ainda tenho dúvidas. Mas vou explicar bem detalhado para ver se existe um acordo:

  • Já aprendi aqui no tópico que o controlador conhece o seu modelo, ou seja, um modelo é agregado a ele. Isso para que o controlador possa alterar o modelo. Esse acoplamento é normal e real;
  • Outra coisa importante é que o controlador (Isso no Desktop) não recebe nada do modelo como resposta. Ele somente aciona os métodos necessários no modelo para que possa ser alterado;

Agora a dúvida 1 é a seguinte: O Controlador é acionado através de eventos? Ou seja, o controlador é um Listener?
E a nova dúvida 2 é a seguinte: O Controlador é quem decide a troca de visão?

[size=15]Companheiros quero agradecer muito pela força que estão realizando aí no tópico. Está sendo muito útil para todos que querem aprender mesmo de vez como funciona o MVC aplicado em sistemas Desktop.

Fico no aguardo pelas respostas, não se acanhe para responder todos nós estamos aqui para aprender.
[color=orange]Muito, muito Obrigado![/color]
[/size]

Andre_Fonseca

O MVC na minha opinião nada mais é do que uma separação de responsabilidades. No mundo orientado a objetos é considerado uma boa prática que cada objeto seu tenha suas responsabilidades bem definidas e se preocupe apenas em resolver estas responsabilidades. Existe até um termo usado para isso, se quiser depois pode dar uma olhada aqui

Isso de separar em camadas é muito subjetivo, como foi dito existem arquiteturas de 3 camadas, 4 camadas, n camadas… etc Lembrando ainda que mesmo o MVC que hoje é considerado 3 camadas antes era considerado 2 camadas, quando você tinha uma scriptlet gigante com toda a lógica de negócio dentro dela…

Não se preocupe em deixar o seu sistema com 2, 3, 4, n camadas, se preocupe em deixar os seus objetos simples o suficiente para fazerem bem o papel deles, se o seu DAO consegue abstrair o acesso ao banco e faz isso bem feito não importa em que camada você diga que ele pertença…

71C4700

Concordo com o André Fonseca, mais importante que conseguir modularizar todos o seu sistema é, fazê-lo de uma forma que quando for realizar a manutenção seja simples a implementação de uma alteração ou mesmo uma mudança em alguma ‘camada’.

Quando ao problema o grande lance a ser notado, em minha humilde optica, é que a visão deve refletir o modelo, logo, falando conceitualmente, esta de certa forma deveria conhecer o modelo/dominio o qual esta correlacionada.

Agora se deu controlador é ‘esperto’ o suficiente para modelar toda a parte de logica da aplicação de forma que a visão tenha acesso apenas a serviços e os beans/POJOs de sua aplicação, acredito que a visão ficará totalmente desacoplada do model, conhecendo apenas a camada do controlador.

Sempre vejo que os beans/POJOs da aplicação não deveriam ser classificados/identificados como model, bem…muitos vão dizer mais o modelo não é o dominio do sistema, sim mas, alem de tudo, o modelo deve conter a logica de negocio, e esta refletir para a visão, ou atraves do controlador ou pelo uso direto do padrão Observer.

Com uma separação razoavel de responsabilidades, seria possivel transpor um sistema WEB para um desktop alterando apenas a View, está é acredito eu, a grade dficuldade de se trabalhar com a modularização.

Espero não ter apenas enxido linguiça(sem trema…rsrs), e possa ter contribuido com o caminhar da discurção que está muito boa e proveitosa, diga-se por passagem.

Att…

pedromuyala

Olá André Fonseca e 71C4700, muitíssimo obrigado por estarem participando do tópico! :smiley:

Perfeito o conceito de ambos. Se reparar as últimas postagem há um acordo geral entre todos.
Exatamente quando procurei entender a arquitetura do MVC o mais próximo do que podemos considerar correto foi exatamente o poder que ela proporcionará em futuras manutenções do código e escalabilidade.

Quando se diz serviços está se referindo aos métodos do controle, quando chamados, chamam os métodos no modelo necessários para alterá-lo? É isso?

Fiz um esqueminha de como estou enxergando a implementação do MVC até este momento para ver se estou no caminho certo. [color=red](imagem em anexo)[/color]

Ah, essas duas dúvidas que postei anteriormente ficaram em aberto:
Dúvida 1 é a seguinte: O Controlador é acionado através de eventos? Ou seja, o controlador é um Listener?
Dúvida 2 é a seguinte: O Controlador é quem decide a troca de visão?

[color=blue][size=16]Muito Obrigado pessoal por estarem participando do tópico e gostando. Fico muito feliz em saber que está sendo útil para toda a comunidade! :D[/size][/color]
[size=14]Por favor, não deixe de participar do tópico. Sua ajuda é muito importante para nós! Obrigado, fico no aguardo por mais respostas![/size] :thumbup:


Proteu_Alcebidiano

Veja como o projeto Griffon trabalha pra voce entender melhor como aplicar MVC em aplicativos Desktop

http://griffon.codehaus.org/

T+

pedromuyala

Obrigado Proteu por participar! :smiley:
Legal o link vou estuda-lo para conseguir ganhar novas informações! Parece que lá tem o MVC aplicado ao Groovy… isso é novo para mim, vou estudar!

[size=15]Enquanto isso as 3 perguntas anteriores a este dois últimos posts estão em aberto (Antes desse post e do Proteu).
Por favor, se souber a resposta não deixe de contribuir com a comunidade, sua resposta é importantíssima![/size]
Fico no aguardo pelas respostas e mais uma vez muito obrigado a todos que estão contibuindo, mesmo aqueles que somente estão desprendendo do seu tempo em ler! Obrigado.

marcio0

Rapaz, da forma que eu aprendi, que não sei se é a mais utilizada, é receber o evento na visão (a visão é o listener), identifico qual evento é e o que deve ser feito, e chamo o método apropriado no controlador.

O que você quer dizer com troca de visão?

maior_abandonado

eu acredito que sim, se vocÊ for pegar o model 2 (que aliais é mais indicado para web), você vai ter la um lugar dizendo de onde para onde entre as paginas jsp. Por exemplo, no caso do JSF, vai ter la no faces-config uma tag navigation-rule, onde você diz de qual pagina você vai para qual pagina, de acordo com determinada situação. Mesmo em desktop eu considero legal você deixar essa informação em um unico lugar, para depois por exemplo saber onde procurar qual janela iria chamar a janela x. Eu não sei se para desktop o padrão seria esse (igualmente ao model 2 no caso de web) mais é o que eu indicaria

pedromuyala

Olá Márcio, obrigado por continuar acompanhando o tópico! :smiley:

Rapaz o Listener da visão não é para escutar os eventos lançados pelo modelo?
E a visão chama métodos do controlador ou passa eventos para ele? (user gestures)

Por exemplo, ao clicar em um botão da visão, ela muda a interface de gráfica para texto.
Ou então ela chama um outro jogo de MVC: Na visão está sendo apresentado o modelo da classe Pessoa. Ao clicar em um determinado botão lá presente, ela passa a exibir a visão cujo o modelo é da classe Carro.

[color=red]Obrigadão Marcião por estar ajudando, fico no aguardo pelas respostas!:[/color] :thumbup:
Obrigado a todos que estão ajudando e somente acompanhando o andamento do tópico, agradeço muito!

71C4700

Algo que venho pensando ultimamente é sobre o que realmente é o Model, no padrão MVC.

A ideia é desacoplar as camadas, ou seja, deixar as responsabilidades comuns juntas.

No entanto, Model poderia se tratar tanto de dominio de aplicação (beans/POJOs), quanto da lógica da aplicação(PessoaService).

Se Pararmos para refletir, devemos separar lógica de aplicação das Visões e dos Controladores, mas separar o modelo da aplicação das Visões é um pouco que paranoico…rsrs. Pois as visões devem refletir o dominio o qual busca captar e exibir os dados.

Partindo deste ponto de vista, teriamos um MVC, onde, agora sim, os papeis fazem sentidos em minha cabeça, onde, a visão fica responsavel por exibir/captar dados do usuario, o controlador responsavel por captar os eventos e determinar quem executará esta operação no modelo, e o modelo seria apenas a logica de negocio da aplicação. Sim! E os beans?! Esses sim estariam disponiveis para todas as camadas do MVC, por teoricamente não pertencer a nenhuma delas.

A grande coisa, penso eu, é que desta forma temos sim um sistema desacoplado tanto para um sistema Web quando Desktop, e podemos modificar somente as Vvisões e o sistema continuará a funcionar, lógico fazendo alguma alteração nos controladores, pois as requisições e captura de eventos nos paradigmas de desenvolvimento são diferentes. Mas no geral, ficaria desacoplado e teriamos um sistema de facil manutenibilidade.

Uffa…Acho que é essa minha humilde opinião. Lógico, gostaria de descutir isso tambem pois foi algo que como falei antes, é algo que venho pensando ultimante e futuramente no momento de projeto tentaria aplicar em projetos reais para ver o desempenho na fase de manutenção!

Att…

pedromuyala

Olá Maior, obrigado por responder, continuar acompanhando e me desculpe pela demora em responder! :smiley:

Eu andei lendo sobre o MVC2 (model 2) e realmente é o que eles fazem. O controle é quem assume o papel de mudar a JSP. :smiley:
O que dá impressão no Desktop ao me parecer é que os eventos lançados do modelo para a visão é que levam a própria visão a decidir o que deverá ser mostrado, ou seja, reenderizar a página atual ou trocar de página e reenderizar uma nova. CONTUDO, se reparar no esquema do MVC da própria SUN (Ver imagem em anexo no primeiro post desta página, a 11) eles dizem que o poder de trocar a visão é do controlador “seleciona a view”. Mas sabe o que eu ponho em dúvida sobre esse esquema é o seguinte:

Imagine que a pessoa que mexe na visão digita um determinado dado que quando chega na visão ele gera uma exceção. Como o modelo não fala (não conhece) o controle, imaginamos que o controle vai trocar a visão sem saber se ocorreu uma exception ou não. Olha que situação catastrófica: Vai aparecer para o usuário uma tela dizendo “OK, opção aceita!” mas na verdade a opção foi é uma Exception! :twisted: Mais uma do capeta! Isso até foi discutido com o Bruno Laturner em posts anteriores. O problema foi solucionado, porém o controle não assumia a troca da visão. Na ocasião, ninguém mais assumiu troca (ficou indefinido quem troca a visão). :shock:

Por isso eu acreditei na idéia de quando o Model gerar o evento para a visão de que tudo correu bem então ela mesma (Vamos entender assim: A camada da visão) trocava a sua visão. O que acha?? :roll:

pedromuyala

Olá 71C4700, muitíssimo obrigado por continuar aqui conosco! :smiley:

71C4700:
Algo que venho pensando ultimamente é sobre o que realmente é o Model, no padrão MVC.

A ideia é desacoplar as camadas, ou seja, deixar as responsabilidades comuns juntas.

No entanto, Model poderia se tratar tanto de dominio de aplicação (beans/POJOs), quanto da lógica da aplicação(PessoaService).

Se Pararmos para refletir, devemos separar lógica de aplicação das Visões e dos Controladores, mas separar o modelo da aplicação das Visões é um pouco que paranoico…rsrs. Pois as visões devem refletir o dominio o qual busca captar e exibir os dados.

Partindo deste ponto de vista, teriamos um MVC, onde, agora sim, os papeis fazem sentidos em minha cabeça, onde, a visão fica responsavel por exibir/captar dados do usuario, o controlador responsavel por captar os eventos e determinar quem executará esta operação no modelo, e o modelo seria apenas a logica de negocio da aplicação. Sim! E os beans?! Esses sim estariam disponiveis para todas as camadas do MVC, por teoricamente não pertencer a nenhuma delas.

A grande coisa, penso eu, é que desta forma temos sim um sistema desacoplado tanto para um sistema Web quando Desktop, e podemos modificar somente as Vvisões e o sistema continuará a funcionar, lógico fazendo alguma alteração nos controladores, pois as requisições e captura de eventos nos paradigmas de desenvolvimento são diferentes. Mas no geral, ficaria desacoplado e teriamos um sistema de facil manutenibilidade.

Uffa…Acho que é essa minha humilde opinião. Lógico, gostaria de descutir isso tambem pois foi algo que como falei antes, é algo que venho pensando ultimante e futuramente no momento de projeto tentaria aplicar em projetos reais para ver o desempenho na fase de manutenção!

Att…

Legal a postagem o conceito está certinho, é esse mesmo. :smiley:
Quanto aos beans estarem soltos para todas as camadas tenho dúvidas no quesito manutenção. Imagine se for alterado um desses beans o estrago estaria feito! :cry:
Mas mesmo assim eu gostei da idéia parece estar bem fácil de entender… gostaria que falasse mais sobre ela: Como a visão irá lançar os eventos ao controle? O Observer vai, via source do evento, levar o bean até a visão ou ele será agregado a ela? Quem vai trocar a visão, por exemplo, após digitar alguns valores e esse ser validado pela lógica de negócio mudar a tela avisando o usuário que os dados foram digitados com sucesso?

[size=16]Fico no aguardo pelas respostas, muito legal![/size] :smiley:
Não tenha pressa em responder o legal é pensarmos em uma coisa real de realizar usando o conceito já existente.
Volto agradecer a paciência de todos os companheiro gujeiros. Estou tentando realizar um trabalho na questão de vincular outros tópicos a este para evitar que a comunidade fique tendo que repetir a mesma coisa em vários tópicos. Espero estar junto com todos colaborando para que o melhor possível seja realizado aqui no fórum GUJ. Um abraço. :wink:

Felagund

acredito que o ideal para desenvolver MVC em desktop, pelo menos foi a abordagem que achei melhor durante o desenvolvimento de aplicações, foi utilizar listener e interfaces para simular esse MVC.

até investiguei o MVP, porem os exemplos ensinavam de forma errada, mantendo referencia circular dos objetos no sistema, ou seja, existiam objetos que nunca morriam (leia-se coletados pelo GC), e aos poucos isso tornava a aplicação lenta.

Porém com alguns ajustes conseguimos tornar a aplicação flexivel, nos aproveitando de listeners e interfaces.

Por que separei listener de interface, um listener extende normalmente a EventListener, que é a base para o Swing.

O que acontece, foi que defimos uma classe básica que extende a JFrame e implementa diversas funcionalidades padrões do sistema, logico que usando um pouco de Convension over Configuration. Todas as telas extendem dessa classe.
E os Controllers também derivam de uma classe que contem metodos comuns que podem ser sobrescritos, e metodos auxiliares para ajustes no codigo. E o listener, a interface que contem os metodos publicos do controller para a view poder chamar. A view conhece unica e exclusivamente o listener. E o controller nem faz ideia de quem ele manipula, somente durante a chamada a tela é passada como source do EventObject, ou seja, ao final do metodo o Controller perde a referencia dessa classe liberando assim ela da memoria. Lógico que existem também o padrão observer, que utilizamos para fazer comunicação entre as telas. e funciona muito bem.

Lógico que esse é um exemplo bem simples, mas na minha visão o MVC pra um pode não ser MVC para outro. O ponto de vista é muito importante.

[]’ s

marcio0

pedromuyala:
Legal a postagem o conceito está certinho, é esse mesmo. :smiley:
Quanto aos beans estarem soltos para todas as camadas tenho dúvidas no quesito manutenção. Imagine se for alterado um desses beans o estrago estaria feito! :cry:
Mas mesmo assim eu gostei da idéia parece estar bem fácil de entender… gostaria que falasse mais sobre ela: Como a visão irá lançar os eventos ao controle? O Observer vai, via source do evento, levar o bean até a visão ou ele será agregado a ela? Quem vai trocar a visão, por exemplo, após digitar alguns valores e esse ser validado pela lógica de negócio mudar a tela avisando o usuário que os dados foram digitados com sucesso?

Se você precisa que mais de uma visão saiba da alteração de um objeto, talvez você deva usar o padrão publish-subscribe, notificando as telas e mandando elas se atualizarem com o valor.
A visão não precisa “lançar” os eventos, ela pode identificar qual é a requisição e chamar um metodo apropriado no controle. Se for o caso, um objeto será retornado.

Na visão:

Usuario user  = new Usuario( .. ); //Instancia o objeto passando os dados recebidos pelo evento
controle.cadastrarUsuario( user );
user = controle.obterUsuario( txtId.getText() );
txtNome.setText(user.getNome());

A troca de visão pode depender do seu contexto. Acho que haverá casos que tanto faz a visão chamar a próxima visão ou o controle fazer a troca. Até porque, existe programação errada, mas não existe “A” programação certa. Se funciona, está de acordo com os requisitos, e você não está quebrando padrões ou convenções, está certo.

pedromuyala

Olá Felagund e Marcio, obrigado por participarem/acompanharem o tópico! :smiley:
Estou respondendo com menor agilidade seguindo recomendações via MP dos companheiros para não dar impressão de estar forçando a resposta!

Então gostei muito, muito mesmo de todas as colaborações de todos os companheiros gujeiros que estiveram conosco participando, somente lendo ou criticando. :smiley:
A atenção que cada companheiro disponibilizou do seu tempo aqui é um carinho que vale muito mais que qualquer coisa que podemos imaginar. :smiley:

Mas preciso dizer uma coisa que andou ocorrendo aqui no fórum em diversos tópicos sobre MVC: Parece que existe uma (com desculpa da palavra) eterna confusão entre MVC e Camadas (tanto Tier quanto Layer) para alguns companheiros. Preciso assumir a todos que eu mesmo acreditava no MVC sendo uma arquitetura ideal para construção de um sistema independentemente do que seria desenvolvido mesmo lendo artigos de pessoas conceituadas com vaga experiência profissional. :frowning:

Mas a essa altura e lendo as respostas nos diversos links relacionados na primeira postagem desse tópico ficou bem claro que não é bem esse o objetivo do MVC. Na verdade aprendi que um sistema deve ser desenvolvido em Layer’s (para não dizer camadas e novamente tornar ambíguo com camadas físicas) e o MVC pode estar presente em uma Layer (Ex: MVC na Apresentação) ou em várias Layer’s individualmente (Ex: 1 MVC na Apresentação e 1 MVC no Cliente) ou seja MVC’s independentes. Não existe UM MVC para duas, três, n Layer’s. O que existe é uma Layer onde pode ser aplicado o MVC mas não um MVC formado por várias Layer’s, agora estou certo? :roll:

[size=16]Portanto se isso que acabei de escrever tiver procedência real gostaria que fosse discutido então como funciona o MVC dentro de uma Layer.[/size]
Espero que agora sim as coisas comecem a fazer sentido na minha mente e pare de causar esse enorme desconforto entre os companheiros.

Preciso frizar uma coisa que já disse em tópicos anteriores: Eu estou aqui é para aprender, eu gosto dessa comunidade, gosto das pessoas que aqui participam e não tenho interesse nenhum por trás de tantas perguntas. O único interesse que tenho é igual a esse aí que acabei de escrever: Ajudar as pessoas, assim como a mim mesmo, a acabar com esses tipos de dúvidas que levam nossos amigos a eternas síndromes de confusão. E outra coisa que preciso frizar é para aqueles que acham que eu só quero audiência ao meu tópico. :x Eu prefiro que meu tópico tenha 1000 respostas e 1000 visitas do que ter 50 mil visitas e nenhuma resposta.

[color=blue]Só posso desejar felicidades a todos e muita saúde.
Espero pelas respostas, um abraço![/color] :wink:

Andre_Fonseca

Oi Pedro

Vamos lá então, deixa eu tentar colocar a minha opinião :slight_smile:

At first glance, the three tiers may seem similar to the MVC (Model View Controller) concept; however, topologically they are different. A fundamental rule in a three-tier architecture is the client tier never communicates directly with the data tier; in a three-tier model all communication must pass through the middleware tier. Conceptually the three-tier architecture is linear. However, the MVC architecture is triangular: the View sends updates to the Controller, the Controller updates the Model, and the View gets updated directly from the Model.

Ou seja, a separação física das camadas (tiers) diz que elas se comunicam linearmente. No exemplo de uma aplicação web você poderia dizer que o browser do cliente é uma camada, o application server onde fica a lógica de negócio é outra camada e o banco de dados é outra camada…

Essas seriam as camadas físicas do seu sistema

Já com relação a separação em camadas lógicas você poderia considerar que teriamos a tal separação de responsabilidades. O seu view irá enviar os inputs de dados para o seu controller, que irá atualizar o seu banco de dados e o seu view irá consultar (ou será avisado) pelo controller quando alguma alteração ocorrer

A grosso modo separar em camadas físicas significa que eu posso ir lá e arrancar pedaço do código, ou por exemplo, se o seu banco de dados cair uma camada vai junto.
Já separar logicamente significa que cada camada tem uma responsabilidade bem definida, e no caso de ela não ser mais suficiente você pode simplesmente substituir este pedaço da sua aplicação por outro pedaço que tem a mesma responsabilidade.

Se tiver tempo dê uma lida também nos artigos abaixo

pedromuyala

Olá André, puxa obrigadão por continuar participando! :smiley:

Entendi direitinho cara a explicação. E acredito que a sua intensão foi me dizer, a princípio, para que eu estude Camadas, não é?

Até porque do jeito que você descreveu as camadas lógicas é exatamente o que eu preciso! Uma visão que envia dados ao seu controlador e realiza a persistência em banco de dados. Após isso a visão é avisada para se atualizar (e o Observer eu aprendi também em um link que você indicou :D) Se em um modelo de camadas lógicas essas responsabilidades ficam definidas, é o que eu realmente procuro. E também entendi as camadas físicas, muito legal!

Poxa você sempre que pode me “destrava” em problemas enrolados. Acho que tem competência o suficiente para ser um moderador do GUJ, espero que leiam isso! :-o

Obrigado mais uma vez, fico no aguardo pela resposta!

sergiotaborda

Sim.


Portanto se isso que acabei de escrever tiver procedência real gostaria que fosse discutido então como funciona o MVC dentro de uma Layer.

Todo o sistema que trabalha com informação ( e aqui se incluem até sistemas fisicos e quimicos) precisa de input e output.
Isto é essencial e obvio. Cada andar (layer) precisa destas coisas. Mas cada andar está empilhado em outros andares.
Isso significa que existe um input vindo de cima, um output indo para baixo e de volta.

cima ---> andar ---- > baixo <---- <-----

OO diz que objetos devem ter responsabilidade unicas e separadas então a primeira coisa a fazer é criar dois objetos
um para a comunicação “acima” e outro para a comunicaão abaixo

cima <—> [ A … B] <—> baixo

“A” será responsável por tratar o input de cima. Traduzi-lo para algo enterpretável pelo andar , isso será tratado e passado a B que traduzirá para o andar de baixo. B traduzirá a resposta de volta e A de volta ao andar de cima. Hum… será trtado por quem ?
PRecisamos deum terceiro objeto C, que fará o tratamento.

cima <—> [ A <–> C <–> B] <—> baixo

Esta é o design padrão de um andar. Agora imaginemos que este andar responde directamente ao usuário ou os comandos do usuário : teclas, mouse, etc… “A” estará disposto a responder a coisas como “usuario clicou em X” Este é o input que A recebe.
Mas não existe hora marcada para isso. Então entra o conceito de Evento. Algo acontece. Quando acontece isso desencadeia as chamadas aos andares de baixo. “A” é “activado” por um evento. Mas o evento é algo assincrono. Outro evento pode imediatamente seguir-se a esse. Um deslocar de mouse geram N eventos em pouco tempo. Então A não pode esperar pela resposta de C porque já precisa ficar disponivel para enviar outro evento. Esta cadeia de eventos força um processo assincrono em que a resposta não chega imediatamente. Mas quando ela chegar , A tem que ser informado. E quem sabe quando ela chega? O cada da outra ponta, B. Então a mecanica de eventos força uma separação

A ---> C --> B -- | ^ | |---------------

É um triangulo. A invoca C que invoca B que invoca A mas nunca a informação volta para quem chamou.
É deste triangulo que nasce o MVC.
M = modelo, é o nome de B. V = View é o nome de A e C = controler é o nome de C.

A view recebe o input e fornece o output ao andar superior. Model fornece o input e recebe o output do andar inferior. C controla o fluxo. Ele pode não chamar B e simplesmente enviar um evento a A, em nome de B.

Isto é o padrão. A implementação são outros 500.
Dependendo do propósito a implementação pode ser complexa ou não.

Não ha receita de como seria a implementação. O ponto é que se for no padrão MVC ela respeita certas regras de separação de responsabilidade. Mas lembre-se que MVC presupoe o uso de eventos. Deveria ser o padrão MVCE. Mas o que é um evento na relalidade ? como se implementa um ?

Em java isso é transparente. É a chamada a um método. Só que assim, não ha diferença entre um método-evento e um método normal. Pois. E por isso que é tão util e interessante, e simples em java trabalhar com eventos. Em outras linguagens um construto diferente de “método” é necessário para representar o evento.

É preciso tb deixar claro que MVC podem ser 3 objetos ou 1000 objetos. O M , o V e o C podem utilizar quandos objetos de tipos diferentes forem necessários. Normalmente uma implementação MVC é componentizada e cada componente assume um dos papeis do MVC. Como disse, a implementação pode ser simples ou complexa.

pedromuyala

Olá pessoal, é o Pedro, [color=red]estou de volta[/color]! Depois de passar por alguns sérios problemas acredito estar são e salvo! 8)
Muito bom estar devolta com todos, é muito bom estar aqui! :smiley: :smiley: :smiley:
Infelizmente não vou poder, até este momento, conectar na Internet no meu horário de serviço que agora está proibído. :roll: (troquei de emprego :frowning: )

Hoje vou atender um pedido de alguém que me procurou via mensagem privada. Prometi ilustrar a explicação do Sergio Taborda acima para que fique bem visível a quem esteja com dificuldade para enxergar algumas arquiteturas de software. Óbvio quero deixar bem claro aqui que estou confiando na explicação do Taborda. Não estou de forma alguma julgando estar correta ou errada…
Muito menos se entendi certo ou errado, caso percebam que estou cometendo um delito aos programadores, por favor, não deixem de postar a opinião aí embaixo, pelo amor de Deus! :shock: kkkkk…

Isso ilustra bem o que foi dito na mensagem anterior. SE ESTIVER ALGO QUE JULGUEM INVÁLIDO, ERRONEO, RIDÍCULO… por favor comentem aí abaixo! :idea:

:arrow: Estou anexando a imagem também para quem quiser ver em alta resolução, ok?

[size=16]E é isso amigos companheiros Gujeiros![/size]
[color=orange]Espero dessa vez manter uma estabilidade aqui com vocês![/color]
Um forte abraço para todos, estamos juntos!


I

Olá Pedro, obrigada por estar se preocupando em me ajudar!

Deixa eu fazer uma obs rápida: Atualiza sua primeira postagem no tópico que a última atualização que fez foi em 2009 hihihihihi…

Então, infelizmente eu tentei ler todo o tópico mas como é muito grande e lá mais para o meio chega a ser “confuso”, me limitei em ler apenas as 4 últimas páginas…
Mas acredito que fiz certo pois a dúvida está alí mesmo nas últimas postagens. E é Desktop como está no título porque de JAVA WEB eu nem conheço!

Vamos ver se captei a ídeia, mesmo já sabendo disso (estudei sobre arquitetura em alguns sites da Internet): O que você quer passar é que Camadas e MVC são duas coisas parecidas, porém distintas, conforme mostrou na imagem que criou para mim (q lindo, muito obrigada, adorei!!!), certo? Que dentro de um andar existe uma arquitetura MVC mas que não existe dentro de um MVC vários andares, certo?

Olhando a explicação anterior (do Sergio) a imagem está representando 100% o que foi dito.

Então o que me confunde é exatamente isso: Sabemos bem que arquitetura é abstrata. No meu caso eu quero criar uma Agenda para guardar os dados das pessoas que conheço para futuramente me comunicar com elas. Para que eu siga esse desenho de arquitetura mostrado na imagem, como teria que dividir minhas classes para que fique de acordo?

  • Apresentação: Seriam as telas exibidas ao usuário? (De cadastro, de confirmação de cadastro, de alteração, de consulta,…)???
  • Negócios: Seriam as regras de negócios e validações? (Não pode cadastrar pessoa duplicada, obrigatório informar um ou mais telefones, e-mail deve conter “@”,…)???
  • Dados: Seria o Crud para persistir em bando de dados?

Outra coisa você usa MVC na camada de negócios (que está com o sinal de “-”). As outras que estão com o sinal de “+” contém a mesma hierarquia?
Obrigada por atender meu pedido via MP, muito legal sua atenção em se preoucpar em ajudar! :smiley:
Parabéns pelo Português você também tenta escrever bem legível… fica mais fácil entender. :oops:

pedromuyala

Magina moça não precisa agradecer! Espero poder ajudar, só isso.

Pedido atendido, está atualizado.

Então é isso mesmo, se nós, claro, não estivermos errados. MVC, conforme desenhei, está presente internamente na camada. Uma camada de nome CAM tem um input (visão), um output (modelo) e um centro de processamento (controle). Tendo isso em mente, lá vai:

  • CAM recebe dados de uma camada superior através do seu input que nada mais é que a visão (podendo ser humana ou não);
  • Visão, então, pela convenção de eventos, lança um evento ao controle;
  • Controle que está escutando a visão recebe o evento e o processa de forma legível para a aplicação;
  • Controle, neste momento pode tomar duas decisões: fazer alteração no modelo ou responder diretamente a visão;

— Então, uma breve pausa no processamento acima para lembrar um detalhe importante: Na convenção de eventos em que um evento pode acontecer a “qualquer instante” o controlador precisa estar sempre livre para receber novos eventos e processa-los, sendo que não pode ficar aguardando uma resposta do modelo o qual, atráves de eventos também, se comunica-rá diretamente com a visão para reenderiza-la. (Caso tenha dúvidas sobre eventos, estudar o pattern Observer) Continuando…

  • Se controle optar em responder diretamente a visão, ela receberá a resposta e exibirá ela (pode ser para um humano ou não);
  • Se controle optar em alterar o modelo, então passará os dados a ele;
  • O modelo poderá enviar dados a uma camada inferior e receber dados dela;
  • Se o modelo for alterado, a visão será notificada.

Pronto… Ufa! Acho que consegui explicar!

ingridfarabulini:
Então o que me confunde é exatamente isso: Sabemos bem que arquitetura é abstrata. No meu caso eu quero criar uma Agenda para guardar os dados das pessoas que conheço para futuramente me comunicar com elas. Para que eu siga esse desenho de arquitetura mostrado na imagem, como teria que dividir minhas classes para que fique de acordo?

  • Apresentação: Seriam as telas exibidas ao usuário? (De cadastro, de confirmação de cadastro, de alteração, de consulta,…)???
  • Negócios: Seriam as regras de negócios e validações? (Não pode cadastrar pessoa duplicada, obrigatório informar um ou mais telefones, e-mail deve conter “@”,…)???
  • Dados: Seria o Crud para persistir em bando de dados?

Cada camada vai ter o M-V-C. No caso da imagem acima, o MVC está presente de forma visual na Camada de Negócios. Mas ele poderia estar em qualquer uma delas, nas três ou em nenhuma.
Suas classe devem ser criadas de acordo a camada. No caso de uma agenda, como cita de exemplo, a camada de apresentação teria como visão um formulário, um controle que receberá eventos do botão quando clicado e traduzirá ao modelo ou a própria visão e um modelo que executará as regras para aquele formulário. Se tudo estiver satisfeito, o modelo (domínio) da apresentação enviará os dados a visão da camada de negócios que acionará um evento ao controle que então chamará o modelo para verificar as regras de negócio que dessa vez são da agenda (não mais do formulário, como na camada de apresentação). Então, por fim o modelo enviará para a visão da camada de dados os dados necessários que lançará um evento para o controle que chamará o modelo e após tudo ok a informação é então persistida em BD e as respostas aos eventos lançados começam a ser devolvidas até chegarem novamente lá na camada superior. Pronto… Ufa 2!

Sim. como disse isso depende de como você quer implementar, não é obrigatório. Você poderia ter o MVC na camada de apresentação, somente.

Bem tudo respondido agora preciso fazer um [color=red][size=24]ALERTA!!![/size][/color] [size=18]Eu acredito que seja isso, com tudo que venho estudando e tentando entender, não estou afirmando nada que seja isso!!![/size] Posso aqui estar fazendo uma baita asneira daquelas se envergonhar até a sogra :oops: :oops: :oops:!!! Mas isso só saberemos mesmo nas próximas postagens dos companheiros Gujeiros que com certeza em breve começaram logo abaixo. E eu peço que por favor opinem mesmo porque se isso for um erro, no lugar de estar ajudando milhares de visitantes estarei é causando um desastre a eles!

[size=14][color=orange]Obrigadão a todos que continuam firmes e fortes conosco nesse mundo maravilhoso do JAVA!
Abração a todos, felicidades![/color][/size]

Lavieri

Só um adendo… o ideal é que o controle não tome decisões,

o ideal é o controle conhecer o fluxo, saber para onde enviar cada evento do sistema, mas não tomcar decisões…

O limiar desse conceito é bem dificil, pq é complicado ate de explicar o que seria tomar decisão ou não, afinal escolher o fluxo correto é um decisão…

Mas o que falo é que além de ifs, cases, e enums, sempre que possivel, o Controle deve delegar ao dominio a tomada de decisão, e com a decisão tomada o controle cuida de enviar o fluxo…

por exemplo

se vc quer checar se os dados estão corretos, parar só ai mandar o fluxo para o cadastro, vc não deve fazer o teste no controle, e sim delegar esse teste ao dominio, a lógica mesmo…

tipo

metodoControladorDeFluxo() { if(dominioValidados.isDadosValidosFor(pessoa)) { dominioCadastrador.cadastrar(pessoa); visaoProximoPasso.exibir(); } else visaoMostradoraDeErro.exibir("Dados inválidos"); }

I

Nossaaa! Eu estou entendendo tudo mas preciso me aprofundar nessa teoria estou entendendo mas muito superficialmente. :roll:
Vou digerir tudo isso tentando implementar a agenda e volto para postar se surgirem dúvidas…
Obrigada Pedro e Lavieri, você estão me ajudando muitooooo :smiley:

eberson_oliveira

ingridfarabulini:
Nossaaa! Eu estou entendendo tudo mas preciso me aprofundar nessa teoria estou entendendo mas muito superficialmente. :roll:
Vou digerir tudo isso tentando implementar a agenda e volto para postar se surgirem dúvidas…
Obrigada Pedro e Lavieri, você estão me ajudando muitooooo :smiley:
´

Olá,

Estive dando uma olhada no seu tópico anterior e, agora, neste… o que tenho a sugerir é que siga o que foi proposto pelo lavieri pensar na divisão de tarefas vai promover a alta coesão e, com os objetos conhecendo o mínimo possível sobre os demais você consegue atingir o baixo acoplamento… Assim, você conseguirá fazer com que seu sistema tenha maior qualidade no sentido da orientação a objetos.
No entanto, pelo que pude ver em suas mensagens… essa explicação toda pode ter te deixado meio confusa… tenho um link de um material que considero muito interessante e que pode ajudar a visualizar melhor a situação proposta pelos colegas do fórum:

http://javafree.uol.com.br/artigo/871446/Apresentando-ModelViewPresenter-o-MVC-focado-na-visualizacao

Este outro link vai ser bastante útil para que você entenda consiga contextualizar as soluções propostas com a evolução dos modelos

Espero ter ajudado
[]s

I

Olá Eberson…
Então pensando exatamente dessa forma que considerei a teoria do Sergio Taborda e a imagem representando ela feita pelo Pedro. Não que o Lavieri esteja sem razão, não não…
Se você notar, poderá perceber que na explicação existe uma alta coesão e um baixo acoplamento. Foca somente um andar lá… vai perceber que na verdade esse andar é um MVC com entrada, processamento e saída [IN-<>process<->OUT]. E porque do MVC dentro desse andar? Justamente para o baixo acoplamento acontecer entre as partes, que é justamente a convenção de eventos criada (note que onde há setas com tracinhos na imagem “---->” lê-se “lança um evento”.

Acredito que a teoria está correta… masssss… quem realmente poderia dizer se é certo ou não a imagem que estamos vendo seria o próprio Sérgio Taborda quem descreveu a teoria… vou ver se entro em contato com ele!

O que eu busco é bem isso aí acima mesmo. A sugestão dada pelo Lavieri no outro tópico é muito legal mas se essa agenda começar a aumentar? Tiver que colocar mais coisas como fotos, enviar um e-mail?? O agendinha passa a ser um agendão! Acredito que devo desde o início acreditar que essas coisas possam ocorrer… por isso quero fazer uma base legal antes de continuar… :shock: Nossa hoje falei demais!

Obrigada Eberson :smiley:

sergiotaborda

Antes demais queria agradecer o esforço de ter criado esse boneco. A minha unica sugestão é que o miolo mvc deveria aparecer na camada de apresentação porque é onde ele realmente é usado a esmagadora maioria das vezes. Um conceito pictorico é representar MVC como um triangulo para que não reste duvida de que não ha uma unica seqüência de eventos.

Realmente como foi dito o controlador não toma decisões de negocio. Isso é o model que faz ( por isso que ele tem comunicação com a camada abaixo).

O boneco da direita não entendi. Não ha relação entre MVC e os andares. O que foi representado com aquelas “salas” são andares, não camadas, nem mvc. ficou algo confuso objetivo dessa parte da imagem.

CRUD não é Dados, é Integração. são 5 camadas : Cliente, Apresentação, Negócios, Integração , Recursos (dados)

O MVC é para ser usado no Cliente e opcionalmente na Apresentação (em web se usa nos dois)

Mas no geral é isso mesmo. Parabéns por ter entendido.

P.S. Só para deixar claro

Cliente = telas , aspecto visual,ergonomia
Apresentação = apoio ao Cliente. Traduz o interno para o externo e de volta.
Negocio = as regras da aplicação (tb chamado Dominio)
integeração = onde estão os dados e como colocá-los fisicamente lá e depois recurperá-los (hibernate, jdbc , essas coisas) + As regras de persistencia (duplicados, indices, etc). Tb se inclui leitura de arquivos de propriedades, xml ou outros que aplicação necessite
Recursos = os dados em si. Arquivos, imagens, e o proprio SGDB.

Lavieri

ingridfarabulini:

O que eu busco é bem isso aí acima mesmo. A sugestão dada pelo Lavieri no outro tópico é muito legal mas se essa agenda começar a aumentar? Tiver que colocar mais coisas como fotos, enviar um e-mail?? O agendinha passa a ser um agendão! Acredito que devo desde o início acreditar que essas coisas possam ocorrer… por isso quero fazer uma base legal antes de continuar… :shock: Nossa hoje falei demais!

Obrigada Eberson :D

não me entenda mau ^^, minha sugestão é exatamente para vc pensar em um modelo como o exposto nesse topico… eu apenas exemplifiquei pequenos trechos de codigo, para que vc entendesse um pouco também do código do problema também.

pensar em sistema pequeno é falho, e o sergio enclusive tem um artigo falando justamente disso.

pedromuyala

Olá [color=blue]Sergio Taborda[/color], muitíssimo obrigado por continuar atento ao tópico mesmo depois de um bom tempo parado. Para mim, particularmente, é uma honra saber que está presente.

Não precisa agradecer absolutamente nada, se alguém tem que agradecer aqui sou eu pela sua presença.
[color=red]Fiquei curioso: Em um sistema Desktop, existe tanto a Camada de Cliente quanto a de Apresentação, ou seja, as duas?[/color]
Concordo quando fala em triângulo a arquitetura MVC. O boneco a direita-inferior representa isso.

É também dou razão a você e ao Lavieri também que logo de cara alertou esse problema. Infelizmente aí eu comi bola, bati na teoria. OBRIGADO POR AVISAREM!!! MUITO BOM.

[color=red]Não pode ser usado em nenhuma das outras 3 camadas? (Negócios, Integração e Recursos) Existem outras arquiteturas para tal?[/color]

[color=red]Fiquei confuso… :frowning: Como ficaria/seria, por exemplo, o sistema da agenda que a Ingrid quer criar usando essas camadas no JAVA SWING?[/color]
Lembrando claro que o próprio Sergio já fez uma explicação sobre MVC + Swing em um tópico anterior. Mas eu não consigo visualizar, como por exemplo, esse caso da agenda?

[size=14]Olha mais uma vez tenho que agradecer muito a boa vontade de todos que continuam aqui firmes acompanhando este tópico :smiley:
Volto a dizer que o GUJ proporciona um espaço mágico para as pessoas com excelentes profissionais atuando nas mais diversas áreas da computação.
Isso é um exemplo para toda a sociedade… pessoas buscando ajudar as outras, as encaminhando no melhor caminho. O mundo inteiro deveria ser assim… infelizmente não é. :frowning:
Mas são esses detalhes que fazem um mundo melhor!!! :smiley: :smiley: :smiley: Um dia todos nós chegaremos lá.[/size]

[size=16]Parabéns mais uma vez aos organizadores do GUJ e a todos os seus usuários que colaboram respondendo perguntas ou simplesmente dispondo do seu tempo para acompanhar o tópico. Fico no aguardo pelas respostas, felicidades a todos.[/size]

sergiotaborda

Olá Pedro.

Primeiro , tenha cuidado com o uso de cores. Vc meio que está violando a netiqueta. Para duvidas procure um moderador.

Pode, claro que pode. Mas normalmente não faz sentido nessas camadas. Lembre-se que o MVC existe para responder a eventos. Normalmente essas camadas não são guiadas por eventos. Mas teoricamente nada impede o seu uso. Apenas não é comum usar nessas camadas pq normalmente não encaixa.

Nenhuma das camadas é obrigatória, contudo é bom ter todas.
No caso do swing o cliente é o que vc monta com o swing. Vc engendra uma estrutura que media com o usuário, isso é o cliente.
Mas ai vc precisa que os seus models do swing conversem com o resto da aplicação. Essa tradução é feita na camada de apresentação.
É mais dificil ver a destinção e é mais ainda se não houver uma correta separação de responsabilidades entre as classes.

I

Olá rapazes…

Estava olhando bem para o desenho na postagem lá no alto e lí os posts seguintes e não entendi um detalhe: vamos dizer que o mvc esteja implementado no andar superior, e essa camada seja Cliente. Se eu clicar em um JButton na verdade quem está se comunicando com a camada de apresentação é o controle e não o modelo do JButton, não é ? O actionListener vai chamar um método do andar inferior… mas não o model quem irá chamar.

Mais um detalhe: essas setas pretas de duplo sentido (vai-e-vem) nomeadas IN/OUT seria uma comunicação por eventos? Pergunto porque se se estiver duas telas abertas que representem o mesmo domínio e uma delas altrar algo, ambas devem imediatamente refletir seu modelo… senão isso não aconteceria, acho. :?

Obrigada! :smiley:

Lavieri

JButton segue um padrao observer para comunicar o evento, entao ele em si, nao e’ acoplado a quem estiver o escutando…

e’ igual um radio… o cara transmite a onda de radio, quem esta escutando ou nao, nao e’ responsabilidade da estacao de radio, ela so envia o sinal… a pessoa que quer ouvir que tem q sintonizar na radio para escutar … nao existe acoplamento entre entre a Estacao de Radio e quem a escuta…

Observer e’ um padrao na mesma linha… o controle que sintoniza para escutar os eventos do botao… portanto… o controle que tem q saber o botao que ele quer ouvir, se colocar como ouvinto do botao, adicionando ao botao um ActionListener

Assim o botao nao se importa de quem o escuta… toda vez que ele precisa informar o evento, ele simplismente vai gerar um evento, e quem estiver sintonizado em sua estacao, ou seja, em sua lista de listeners, vai escutar esse evento…

Lavieri

Para entender o desacoplamento desse padrao...

public class Mensageiro {
      public Mensageiro(Receptor receptor) { //forte acoplamento
            this.receptor = receptor;
      }

      public void fazAlgo() {
             receptor.aviso("eu fiz algo"); //forte acoplamento, eu conheco quem estou enviado a msg
       }
}

Agora com baixo acoplamento, usando observer

public class Mensageiro {
      private Set<Receptor> receptores = new HashSet<Receptor>();
      public Mensageiro() {}
       
      public void addObserver(Receptor receptor) { receptores.add(receptor);}
      public void removeObserver(Receptor receptor) { receptores.remove(receptor);}
      
      private void avisa(String msg) {
           for(Receptor receptor : receptores) receptor.aviso(msg);
      }

      public void fazAlgo() {
           avisa("eu fiz algo"); //BAIXO ACOPLAMENTO
           //aqui vc esta avisando... mas nao faz a menor ideia de a quem...
           //simplismente qualquer um sintonizado na sua estacao, ou seja, 
           //adicionando a lista de repectores, vai receber o aviso
      }
}
public interface Recptor {
      void aviso(String aviso);
}
pedromuyala

Olá Sergio, obrigado por responder as perguntas e continuar atento ao tópico, fico muito feliz!

Com certeza vou seguir sua recomendação… realmente fui infeliz em querer destacar as perguntas de vermelho. Fico triste pelo erro. :frowning:
Mas foi bom ter chamado a atenção, até lí sobre “netiqueta” no Wikipédia. Muito legal, não conhecia! :slight_smile: Obrigado pela dica :wink:
Peço desculpas pelo transtorno… evitarei ao máximo! Gosto muito da comunidade, espero não prejudicar!

Não há dúvidas que o conceito está bem claro para mim. Que coisa, acho que agora estou conseguindo entender definitivamente seu raciocínio…
Mesmo assim, ainda preciso fazer três perguntinhas:

  1. É normal o modelo ter uma coleção de Listener’s que possa registrar as visões que implementarão esse mesmo Listener e passarão a receber eventos de “notificação de alteração” do modelo?
  2. É normal a visão ter uma coleção de Listener’s que possa registrar os controladores que implementarão esse mesmo Listener e passarão a receber os eventos de “user gestures (Ex: Click’s,etc…)” da visão?
  3. Vários controladores podem escutar a visão assim como várias visões podem escutar o modelo (desde que se registrem como ouvintes)?

Obrigadão a todos que estão acompanhando! Espero pela resposta companheiros!

Lavieri

pedromuyala:

  1. É normal o modelo ter uma coleção de Listener’s que possa registrar as visões que implementarão esse mesmo Listener e passarão a receber eventos de “notificação de alteração” do modelo?

Eu entendo que não, eu não faria assim, no meu entender o normal, é o controle implementar esses entityListener, de forma a repassar corretamente para a visão… A Visão não deve estar acoplada ao modelo.

pedromuyala:
2) É normal a visão ter uma coleção de Listener’s que possa registrar os controladores que implementarão esse mesmo Listener e passarão a receber os eventos de “user gestures (Ex: Click’s,etc…)” da visão?
Eu entende que sim, o controle escuta a visão, de forma a encaminhas os eventos para o local correto do modelo.

pedromuyala:
3) Vários controladores podem escutar a visão assim como várias visões podem escutar o modelo (desde que se registrem como ouvintes)?
Varios controles podem escutar a visão sim…

O Ideal é que a visão não escute o modelo (na minha opinião claro) e sim o controle, que faria então a intermediação,

o que entendo que a visão conhece diretamente do modelo são no maximo as entidades, ou seja ele pode conhecer uma informação, e exibir ela na tela.

essa é a opinião que tenho

sergiotaborda

Sim é normal.
Conceptualmente a visão que se registra no model para este a avise quando mudar. Se não fosse assim, como a visão saberia que o modelo mudou?

Não. Cada visão tem apenas um controlador. Ela repasse os eventos sempre ao mesmo controlador.
O que pode acontecer é mudar a visão associada ao controlador. Mas num dado momento só existe uma associada ( No swing a visão é o look&feel, só existe um por componente num dado momento. o componente é o controlador)

Não. Várias visões ouvem o mesmo modelo Mas cada visão só tem um controlador e cada controlador só tem uma visão e um modelo.
O que pode acotecer é que o controlador A está ligado ao mesmo modelo que o controlador B.

I

Lavieri:
pedromuyala:

  1. É normal o modelo ter uma coleção de Listener’s que possa registrar as visões que implementarão esse mesmo Listener e passarão a receber eventos de “notificação de alteração” do modelo?

Eu entendo que não, eu não faria assim, no meu entender o normal, é o controle implementar esses entityListener, de forma a repassar corretamente para a visão… A Visão não deve estar acoplada ao modelo.

pedromuyala:
2) É normal a visão ter uma coleção de Listener’s que possa registrar os controladores que implementarão esse mesmo Listener e passarão a receber os eventos de “user gestures (Ex: Click’s,etc…)” da visão?
Eu entende que sim, o controle escuta a visão, de forma a encaminhas os eventos para o local correto do modelo.

pedromuyala:
3) Vários controladores podem escutar a visão assim como várias visões podem escutar o modelo (desde que se registrem como ouvintes)?
Varios controles podem escutar a visão sim…

O Ideal é que a visão não escute o modelo (na minha opinião claro) e sim o controle, que faria então a intermediação,

o que entendo que a visão conhece diretamente do modelo são no maximo as entidades, ou seja ele pode conhecer uma informação, e exibir ela na tela.

essa é a opinião que tenho

Olá lavieri ,

Isso que está parecendo ser MVP, não? Esse controle não seria um presenter?

Olá Sergio,

Então o controle e a visão se comunicam diretamente [1 para 1] assim como o controle se comunica diretamente com o modelo [1 para 1].
Porque a visão lança “eventos” para o controle ao invés de chamar um método diretamente do controle, como control.somaUm(); ?
Não é necessário usar o padrão Observer entre visão e controle?

Obrigada! :smiley:

sergiotaborda

Para responder a isso temos que entender primeiro o conceito de mensagem OO.
Na realidade pura os componentes mvc comunicam via o envio de mensagens.
A questão é que existem duas formas de enviar mensagens de um objeto para o outro.

  1. chamar métodos no outro objeto (mecanismo sincrono)
  2. o padrão Observer (mecanismo assincrono)

A comunicação entre a visão e o controlador é por eventos porque a interação do cliente com a view é assincrona não porque ha mais do que um ouvinte.

Se vc imaginar que a view do JTable apenas aciona comandos relacionados ao JTable ( cellClick, por exemplo) faz sentido.
Só que, em UI um outro padrão bom de usar é Composite Object.

Quando vc compoe os objetos numa estrutura semelhante a uma arvore, vc tem a capacidade de interceptar os eventos antes que cheguem no componente. É por exemplo o papel do GlassPane. Porque existe este mecanismo de intercepção precisamos de um mecanismo de eventos.

Portanto, da view para o componente vamos de lançamento de eventos assincrono para tirar partido do assincronismo (o componente só responde quando algo acontece com ele) e da composição.

A cardinalidade (1-1) não está diretamente relacionada ao padrão Observer. Vc pode usar observer mesmo quando é 1-1, a diferença é que quando é 1-n , vc só pode usar observer.

Da mesma forma que não faz sentido uma view mandar comandos a mais que um controlador, tb não faz sentido um controlador ter mais que um modelo. Mas aqui, nada nos impede de ter controladores diferentes baseados no mesmo modelo. Por exemplo, é comum que a mesma action de um botão da toolbar seja tb a action do item de menu que faz a mesma coisa. A representação mudou, mas o modelo não.

Do modelo para a view, a ligação é com eventos por causa, mais uma vez , do assincronismo não da cardinalidade. Quando o modelo muda, por causa da logica do sistema ( por exemplo, outro utilizador adicionou mais um item na lista) o modelo indica à view que mudou. Isto é equivalente ao usuário dar um comando quando ele sabe que os dados mudaram, o problema é que ele não tem como saber isso. então o próprio modelo avisa a view para dar um “refresh”.

O conceito é : o uso do padrão observer deve-se à necessidade de assincronismo , e nada tem que ver com a cardinalidade.

View <- 1 — 1-> Controlador <-----1-> Model <-1—-> View

outra forma de ver é que as consultas são feita sincronamente, portanto quando o view pega os dados do model só pode ser 1 model porque a chamada é sincrona. Quando o controlador comanda o modelo, é síncrono, portanto tem que ser 1 modelo.

pedromuyala

Fala companheiros, boa noite! :smiley:

Poxa muito legal essa última explicação postada pelo Sergio em resposta a Ingrid, bem legal mesmo. Além que eu já havia perguntado isso em uma postagem anterior e ele mesmo havia respondido mas agora sanou de vez qualquer dúvida, parabéns! :wink: Também quero agradecer por ter respondido as minhas perguntinhas antes de tudo isso! :lol:

Poxa, posso estar enganado, ou melhor, acredito estar sim… mas a pergunta da Ingrid me pareceu bem inteligente para acrescentar mais um conceito a explicação: Acoplamento/Desacoplamento de sistema. Segundo estudos no passado, o Observer é uma forma de desacoplar as partes, certo?

Então pergunto, aproveitando o embalo: O Sergio já explicou que a cardinalidade nada quer dizer com relação ao uso do design pattern Observer.
Se for pensar em desacoplar as partes, então o que é mais desacoplado no MVC: Chamar diretamente o método de outra classe (visão chama métodos diretamente do controle) ou usar o Observer, mesmo que seja síncrono?

O que estou imaginando é o seguinte, lembrando que os conceitos são uma abstração: (imaginando que estou desenvolvendo um sistema que ao apertar o botão aumenta 1 no valor)

  • A camada de Cliente fica definida como sendo composta por três classes: V.class, C.class e M.class
  • V é a Visão; C é o Controlador e M o Modelo.
  • V é um JFrame com um JPanel que possui um JButton.
  • C possui métodos que alteram M.
  • M possui um atributo int e um método que soma 1 a esse atributo quando chamado.

Tendo isso em mente…
Implemento Observer para V enviar eventos à C (que nesse caso só pode ser o clique no botão) e outro Observer para a M notificar V? ou
Faço V chamar métodos de C diretamente e implemento Observer para M notificar V? ou
Continuo com graves problemas em entender corretamente o conceito de Camadas e MVC portanto recomendaria, como disse anteriormente, mudar de ramo e abrir um Pet Shop? :oops:

Fico no aguardo guerreiros companheiros!
Muito obrigado por dispor seu tempo ajudando ou simplesmente lendo as postagens. Para mim, é uma honra.

I

Olá Sergio :smiley:

Entendi o conceito… ficou bem explicadinho.

Você esta perguntando em aplicar o Observer para desacoplar o trio MVC ? Essa eu também quero saber kkkk… :?:

Eu acho que está certo sim a sua divisão, acho :!: E também acho que o certo é
Faço V chamar métodos de C diretamente e implemento Observer para M notificar V? ou

Mas é melhor você aguardar as repostas dos outros porque eu ACHO…

Obrigada :smiley:

pedromuyala

Olá Ingrid!
Não precisa agradecer, eu quem agradeço pela ajuda!

Opa acredito na sua opinião… é muito importante!
Também acredito que é essa a ideia… mas como você mesmo sugere, vou continuar no aguardo a pergunta que fiz aí dois post’s acima e ver se o pessoal tem outra visão diferente da nossa.

Sei lá… sinceramente acho que a forma que dividi o MVC está cheirando a erro…

Lavieri

Voltando ao que falei la em cima, e que acho que não fui bem interpretado… não acho errado a visão ouvir o modelo … acho errado a visão se registrar no modelo, para ouvilo, esse trabalho deve ser mais do controle, isso é o que acredito…

Sobre o que foi falando acim com os observers,

M e principalmente M, não deve nem saber que existe V …

O Modelo existe com a lógica de negocio, e ele deve ser independente da visão o maximo que você conseguir.

Ai vamos o motivo da existencia do controle… A Colocar decisões dentro do modelo (mesmo que estas sejam de fluxo) não é bom, e é ai que entra o controle…

o contrlle existe principalmente para mediar o meio de campo… A View deve conhecer do modelo apenas as informações, ou seja, deve conhecer Beans ou Entidade que contenham informações a serem exibidas ou coisas do genero.

C, o Controller existe para agrupar a “pseudo lógica” da visão, ou seja, ele existe para Converter as informações da visão em informações legiveis para o Modelo, e quando necessário fazer o mesmo transformando as informações do Modelo em informações legiveis para a Visão.

Além disso é de responsabilidade do Controller conhecer o fluxo do sistema, ou seja, ele deve saber encaminhar uma ação vinda da View, e direcionar para o local correto no Modelo, se houver retorno do Modelo, é geralmente trabalho de C o Controller devolvero retorno a VIEW…

Mesmo no caso de uso de Observer, as coisas continuam passando pelo controller, pq é ele quem registra uma Visão em um Modelo (quando possivel!, quando isto é compativel, quando não é compativel o controle é responsável por intermediar fazendo o papel do adaptador), portanto neste caso, mesmo que o FIRE do observerdo modelo vá direto a VIEW quem a colocou lá foi o controller, e foi através dele que essa informação foi parar no local correto, afinal essa é a função do controle.

Pq esse papel do C ? no meio de campo ? pq não fazer essas coisas na view ? o motivo é para deichar o código mais coeso.

dentro do Modelo há toda sua lógica o ideal é que vc seja capaz de um dia, se quiser, mudar a VIEW sem abalar o seu modelo, e assim seu código pode ser bastante reutilizável.

dentro da sua View não deve existir código do modelo, exceto os de uso de informação, ou seja, partes do modelo que são informação, e não os que são processamente… partes do modelo que servem para trazer infomação ou levar informação

dentro do seu controle, bom, como no modelo não pode ter NADA da view, como no sua view só pode ter objetos que carregam ou levam informações do modelo,

  • alguem tem que fazer as ligações, alguem tem q levar a informação que o usuário passa através de uma view, la pra baixo para o modelo.
  • alguem tem que pegar o processamento do modelo, e devolver a informação para a view correta, de forma que o usuário tenha interação com o sistema.
  • alguem tem que ser responsavel por ligar a VIEW ao MODELO e esse alguem é o CONTROLE.

Bom esse é o meu intendimento do assunto, e é assim que faria/faço … não vejo motivos para uma view acessar diretamente o modelo, mesmo que para se registrar com observer, não é trabalho da view saber onde se registrar e sim do controller…

Ficam ai minhas observações…

Ps.: Cuidado com o entendimento de MVC em varias camadas, isso é possivel sim, mas não é prache e nem sempre a melhor forma de se fazer… um MVC existe onde você conseguir enchergar um MODELO e uma VIEW … a interface da sua camada pode sim ser conciderada uma VIEW (quando falo interface, falo do limiar da camada que é usado pela camada superior), mas ai vc esta levando em concideração que pode trocala por algum motivo, se não houver como trocar esqueca, e escreva um MVC só pra uma camada…

Lembrando que, GUI, páginas web, são lógicamente views, e portanto é sempre bom pensar em MVC quando usalas.

71C4700

Se pensarmos da seguinte forma: O controlador deve apenas receber as notificações da visão e repasá-la ao modelo. O Modelo deveria, então, trata da forma a qual fosse mais conviniente.

Sendo assim, teriamos algo mais simples, onde o controlador apenas seria ouvinte dos eventos que ocorrem na visão, e tambem poderia ser o objeto observado pelo modelo. Ai teriamos uma divisão bem legal, pois o controlador nao precisaria conhecer o modelo, nem a visão o controlador. Ocorreia apenas um ‘conhecimento unidirecional’ entre as camadas subadjacentes. E teriamos uma forma simples de realizar a manutenção no codigo, pois teriamos apenas a alteração em uma camada, não refletindo na outra, nem mesmo quando a lógica, ou a forma que o controlador é notificado pela visão nem tao pouco quando a visão mudasse.

Lógico, são opiniões que podem estar um pouco vagas, mas acredito que dessa forma poderiamos ter uma maior escalabilidade e manutenibilidade no software.

Att…

Lavieri

71C4700:
Se pensarmos da seguinte forma: O controlador deve apenas receber as notificações da visão e repasá-la ao modelo. O Modelo deveria, então, trata da forma a qual fosse mais conviniente.

Sendo assim, teriamos algo mais simples, onde o controlador apenas seria ouvinte dos eventos que ocorrem na visão, e tambem poderia ser o objeto observado pelo modelo

É aqui onde mora o problema… se o Modelo conhecer o controle, vc fica incapacitado de pegar o mesmo modelo e usar com uma visão diferente…

O papel do controle é de intermedirar o assunto, então inevitavelmente ele vai ter que conhecer os 2…

71C4700

Neste caso o modelo apenas seria ouvinte do controlador. Não tendo, entao, a necessidade de conhece-los, podendo ser aplicado tanto pra Web quanto pra Desktop.

Assim penso, pois o modelo pode mudar, e essa mudança deve revletir o minimo possivel. Nesta solução, teriamos que alterar apenas a visão sobre alguma modificaçao no modelo, nao tendo necessidade de alterar o controlador. Mas esta mudança na visão seria apenas se alguma informaçao na notificação ou alteração na estrutura dos objetos trocados entre visão e modelo, pelas notificações.

Att…

Lavieri

Como vai ser ouvinte de alguem sem conhecelo ? … o que vc chama de ser ouvinte sem cohecelo ? (Obs.: entenda que não estou criticando que isso não possa acontecer, tanto que é o que afirmei acima, e o que tento explicar novamente abaixo)

o Modelo pode ter espaço para registro de observer(isso não o torna informante do controle e sim um local de onde informações são enviadas, seja pra onde for) , ou espaço de registro para entrada de eventos (isso não os torna ouvinte de evento do controle, e sim receptivo a eventos externos, o que faz o estado do modelo alterar, ou uma cadeia de eventos ocorrer), isto não implica que ele conheça o controller, ou que ele esteja ligado de alguma forma ao controller…

o Modelo continua sozinho, com espaços para receber informação/eventos, e espaços para enviar informações/eventos… ficando desacoplado totalmente da visão ou controle.

assim… o Controle precisa conhecer o modelo, pois o modelo não vai chamar a visão para ser registrada nela, nem mesmo o modelo, ele apenas tem lugares onde isso pode ser feito, mas quem tem que fazer é o controle, e para tal ele vai precisar conhcer o modelo, e como o que o controle vai ligar ao modelo é a visão, ele acaba conhecendo os 2, e não da pra fugir muito disso =/

pedromuyala

Olá pessoal, muito obrigado pela participação de todos! Fico muito contente em ver o interesse do pessoal! :smiley:

Nós estamos aqui neste tópico há alguns meses debatendo com muitos profissionais (especialistas ou não) em suas diferentes áreas de atuação. O que nota-se claramente é um certo “desacordo” entre os diversos lados sobre um tema que tem como definição “pattern” (padrão), ou seja, um assunto que deveria ser igualmente entendido por todos, no nosso caso, o MVC.

A minha real intensão para criação deste tópico era debater algo que as pessoas conseguissem realmente entender e resolver suas dúvidas sobre o pattern MVC. Só não acreditava que esses problemas fossem tão ramificados e difíceis de serem resolvidos de forma que houvesse um acordo geral entre a maioria de nós.

Mas tem alguns detalhes do MVC que parecem estar de acordo com a grande maioria das pessoas, os quais só consegui perceber depois desses meses de debate. São eles:

1 ) MVC funciona bem quando aplicado de forma integrada/indivisível/impartível a Camada. Geralmente não se parte o trio MVC para abrangir várias camadas. Cada uma tem o seu MVC próprio, quando necessário. Exs:

Ex1 - a) MVC aplicado a Camada de Apresentação;

Ex1 - b) MVC aplicado a Camada de Cliente;

Ex1 - c) Um MVC aplicado a Camada de Apresentação e outro MVC aplicado a Camada de Cliente seu um mesmo sistema.
2 ) No MVC entende-se como entrada/exibição de dados o V de Visão. Exs:

Ex2 - a) (Como Entrada) O usuário interage clicando/teclando em um JButton (ou qualquer outro componente que gera um evento para a Visão);

Ex2 - b) (Como Exibição) Exibe a interface gráfica de determinado componente ao usúario;

Ex2 - c) (Como Exibição) Mantém a Visão de acordo com o seu respectivo Modelo.
3 ) No MVC entende-se como saída/domínio de dados o M de Modelo. Exs:

Ex3 - a) (Como Saída) O Modelo presente na Camada de Cliente sofre uma alteração que também altera algo na Camada de Apresentação;

Ex3 - b) (Como Domínio) O Modelo mantém guardado o dado de quantas vezes o usuário digitou uma tecla em um JTextField;

Ex3 - c) (Como Domínio) O Modelo notifica a sua respectiva visão quando algo é alterado.

4 ) O trio M-V-C forma um triângulo e tem um ciclo/fluxo no formato …->V->C->M->V->C->M->…, formando uma interação circular. Ex:
Ex4 - a) Se a Visão gera um evento o qual é interpretado pelo Controlador como algo que altera o Modelo, após essa alteração, a Visão deve se reenderizar.

5 ) A camada com seu respectivo MVC interage, em uma hierarquia de Camadas, com uma camada superior através da sua Visão e com uma camada inferior através do seu Modelo. Ex:
Ex5 - a) Usuário seleciona uma cor de texto diferente em um componente. Isso é uma interação que ocorre entre o usuário e a Visão da Camada de Cliente. Essa ação do usuário gera uma modificação no Modelo da Camada de Cliente sendo que essa modificação é fruto do resultado de uma solicitação do Modelo da Camada de Cliente à Visão da Camada de Apresentação que retornou ao Modelo da Camada de Cliente.

6 ) A Visão de um MVC lança eventos, e somente eventos crus, ao seu Controlador, o qual interpretará o significado do evento para uma forma legível ao Modelo que poderá ou não ser modificado.

7 ) O Modelo só notificará as Visões que o refletem através de eventos, mas a Visão se atualizará diretamente através da instancia do objeto no Modelo ao qual exibe naquele momento.

8 ) Formulários de preenchimento de dados estão mais para o conceito de MVP do que para o conceito de MVC.

Consegui expor oito pontos na qual a grande maioria parece estar concordando. Preferi me preservar em outros mais discutíveis. Com certeza os próximos post’s serão de usuários discordando desses pontos, mesmo com grande maioria a favor.
Para piorar mais ainda aparece minha avó aqui dizendo que “na casa que falta pão, todos brigam e ninguém tem razão”… o vovó, pega leve poxa! :stuck_out_tongue:

Bem como disse incialmente o MVC tem muitas ramificações a serem debatidas, as quais acredito que já não são mais suportáveis por este tópico que está imenso.
Sendo assim, vou começar a ramificar também o tópico abrindo novos tópicos com as questões mais “fora de padrão” do padrão MVC, até mesmo para que os novos leitores do tópico se interessem mais com menos sono (Ler 192 postagens com o assunto mudando constantemente dá mais sono que o pós-almoço de Segunda-feira). Vou postando os novos tópicos no início deste principal, para guiar corretamente a galera! :wink:

Vou ficar aqui no aguardo das opiniões, principalmente das últimas postagens. :wink:
Um abração galera do GUJ, seus usuários e moderadores. Todos proporcionam essa comunidade linda e maravilhosa, a maior do Brasil! :smiley:

Lavieri

Só para entender o que exatamente vc esta querendo colocar neste poto, quando fala que o modelo noifica a visão…

A) Se vc esta falando, que um controle, registra uma visão, como observadora do modelo, e este modelo ao ter seu estado alterado, notifica a seus ouvintes (o que indiretamente, e só indiretamente notifica a visão) ai eu concordo.

B) Se vc esta falando, que a propria visão se registra no modelo, ou que o proprio modelo sabe a qual visão alertar ao ter seu estado alterado, ai eu discordo.

Eu acredito que com essa explicação vc quis colocar o ponto “A”, estou apenas tocando neste ponto, para falar sobre a opinião que tenho que o modelo é isolado, ou seja, para colocar o ponto em que o modelo não se comunica com a visão, não diretamente … o modelo tem sim é porta de entrada de informação/eventos, e porta de saida de informação/evento …

essas portas genericas é o que deicham o modelo isolado, e o tornam reutilizaveis, nestes pontos de contato com um mundo exterior vc pode fazer o acoplamento solto com a visão, e esse é o caso “A” que falei aqui.

enfim é isso,

não sei se fui claro com o post, espero que sim

pedromuyala

Olá Lavieri! Obrigado por participar! :-o

Lavieri:
A) Se vc esta falando, que um controle, registra uma visão, como observadora do modelo, e este modelo ao ter seu estado alterado, notifica a seus ouvintes (o que indiretamente, e só indiretamente notifica a visão) ai eu concordo.

Eu acredito que com essa explicação vc quis colocar o ponto “A”, estou apenas tocando neste ponto, para falar sobre a opinião que tenho que o modelo é isolado, ou seja, para colocar o ponto em que o modelo não se comunica com a visão, não diretamente … o modelo tem sim é porta de entrada de informação/eventos, e porta de saida de informação/evento …

essas portas genericas é o que deicham o modelo isolado, e o tornam reutilizaveis, nestes pontos de contato com um mundo exterior vc pode fazer o acoplamento solto com a visão, e esse é o caso “A” que falei aqui.

Não consigo entender uma coisa:

Como estamos debatendo um assunto Desktop os objetos do trio MVC são instanciados pelo main que é quem liga as partes e o Observer de Model para Visão, certo? Veja:

import javax.swing.JFrame;

public class MVC {
   public static voi main(String args[]) {

      Modelo m = new Modelo();
      Controle c = new Controle(m);
      Visao v = new Visao(c);

      m.addModeloListener(v); // Isso que você está opinando ser o erro?

      JFrame j = new JFrame();
      j.add(v);
      j.setVisible(true);

  }
}

Fico no aguardo pela resposta! Forte abraço.

Lavieri
pedromuyala:
import javax.swing.JFrame;

public class MVC {
   public static voi main(String args[]) {

      Modelo m = new Modelo();
      Controle c = new Controle(m);
      Visao v = new Visao(c);

      m.addModeloListener(v); // Isso que você está opinando ser o erro?

      JFrame j = new JFrame();
      j.add(v);
      j.setVisible(true);

  }
}

de forma alguma isso é correto.... pois o MAIN é controle, e não modelo.... a visão não esta se escrevendo no MODELO, nem o MODELO esta inscrevendo a visao....
o controle é que instancia o MODELO, instancia a VISAO, e pega e junta um no outro.... essa abordagem é correta....

o que não pode ?
Modelo {
    addModeloListener(Visiao v) {} //esse argumento aqui é errado!
}

a forma mais correta é

Modelo {
    addModeloListener(ModeloListener ml) {} //ai é correto, aqui vc não conhece a visao
}
//quem precisar que implemente a interface ModeloListener

mas o IDEAL mesmo é

public static voi main(String args[]) {

      Modelo m = new Modelo();
      Controle c = new Controle(m);
      final Visao v = new Visao(c);

      m.addModeloListener(new ModeloListener() {
           void notificador(ModeloEvento me)  {
              v.façaAlgo();
           }
      });
      JFrame j = new JFrame();
      j.add(v);
      j.setVisible(true);

  }

Observação...

Visao v = new Visao(controller);
isso aqui também não é muito bom... não tem motivos para a visão depender do controler, o ideal é vc inverter o papel.... deixar o controle cuidar da visão....
pedromuyala

Ah sim aí concordo perfeitamente. O Controle do MAIN é quem monta o jogo e quem está fazendo a ligação das notificações do modelo até a visão, está perfeito!

[quote=Lavieri]
Observação…

Visao v = new Visao(controller);

Não entendi como a Visão vai falar com o Controle!
Nesse caso, você diz assim??:

public static voi main(String args[]) {

      Modelo m = new Modelo();
      Visao v = new Visao();
      Controle c = new Controle(v);

      m.addModeloListener(new ModeloListener() {
           void notificador(ModeloEvento me)  {
              v.façaAlgo();
           }
      });
      JFrame j = new JFrame();
      j.add(v);
      j.setVisible(true);

  }

Fico no aguardo! Abração.

Lavieri

o seu main, faz parte do controle... ele é o que monta o inicio da aplicação e da um start...

se o controle que cuida de integrar a visão "v" ao modelo "m" é o controle "c" ... então "c" que tem que instanciar e cuidar dos dois ...

melhor do que colocar os passos do controle no MAIN é fazer assim

public  static voi main(String args[]) {  
        new ControlePrincipal().start();
 }

ai no caso o controle principal seria assim....

public class ControlePrincipal() {
  
  private Modelo modelo;
  private ModeloBeanInformacao umBeanContendoInfos;
  private Visao visao;

  public void start() {
     montaModelo();
     montaVisao();
     ligaAInformacaoDaVisaoComOModelo(); //aqui foi por minha conta, para deixar o exemplo mais rico.
     mostraVisao();
  }

  private void montaModelo() {
      this.modelo = new Modelo();
  }

  private void montaVisao() {
      this.visao = new Visao();
      modelo.addModeloListener(new ModeloListener() {  
          void notificador(ModeloEvento me)  {  
             visao.façaAlgo();  
          }  
      });
  }

  private void ligaAInformacaoDaVisaoComOModelo() {
      this.umBeanContendoInfos = new ModeloBeanInformacao ()ç
      visao.setBeanDeInfos(umBeanContendoInfos);
      visao.addVisaoListenerBotaoSalva(new VisaoListenerBotaoSalvar() { //isso é apenas um exemplo didatico
           public void botaoClicado(EventoVisaoBotaoSalva evento) {
                this.modelo.salvar(evento.getBeanContendoInfos()); //#1
           }
      });
  }

  private void mostraVisao() {
     visao.setVisible(true); //observação, nesse exemplo, o objeto Visão já é um JFrame, 
     //se ele não for um, ai vc muda a montagem, ou adiciona um montarJanlea(); antes do mostrarVisao() =P
  }
}

ai o que vc for precisando fazer a mais, vc vai fazendo a ligações com novos controles

no caso ilustrativo do #1 ... ai clicar no botão da VIEW, o controle recebe o evento.... pega a informação que o modelo precisa do evento (o objeto contendo as informações, esse objeto é um objeto de modelo) .... pega este objeto e envia para o this.modelo, para que ele salve o objeto.... esse método modelo.salvar(bean); pode disparar um evento, e como a visão esta escutando o evento do modelo, o controle nem precisa se preucupar com a resposta do modelo, pois ela já vai direto pra visão.... visto o que foi setado em "montaVisao()" quando adicionou-se a visão como listener...

O papel do controle é esse... intermediar, fazer o meio de campo....

dizer.... BOTão da VIEW 1 .... vc vai representar tal ação no modelo

ele serve pra isso ocontrole... receber informação dos dois lado... e fazer as ligações... enviar para os lugares corretos

pedromuyala

Fala Lavieri, obrigado por continuar aqui atento acompanhando e ajudando no tópico!

Sim realmente é perfeita tanto a explicação quanto a implementação exemplo.
Porque comentou uma linha dizendo que era somente um exemplo didático no código? Eu, na minha opinião, vejo estar perfeito, principalmente quando olho para o desenho teórico do MVC.Interessante é que esse esquema parece ser mais inteligente do que diz a teoria, vou tentar explicar: Na minha opinião esse BEAN solto carrega dados da visão ao controle e do controle ao modelo, ou seja, no caso de preenchimento de formulários, através do evento. Sem falar que posso deixar a visão interativa, assim: o usuário digita um cpf. Na hora que ele sair do campo (tirar o cursor) eu posso lançar um evento que leva o número do cpf até o modelo, que chama as suas camadas inferiores até receber a resposta de volta e notificar a mudança para a visão, no caso de ocorrer, por exemplo um erro ou o cpf já constar.

Fiquei com 3 dúvidas:

  1. Como um trio MVC chama outro trio MVC em determinado momento? Assim: Um MVC está ativo. Em determinado momento o usuário clica/seleciona um botão (Ex: JButton “Avançar”) que agora precisa chamar um outro trio MVC (Digamos que ele está trabalhando um trio MVC coeso que trata de pessoas e ao pressionar o botão, agora ele vai ter que mostrar um outro trio MVC coeso que trata de vendas) Consegui expor a dúvida?

  2. Se ocorrer um erro/falha nas camadas inferiores e esse deve ser mostrado ao usuário? O Modelo quem terá que ter o atributo para guardar a informação de modo que a visão mostrará assim que o modelo notificar a alteração?

  3. Esse BEAN (que é do modelo) não está acoplando tudo a partir do momento que ele é carregado pelo evento?

Mais uma vez muito obrigado Lavieri por estar aqui nos ajudando!
Forte abraço, fico no aguardo pela resposta. E a todos que quiserem colaborar! Não deixe de opinar!

Lavieri

pedromuyala:
Fala Lavieri, obrigado por continuar aqui atento acompanhando e ajudando no tópico!

Sim realmente é perfeita tanto a explicação quanto a implementação exemplo.
Porque comentou uma linha dizendo que era somente um exemplo didático no código? Eu, na minha opinião, vejo estar perfeito, principalmente quando olho para o desenho teórico do MVC.Interessante é que esse esquema parece ser mais inteligente do que diz a teoria, vou tentar explicar: Na minha opinião esse BEAN solto carrega dados da visão ao controle e do controle ao modelo, ou seja, no caso de preenchimento de formulários, através do evento. Sem falar que posso deixar a visão interativa, assim: o usuário digita um cpf. Na hora que ele sair do campo (tirar o cursor) eu posso lançar um evento que leva o número do cpf até o modelo, que chama as suas camadas inferiores até receber a resposta de volta e notificar a mudança para a visão, no caso de ocorrer, por exemplo um erro ou o cpf já constar.


didatico, pq assim o é =P … pq estava querendo exemplificar para te explicar =P … just it…

pedromuyala:

  1. Como um trio MVC chama outro trio MVC em determinado momento? Assim: Um MVC está ativo. Em determinado momento o usuário clica/seleciona um botão (Ex: JButton “Avançar”) que agora precisa chamar um outro trio MVC (Digamos que ele está trabalhando um trio MVC coeso que trata de pessoas e ao pressionar o botão, agora ele vai ter que mostrar um outro trio MVC coeso que trata de vendas) Consegui expor a dúvida?

a verdade é que não existe TRIO MVC =P … existe o MODELO, a VISAO … e o controlador no meio, fazendo o meio de campo… vc separa em areas lógicas claro… e pode ter vários Controllers…

por exemplo… botão avançar, pode fazer …

new ControleJanelaSeguinte(informacoesPassadasDessaJanela).start(); fechamentoDeRecursos(); //isso aqui se precisar fazer operações e abondonar a janela atual.

um só controle pode cuidar de varias janelas da view, e se comunicar a varias partes do modelo… o ideal é que o controle represente uma operação lógica, ou seja… contenha os caminhos de um case use (quando possivel, para não torar o controle um monstro, vc separa em mais cases o controle)

Normalmente um erro no modelo interrompe um processo que não deveria ser interrompido, as vezes há solução, as vezes não… o modelo quase nunca sabe que decisão tomar, e o que ele faz é enviar a exceção mais pra cima… tem partes do modelo que pode fazer um fluxo de decisão para uma exceção…

vamos ao exemplo…

modelo.salvar(informacao); throws MeuBancoTaOffLineException … o que o modelo pode fazer ?? ficar tentando reconectar ? tentar novamente ? fazer nada ? normalmente aqui não é o lugar de decidir… o que fazer ? essa exceção sai do modelo … ele joga ela pra fora…

o controle é o CARA, ele sabe pra onde vai as coisas

try { modelo.salvar(informacao); } catch(MeuBancoTaOffLineException ex) { mostraJanelaDeDeconectadoEPerguntaSeQuerTentarNovamenteOuReconectarOuEtcs(); }

em alguns casos o erro é de outra ordem

modelo.salvar(informacao); dispara um evento, avisando que não salvou! … e falando que não salvou pq faltou informar um campo… ai alguem pega o evento, e faz com isso o necessário

ele não ta acoplado a ninguem … ele é um bean, quem o usar, que vai estar se acoplando a ele… a view as vezes tem que realmente conhecer o modelo… quando não dá quando isso é ruim de fazer, ai o controle tem q traduzir esse BEAN pra algo que a VIEW entenda…

mas um BEAN que carrega informação, ele sai de dentro do modelo, com esse intuito, de levar a informação para fora do modelo, que precisar que a use.

pedromuyala

Entendi Lavieri… bem bacana a sua explicação.
Muito legal. Vou fazer o seguinte: Vou tentar firmar a sua idéia ajudando alguém que há alguns dias não aparece no tópico, a menina da Agenda, lembra dela?
Vou tentar fazer uma agenda usando esse esquema e vou colocar o código aqui. Só peço um pouco de paciência que meu raciocínio é mais lento que botar fogo no gelo! :shock:

Mas depois dessa explicação vou ficar com :oops: se não conseguir!!!
Forte abraço, breve estarei postando o código! :wink:

Trebloc

Esse tópico deve ser um dos melhores daqui, aprendi mais algumas coisas que não sabia só de dar uma olhada nos posts. :roll:

I

Olá rapazes,

Pedro, não precisa se preocupar em implementar a agenda. Citei a agenda como um exemplo também para aprender melhor a teoria… tinha dúvidas parecidas com as suas.
Gostei da explicação do Lavieri ficou bem interessante… (não dá sono, como disseram aí acima hihihihi!)
Vou tentar também implementar do meu jeito e posto aqui!

Obrigada! :smiley:

I

Oi meninos! Procurei mais sobre o assunto, não poderia deixar de comentar uma coisa que percebi: existe uma confusão muito grande entre MVC x MVP.

Lavieri:
o seu main, faz parte do controle... ele é o que monta o inicio da aplicação e da um start...

se o controle que cuida de integrar a visão "v" ao modelo "m" é o controle "c" ... então "c" que tem que instanciar e cuidar dos dois ...

melhor do que colocar os passos do controle no MAIN é fazer assim

public  static voi main(String args[]) {  
        new ControlePrincipal().start();
 }

ai no caso o controle principal seria assim....

public class ControlePrincipal() {
  
  private Modelo modelo;
  private ModeloBeanInformacao umBeanContendoInfos;
  private Visao visao;

  public void start() {
     montaModelo();
     montaVisao();
     ligaAInformacaoDaVisaoComOModelo(); //aqui foi por minha conta, para deixar o exemplo mais rico.
     mostraVisao();
  }

  private void montaModelo() {
      this.modelo = new Modelo();
  }

  private void montaVisao() {
      this.visao = new Visao();
      modelo.addModeloListener(new ModeloListener() {  
          void notificador(ModeloEvento me)  {  
             visao.façaAlgo();  
          }  
      });
  }

  private void ligaAInformacaoDaVisaoComOModelo() {
      this.umBeanContendoInfos = new ModeloBeanInformacao ()ç
      visao.setBeanDeInfos(umBeanContendoInfos);
      visao.addVisaoListenerBotaoSalva(new VisaoListenerBotaoSalvar() { //isso é apenas um exemplo didatico
           public void botaoClicado(EventoVisaoBotaoSalva evento) {
                this.modelo.salvar(evento.getBeanContendoInfos()); //#1
           }
      });
  }

  private void mostraVisao() {
     visao.setVisible(true); //observação, nesse exemplo, o objeto Visão já é um JFrame, 
     //se ele não for um, ai vc muda a montagem, ou adiciona um montarJanlea(); antes do mostrarVisao() =P
  }
}

ai o que vc for precisando fazer a mais, vc vai fazendo a ligações com novos controles

no caso ilustrativo do #1 ... ai clicar no botão da VIEW, o controle recebe o evento.... pega a informação que o modelo precisa do evento (o objeto contendo as informações, esse objeto é um objeto de modelo) .... pega este objeto e envia para o this.modelo, para que ele salve o objeto.... esse método modelo.salvar(bean); pode disparar um evento, e como a visão esta escutando o evento do modelo, o controle nem precisa se preucupar com a resposta do modelo, pois ela já vai direto pra visão.... visto o que foi setado em "montaVisao()" quando adicionou-se a visão como listener...

O papel do controle é esse... intermediar, fazer o meio de campo....

dizer.... BOTão da VIEW 1 .... vc vai representar tal ação no modelo

ele serve pra isso ocontrole... receber informação dos dois lado... e fazer as ligações... enviar para os lugares corretos

Isso é MVP - Passive View.. Pode conferir neste link
Por sinal, muito bem mostrado pelo Lavieri. :D

[img]http://farm3.static.flickr.com/2755/4491937766_570fe43b7a_o.png[/img]

Outro exemplo de confusão está em outro link postado aqui neste tópico mesmo. Neste link diz "estrutura MVC" mas na verdade é uma 'estrutura MVP' a qual não consigo definir se é Passive View ou Supervising Controller. A mesma coisa vale para este outro link. Ambos não usam o Observer, simplesmente intermediam o meio de campo. - Agem como Presenter, sem Observer.

------

Particularmente o MVP 'ao meu olhar feminino' é a melhor opção para o caso de construir uma Agenda (só olhar a img acima). Mas ainda estou preocupada quanto a esse 'bean' solto por todo lado.. :? Não seria mais adequado (isso falando em MVP, my case ) existir uma interface implementada pela visão com gets/sets dos TextFields para que o Presenter ao receber o evento do botão possa colher os dados e passar para os set's do modelo? Evitaria esse bean e teoricamente mais correto.. tô errada? me falem!!!!

Obrigada meninos fico no aguardo. :D

sergiotaborda

Na prática MVC é legal para frameworks. Swing, JSF , etc… e MVP é legal para como as aplicações interagem com esses frameworks.

O pessoal do swing criou-o em MVC. mas agora eu só preciso na realidade lidar com os modelos para injetar dados, e com a visulaização (desabilitar , tornar invisivel, etc…) Aqui entra o MVP. O Presenter é responsável por consultar o modelo dele e/ou alterar a visualização em conformidade.
Por exempplo, só habilita o combo de cidades se o cara já escolheu o pais. Repare que ainda estou ouvindo eventos, mas eventos de alto nivel “alteração do pais” e não “o combo xpto foi modificado”. Como eu transformo um change event do combo num evento de negocio que o presenter entende ? Na view do MVP. A view do MVP é um cara super bom que conhece todo o MVC do cliente gráfico. Ele tanto pode manipular modelos como componentes.Ele canaliza e traduz os eventos em conformidade com as regras de apresentação. Por isso que temos dois andares : cliente e apresentação. Os comandos do cliente são agnostios sabemos que tal menu foi clicado ou tal botão foi apertado, etc, mas não sabemos o que isso significa. Cabe à camada de apresentação saber. Podemos usar um MVC na camada de apresentação, mas o MVP tem mais vantagens práticas.
Frameworks web já implementam a camada view para HTTP pela injeção de dados e outas coisas assim, em swing é mais complexo , não ha nada pronto assim , apenas frameworks como o thinlet que dão todo o frameowork mas de forma abstrata ( não se é um JButton do swing ou um button do AWT por detrás do evento. )

A vantagem do MVP é que tanto o M como o V podem ser abstraidos de forma genérica e abacamos apenas ter que implementar o presenter. Por exemplo, para formulários, teriamos um view que já sabe trabalhar com formulários que dá acesso aos valores dos campos, e ás acções que o usuário executor como salvar, deletar etc… no presenter teremos métodos como

save(AlgumObjectoDeContexto contexto) {
     // le os dados do formulário e poe num objeto
     ClienteForm clienteForm = contexto.getFormInstance(ClienteForm.class); 

    // valida formulário 

   // se tudo está ok, transforma clienteForm para o objeto Cliente
  
   // salva

      ClienteCRUDService service = ...
      service.save(cliente);   
}


@Trigger("//pais[changed]")
onPaisChanged(AlgumObjectoDeContexto contexto){
 ClienteForm clienteForm = contexto.getFormInstance(ClienteForm.class); 

       UIComponente uic = contexto.find("//cidades");

      uic.setVisible(clienteForm.getPais()!=null);
}

Como se vê é preferivel ter um conjunto de interfaces que abstraem muito do cliente UI, Contudo isso não é obrigatório.
Poderiamos ter um modelo mais simples onde do contexto tenho um objeto Form e nesse objeto tenho get/set dos campos (semlhante a um httprequest em web).

É bom também que se usem bens de visualização. O clienteform é um bean simples ( sem composição) onde pais e cidade são campos “não relacionados”. O Presenter pode transformar isso para um objecto cliente concreto que tem, por exemplo, associação a Endereço e Endereço que tem esses dois campos. O UIBeans são uteis para facilitar a leitura dos dados da tela onde não queremos nos preocupar com as relações. Além disso permitem que sejam adicionados campos de controle (flags / hidden) que são apenas usados pelo presenter e não têm relação com as entidades em si.

Para quem trabalha com Spring, ou Struts ou algum web framework conhece este mecanismo onde apenas se implementa um classe. As pessoas chamam ela de controlador, mas na realidade é um presenter. No Struts 1 isso é ainda mais obvio porque existe um encapsulamento explicito num objeto ActionForm ( que equivale ao meu clienteForm no exemplo).

Resumindo, se vc for implementar com MVP vc precisa de construir o V que se ligue ao swing. e depois só implementa o presenter para cada caso. Isto pode não ser tão trivial como parece, mas tb não é nenhum bixo de sete cabeças.

Isolando o presenter do swing, vc acaba ganhando um mecanismo de presenter que funciona para todos os MVC que existem. Portanto, se um dia vc quiser mudar para SWT ou AWT ou mesmo javaFX, em tese vc consegue. Este conceito é o que o thinlet aplica se bem que - até onde sei- ele só gera AWT.

I

Olá dedicados meninos… :wink:

Sergio, se entendi direito o que tentou expor teoricamente aí na postagem anterior você defende o que o Lavieri falou, estou errada?
Defende o uso de um bean para trazer os dados da visão até o presenter e vice-versa, certo? Mas ao invés dele, porque não usar interfaces?
Veja, vamos ver se entendi o que uma parte do MVP implementado:

  1. MVP Está dentro de uma camada (assim como o MVC)? Trocando em miúdos, MVP está em uma camada ou mais, mas não está jampeando duas, três, quatro camadas?
  2. Visão e Presenter são fortemente acoplados?
  3. Presenter instacia a visão e o modelo?
  4. Presenter modifica/consulta diretamente os componentes da visão chamando métodos gets/sets da interface dela?
  5. Presenter tem as funcionalidades (classes Listeners) dos componetes da visão, por exemplo, dos botões e o que eles farão?
  6. Presenter consulta/modifica o modelo por chamada direta aos métodos?
  7. Presenter escuta os eventos de notificação de mudança de estado do modelo? (Isso é para dar extensibilidade ao sistema, não?)
  8. No MVP a visão é ‘burra’. Ela possui componentes SWT, ou AWT, ou GWT, ou JavaFX, que simplesmente não sabem fazer nada a não ser interagir/capturar dados do usuário?
  9. A visão implementa uma interface com os métodos necessários para que seja usada pelo Presenter?
  10. A visão possui métodos set/getListener() para receber os listener’s do Presenter que escutarão os eventos lançados pelos componentes presentes nela?
  11. O modelo é a lógica da Apresentação e ponto?

E lembrem-se: no momento é uma Agenda em Swing… :lol: Quero aprender o melhor possível o básico… se a fundação é boa, o prédio não cai. :oops:

Pra mim o que diferencia o MVC do MVP é:

  1. MVC é para um componente. MVP é para vários componentes (ou widgets, como quiserem).
  2. MVC a visão escuta o modelo. MVP o presenter escuta o modelo.
  3. MVC o controle só transforma os “user gestures” em situações reais para o modelo. No MVP o presenter, além de fazer o que faz o controler do MVC ele também fala com a visão.

Vejam:

<<< MVP != MVC >>>

Agora uma pergunta final, depois de tantas acima que ainda não tem resposta (e olha que procurei nas postagens anteriores): Essa seta “Seleciona a View” está errada na imagem do MVC não?
Controle não fala com a visão por chamada direta, certo? elá deveria então ser tarcejada, não?

Obrigada por me aturarem… :smiley:

sergiotaborda

ingridfarabulini:
Olá dedicados meninos… :wink:

Sergio, se entendi direito o que tentou expor teoricamente aí na postagem anterior você defende o que o Lavieri falou, estou errada?
Defende o uso de um bean para trazer os dados da visão até o presenter e vice-versa, certo? Mas ao invés dele, porque não usar interfaces?

Não sei de onde inferiu que usei beans no exemplo atráz. Como vc pode saber se ClienteForm é um bean ou uma interface (thats right, não pode, :slight_smile: )
Na prática tanto faz. Ou vc vai ter um bean com get/set diferentes para cada formulário (porque cada um tem campos diferentes) ou vc vai ter uma interface de get/set
para cada formulário e um mecanismo que responde por essa interface ou vc vai ter um objeto de contexto genérico mais parecido com um Map.
A escolha do bean não é diferente da interface na prática, apenas na implementação.

sim

Não. O presenter sabe qual é a visão, mas a visão não precisa saber qual é o presenter. O presenter precisa ouvir eventos da visão, mas isso pode ser feito por um mecanismo do tipo Observer.
Não ha necessidade de acoplamento.

Sim, mas não precisa ser explicitamente. como mostrei atraz eu mudei o estado de enable de um componente sem ter que saber qual ele é.
Nem mesmo preciso saber que é um componente swing.

sim. o presenter terá vários métodos que são invocados quando os ventos acontecem.

6. Presenter consulta/modifica o modelo por chamada direta aos métodos?

sim.

7. Presenter escuta os eventos de notificação de mudança de estado do modelo? (Isso é para dar extensibilidade ao sistema, não?)

Exacto. Na prática não é muito usado.

8. No MVP a visão é ‘burra’. Ela possui componentes SWT, ou AWT, ou GWT, ou JavaFX, que simplesmente não sabem fazer nada a não ser interagir/capturar dados do usuário?

mais ou menos burra. Ela sabe que clicar no botão x significa “salvar” e no y significa 'sair". Ela apenas não sabe o que fazer.
O mecanismo que traduz o clique no botão para a chamada ao método no presenter está na visão.

9. A visão implementa uma interface com os métodos necessários para que seja usada pelo Presenter?

sim. Normalmente um objeto não chega. É preciso ter um mecanismo mais ou menos como o de um servlet.

10. A visão possui métodos set/getListener() para receber os listener’s do Presenter que escutarão os eventos lançados pelos componentes presentes nela?

Depende de como implementar. Pode fazer dessa forma.

Não. O presenter é a logica de apresentação (presentation ~presenter)
O modelo do MVP normalmente é adaptaer para um serviço , um façade , um besiness delegate , um dao ou um repositorio. Não é um objeto de UI como o M do MVC.

Não. Não tem nada a ver.

No MVC o modelo é do V, e o C é apenas um mediador. A logica está contida no M. ( o V é o “master”, todos trabalham para que ele funcione)
No MVP o V é do presenter e a logica está no presenter. O mediador é o M.( O P é o “master” todos trabalham para ele).

NO MVP o V não passa de um grande adpater da tecnologia de UI, no caso swing. E o M não passa de um adpater para a camada abaixo ( a de negocio).
No MVC não adapters. Cada item tem o seu papel proprio e as coisas só funcionam quando os 3 funcionam coerentemente.

Sim, o presenter é muito mais “controlador” que o controler do MVC. Infelizmente os nomes do MVC foram mal escolhidos ( deveria ser algo mais como Renderização-Componente-Dados)

Imagine um sistema de chat. Quando A envia uma mensagem a B ela chega pela camada abaixo do apresentação, ela chega pelo M do MVP. O M então precisa avisar o P que chegou uma mensagem para que o P faça algo com ela. Outro exemplo seria o sistema através do M avisar que a rede caiu e o P , sabendo isto, faz aparecer algum icon em algum lugar da V.
É por isso que o M pode ter que avisar o P. O P controla o estado de apresentação e a apresentação não depende apenas do que o usuário faz, depende tb do que o sistema faz e do que outros usuários fazem quando o sistema é multi-usuario. É por isso o MVP é mais natural para a camada de apresentação que o MVC.

Alchemist

Opa tudo bem ai pedromuyala, cara achei o topico muito bom parabens pela iniciativa, fiquei muito interessado na analise e no projeto que vc está fazendo… ainda não tive tempo de ler as 14 paginas do topico… será que vc poderia me mandar o seu projeto para ver como está ? Me responda por MP se possivel.

Obrigado.

pedromuyala

Opa, fala Alchemist, tudo bom contigo?

Então na verdade não existe nenhum projeto em desenvolvimento. O único projeto real mesmo até o momento é a Agenda da Ingrid ( aí de alguns post’s atrás! :smiley: )
Na verdade, quando criei o tópico tinha o objetivo de conseguir esclarecer de uma vez por todas algumas dúvidas que tenho de MVC desde que o conheci… mas nunca imaginaria que se tornaria essa coisa monstro que está, como pode ver você mesmo. Sempre acreditei que o MVC ajudaria da melhor forma os programadores, engenheiros, arquitetos de software a desenvolverem sistemas com qualidade na hora de realizar manutenções ou alterações. Mas já vi que não é bem isso que ocorre. Se ler todos os post’s vai ver que cada pessoa entende MVC de uma maneira diferente, não é criticando, muito pelo contrário, é até legal que existam diferentes idéias… o triste é que não se tem um acordo geral. Imagine uma grande empresa de software que desenvolve um único sistema, porém as diversas equipes entendem uma mesma teoria de diferentes maneiras… se essas equipes mudarem, por força maior mesmo, na hora de integrar ou dar manutenção, alterar, aumentar, testar o sistema… meu Deus, e agora, quem tem razão: A equipe que entende MVC x, a equipe que entendia MVC y ou z?

Acredito que o tópico tem ajudado muita gente principalmente a pensar nisso. Será que estou certo no MVC, ou errado? :roll:
E para responder isso não há dúvida que realmente é necessário ter um grande embasamento teórico e não um monte de código escrito.
O pessoal entendeu bem essa ideia e vem colaborando da melhor maneira possível expondo suas bases teóricas e também seus conhecimentos de anos, da melhor maneira possível.
O que mais me deixa feliz é que muitas pessoas com certeza estão tendo a oportunidade de esclarecerem suas dúvidas.

Ok rapaz? Agradeço muito por acreditar no trabalho que está sendo aqui mostrado.
Fico feliz por ter mostrado interesse pelo tópico, é uma honra!
Continue acompanhando conosco e não deixe de fazer suas perguntas se sentir necessidade.

Felicidades a todos os Gujeiros! Parabéns a todos. :wink:

Lavieri

Bom respondendo a dúvida da Ingrid, juntamente com as respostas do Sergio Taborda…

pelo que li, aqui, no post do taborda… no tal MVP (que li em outro canto ser uma variação do MVC, portanto não tem como deichar de ser um MVC)… voltando, no tal MVP a carcteristica principal é que a view e o modelo trabalham para o Presente …

Bom, se é este o caso, então realmente os exemplos que dei não são de MVP …

Eu simplismente desacoplo a VIEW e o MODEL … e uso o meu controler para ligar os 2 … view e modelo não se conhecem…

vou exemplificar com código (sim o código é de um exemplo web, mas é o que tenho pra mostrar…)

http://pastebin.com/FGJ296Ad (estou postando o código no paste bin, para não poluir o post)…

Vamos as explicações… esse é o código do meu controller, nele evito usar de lógica ao máximo… ele controla FLUXO, encaminha as coisas… a lógica já esta escrita, e não depende do controller… a view esta escrita, e não depende do controller nem do modelo… o trabalho do controller é traduzir a view para o modelo…

vamos ao exemplo…

Obs.: Antes de começar a ler… "logic" contém uma instancia de UsuarioLogic que é um objeto do modelo. "result" é um objeto do vraptor, que auxilia com os resultados para a view.


uri => /usuario/alterarSenha

@Post @TransactionScoped @Roles(includeResourceRoles=false) public void alterarSenha(Credential antiga,Credential nova) { if (logic.alterarSenha(antiga,nova)) result.redirectTo(this).meusDados(); else result.include("senhaInvalida", true); } Aqui eu recebo os dados da view, parte do trabalho de converter os dados da view em objetos é feito pelo VRaptor, afinal o VRaptor é parte do meu controle e me auxilia no modelo MVC para assim fazelo…

Na página web foi postados input texts normais, ele cai ai nesse método, no meu controller eu apenas uso a lógica para alterar a senha, se foi bem sucedida eu redireciono para meusDados, caso contrario eu continuo no mesmo caso, e apenas incluo no VIEW a mensagem de que a senha esta inválida.

uri => /usuario

@Get @Path("") public List<Usuario> listar() { return logic.listar(); }Aqui eu adiciono a view a lista de usuário, a listagem obviamente é feita na lógica, no controller eu só faço a chamada ao método (Obs, para o vraptor return list, é o mesmo que result.include(“usuarioList”,list) portanto nesse método do controller eu estou apenas colocando a lista que foi gerada na lógica dentro da view)

uri => /usuario/{id} , por exemplo /usuario/12

@Get @Path("/{id}") public void editar(Long id) { result.include("usuario", logic.buscar(id)); useForm(); }
aqui eu busco no modelo (através de uma lógica) o usuário do ID colocado na uri, e então adiciono ele a view, logo após eu carrego a página do formulário.

uri => /usuario/{id} , por exemplo /usuario/33

@Delete @Path("/{id}") @TransactionScoped public Usuario apagar(Long id) { Usuario result = logic.apagar(id); validator.onErrorUse(Results.logic()).redirectTo(getClass()).listar(); return result; }
Obs.: apesar da uri deste método ser a mesma do anterior, esse método é acessado quando a uri é usada através de um DELETE (isso são métodos http)
como podem ver a lógica de remoção esta no modelo, la dentro eu dou um apagar. em seguida vejo se houve erros de validação, em caso positivo eu redireciono para página de listagem.
caso a remoção seja um sucesso, eu apenas coloco na view o objeto que foi removido.

Enfim ai estão alguns exemplos, de como contruo meus controller… como podem ver a lógica não esta presente… apenas chamadas aos metodos corretos, e recuperação dos resultados e coloco esses resultados na view.

Lavieri

Bom, e se você olhar esta imagem que esta na WIKI PEDIA

e ler a legenda

“Model-View-Controller concept. Note: The solid line represents a direct association, the dashed an indirect association via an observer (for example).”

vai ver que é basicamente como uso… a ligação direta da VIEW com o MODELO é explicada, pq a view usava alguns objetos do MODELO, (normalmente objetos de informação, como entiades) para exibir informações…

Enfim é desta forma que uso…

Lavieri

para ajudar no exemplo, segue o objeto com lógica de verdade

Este objeto é o UsuarioLogic, que esta instanciado dentro de "logic" do controle, do exemplo dado no post anterior

package br.com.simtecnologia.helpdesk.model.user;

import java.util.List;

import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.validator.Hibernate;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.simtecnologia.helpdesk.model.login.Credential;
import br.com.simtecnologia.helpdesk.model.queries.QueryUsuario;
import br.com.simtecnologia.persistence.DomainStore;

@Component
public class UsuarioLogic {
	private final DomainStore helpdesk;
	private final UsuarioSession usuarioSession;
	private final Validator validator;
	private final QueryUsuario query;
	public UsuarioLogic(DomainStore helpdesk, UsuarioSession usuarioSession, Validator validator, QueryUsuario query) {
		this.helpdesk = helpdesk;
		this.usuarioSession = usuarioSession;
		this.validator = validator;
		this.query = query;
	}
	
	public Usuario buscar(Long id) {
		return helpdesk.get(Usuario.class, id);
	}
	/**
	 * Altera a senha, de acordo com as credenciais, para o usuário logado, na sessão corrente.
	 * @param credential as novas crendenciais contendo a nova senha.
	 * @param nova 
	 * @return 
	 */
	public boolean alterarSenha(Credential antiga, Credential nova) {
		if (!usuarioSession.isLogged())
			throw new IllegalStateException("Não há usuário logado para alteração da senha");
		if (!usuarioSession.confirmaSenha(antiga))
			return false;
		alterarSenha(nova,usuarioSession.getUsuario().getId());
		usuarioSession.getUsuario().setSenha(nova.getPassword());
		return true;
	}
	/**
	 * Altera a senha para o usuário do <tt>id</tt> enviado.
	 * @param credential as novas crendenciais contendo a nova senha.
	 * @param id o ID do usuário o qual deseja-se alterar a senha.
	 */
	public void alterarSenha(Credential credential, Long id) {
		Usuario usuario = buscar(id);
		usuario.setSenha(credential.getPassword());
	}
	
	public List<Usuario> listar() {
		return helpdesk.list(Usuario.class);
	}
	
	public List<UsuarioRoles> listarRoles() {
		return UsuarioRoles.list();
	}

	public Usuario apagar(Long id) {
		if (usuarioSession.isLogged() && usuarioSession.getId().equals(id)) {
			validator.add(new ValidationMessage("Não é possivel apagar o seu proprio usuário", "id"));
			return null;
		}
		return helpdesk.remove(Usuario.class,id);
	}

	public Usuario atualizar(Usuario usuario) {
		validator.addAll(Hibernate.validate(usuario));
		return validator.hasErrors() ? null : helpdesk.marge(usuario);
		
	}

	public void adicionar(Usuario usuario) {
		validator.addAll(Hibernate.validate(usuario));
		if (!validator.hasErrors()) {
			if (query.hasUsuarioByLogin(usuario.getLogin())) {
				validator.add(new ValidationMessage(
						"já existe um usuário com o login " + usuario.getLogin(),
						"login"));
				return;
			}
			helpdesk.add(usuario);
		}
	}
}
I

Olá rapazes, desculpem pela demora. :frowning:

Sergio Taborda,

Pergunta1: Não é muito usado. Mas se for um sistema de chat como o exemplo que citou no último quote deste post, vai ser necessário senão o chat se manteria desatualizado na tela, certo?

Pergunta2: “O mecanismo que traduz o clique no botão para a chamada ao método no presenter está na visão.” Não entendi, desculpe. A visão não conhece o Presenter, certo? Então como ela vai chamar um método no Presenter?

Pergunta3: Talvez por não conhecer quase nada de JAVA WEB eu não entendi o que quis dizer nessa resposta.

sergiotaborda:
Sim, o presenter é muito mais “controlador” que o controler do MVC. Infelizmente os nomes do MVC foram mal escolhidos ( deveria ser algo mais como Renderização-Componente-Dados)

Imagine um sistema de chat. Quando A envia uma mensagem a B ela chega pela camada abaixo do apresentação, ela chega pelo M do MVP. O M então precisa avisar o P que chegou uma mensagem para que o P faça algo com ela. Outro exemplo seria o sistema através do M avisar que a rede caiu e o P , sabendo isto, faz aparecer algum icon em algum lugar da V.
É por isso que o M pode ter que avisar o P. O P controla o estado de apresentação e a apresentação não depende apenas do que o usuário faz, depende tb do que o sistema faz e do que outros usuários fazem quando o sistema é multi-usuario. É por isso o MVP é mais natural para a camada de apresentação que o MVC.

Lavieri,
Obrigada por mandar um exemplo quase pronto para me ajudar… :smiley: Gostei muito da explicação do mvp, mesmo sendo para WEB, dá para entender bem a idéia e tentar transformá-la em desktop.
Já havia escutado sobre VRaptor mas nunca usei. Eu estou elaborando um post mais técnico e específico para ver se alguém desafia responder essas minhas dúvidas que estão me deixando bem confusa em relação, agora, ao mvc. Estou entendendo bem a idéia que vocês estão mostrando mas sempre que observo um exemplo novo, mesmo sabendo que ele está lá para me ajudar, minhas dúvidas aumentam ainda mais… :cry: :?

Pedro Muyala,
Concordo com você quando fala sobre ‘embasamento teórico’ mas um pouco de código também ajuda a entender, não acha? Até mesmo algumas de suas postagens anteriores (lá nas páginas 9, 10) alguns amigos explicavam como montar o mvc através de códigos mesmo… chegou a falar até de exception’s se não me engano. Na verdade as minhas dúvidas são bem técnicas, mesmo eu me apreendendo em um exemplo simples, como o de uma agenda. E concordo quando diz que um pattern deveria ser de um Único Entendimento. Na próxima postagem vou fazer perguntas mais específicas e separadas por números para que as respostas fiquem bem definida para aquela pergunta e não para um todo. espero também estar ajudando assim no seu tópico.

Obrigada a todos meninos! :smiley: Estou muito feliz por todos. :wink:

I

Olá rapazes, eu novamente com as perguntas que comentei elaborar. :smiley:

O que realmente está difícil de entender é porque as implementações (tanto MVC quanto MVP) não seguem o desenho da arquitetura?
Nessa postagem vou focar no mvc.

Veja:



Olhando as imagens acima que mostram o formato da arquitetura MVC entendi que no desenvolvimento Desktop com Swing:

Ponto1: Cada letra do mvc é um pacote ‘package’.
Ponto2: O mvc trabalha dentro da camada e não ‘jampeando’ camadas.
Ponto3: Seu uso é melhor empregado na camada de cliente e na camada de apresentação.
Ponto4: O modelo é quem envia/recebe dados da camada inferior ( a de baixo ) quando necessário.
Ponto5: O modelo é o lugar onde as coisas acontecerão de verdade. As funcionalidades estão nele. Pode ser uma única classe ou ‘n’ classes.
Ponto6: O modelo ‘só e somente’ notifica a visão de alterações em seu estado através do pattern observer ( ou outra forma de associação indireta ).
Ponto7: O modelo não conhece o objeto do controlador que está alterando seu estado. E só conhece o objeto da visão ( o listener implementado por ela ) através do pattern observer, pois esse objeto se registra no modelo como ouvinte dos eventos de notificação gerados por ele próprio.
Ponto8: O controle é quem define o comportamento dos ‘eventos’ que chegam da visão para realizar mudanças de estado no modelo.
Ponto9: O controle conhece o objeto modelo e o objeto visão.
Ponto10: O controle altera o modelo chamando seus métodos diretamente ( ou outra forma de associação direta ).
Ponto11: O controle seleciona outra visão a ser exibida se em uma determinada situação que ocorrer tornar-se necessário.
Ponto12: A visão é quem interage com o usuário.
Ponto13: A visão só conhece o objeto do controle ( o listener implementado por ele ) através do pattern observer, pois esse objeto se registra na visão como ouvinte dos eventos gerados por ela própria.
Ponto14: A visão ‘só e somente’ manda um user gesture para o controlador através do pattern observer ( ou outra forma de associação indireta ).
Ponto15: A visão conhece o objeto modelo e o consulta para se reenderizar chamando seus métodos diretamente ( ou outra forma de associação direta ).

Se esses 15 pontos estiverem corretos exitem algumas dúvidas por trás dessas imagens que não são esclarecidas e são elas:

Dúvida1: Se o main ou um outro objeto cria as instancias da visão, controle e modelo, como um irá conhecer o outro? Serão passados por referência? Ex:

public class AgendaVisao implements iAgendaVisao { }
public class AgendaControle implements iAgendaControle { }
public class Agenda {
   public static void main(String args[]) {
      AgendaModelo m = new AgendaModelo();
      AgendaVisao v = new AgendaVisao(m);
      AgendaControle c = new AgendaControle(v,m);

      m.addModeloListener(v);
      v.addVisaoListener(c);
   }
}

Dúvida2: Como o controle seleciona uma nova visão? Ele vai instanciar uma nova visão, um novo modelo, ou seja, vai fazer o papel que está fazendo o main acima ( do código )?
Dúvida3: Em nenhum momento o controle chama métodos para ‘puxar’ dados da visão para ele. Ou seja, ele não deverá fazer isso, certo? Ele não foi criado para isso.
Dúvida4: Se é verdade as dúvidas 4 e 5 então o mvc não foi criado para formulários/entrada de dados, sendo esse problema corrigido com o padrão mvp?
Dúvida5: Quando eu clico em um JButton que está sendo exibido na visão, na verdade, eu estou interagindo com um controlador (o JButton) que lança um evento chamado ‘user gesture’, correto? O mesmo valeria se eu clicasse em um JComboBox, saisse de um JTextField, entre outros componentes do swing, certo?

Dúvida 6 e trivial: Na verdade, olhando as imagens que tentam mostrar a arquitetura mvc você tem esses 15 pontos que citou acima, porém o que ocorre de fato é uma interação do usuário com o controle. Seu main chama um controle e ele definirá qual visão será exibida e qual modelo usar naquele momento. É ele também quem faz a ligação entre a visão e o seu modelo com o observer. Na verdade, a visão recebe o ActionListener do controle e instala (coloca ele para ouvir) os eventos de determinados botões na visão, que não passam de controladores. Seria como o exemplo citado pelo Lavieri na página 14 só que entrada de dados nos controladores exibidos na visão (ex: JTextField) não podem ser lidos pelo controle nem passados pelo evento. É isso :?:

E lembrem-se: é somente uma simples agenda em desktop. Percebam que não uso absolutamente ferramenta nenhuma a não ser um Bloco de Notas (é isso mesmo, NOTEPAD) e as linhas de comando java e javac. Tenho certeza que vão ler isso e me indicarem muitas ferramentas… mas não quero no momento. quero aprender bem o básico e simples.

Obrigada meninos pela paciência, por toda a ajuda que postam, leio elas com muito carinho e faço o possível e impossível para enteder tudo. :smiley:
Desculpem minha dificuldade faz pouco tempo que comecei a estudar Java (não tem um ano e meio)… Vou aguardar pelas respostas.
Gostei do sistema de resposta que o Sergio Taborda adotou, respondendo item por item no assunto de mvp em alguns posts anteriores, ficou bem didático.
Até +…

Lavieri

não terminei de ler, então vou respondendo logo um ponto onde discordo (teoricamente do que disse) …

O modelo não conhece a view, o modelo não conhece o Listener implementado por ela, através do pattern Observer…

O modelo na verdade define uma Interface para quem quiser Ouvilo, ou seja uma interfacepara seu Listener … quem quer que implemente a interface não será conhecido pelo modelo… ela apenas checa a lista de objetos que se registraram como listener… todos esses objetos para o modelo são apenas as interfaces que ele definiu, então ele usa o método definido na interface (que é parte do modelo) … e ai que alguem recebe a informação…

Portanto o modelo não conhece ninguem neste ponto… nem a view, nem o controller…

Falando de implementação eu custumo implementar o listener no Controller (para deixar view mais solta) … o controle recebe as notificações e ele avisa a view sobre a alteração… assim tanto a view como o modelo ficam mais livres…

se vc implementa na view a interface Listener do modelo, estará mais acoplada ao modelo… fazendo isso no controle fica mais solto ao modelo…

Como o controller já é ligado ao modelo e a view, então não há problemas de acoplamento

Edit:
Aquela linha indireta onde há a seta MODELO —> VIEW é pq o modelo indiretamente pode passar informações diretamente a view… mas isso ele faz sem conhcer a view, ele só conhece o proprio modelo… a Interface Listener é parte do modelo, portanto ele não conhece a view, e é por isso que é dito que a informação é passada indiretamente…

Edit2:

aqui vale o mesmo raciocinio acima… a view não conhece o controle neste … isso é indireto, a view conhece é a interface do Listener que faz Parte da view, quem a implementa e se registra nela, não é conhecimento da view, é algo feito com desacoplamento total…

Lavieri

Não, o controle não define… isso… isso já esta definido… o controle só faz acontecer…

Por exemplo… se a view em um botão SALAR, e nele esta o FOMRULÁRIO de USUARIO, ao clicar em SALVAR, o controller não define o comportamente do evento… ele apenas conhece a view suficientemente, para conhecer a ROTA o destino, o que deve acontecer…

Ele então, ao acontecer o clique no botão… pega os dados do formulário, e envia lá para baixo, para o modelo salvar… o modelo salva, e ele ratorna informando que tudo ocorreu bem… e por exemplo dando um disable no botão de salvar…

O trabalho do controle é este… a view existe pra fazer algo … mas a view não sabe quem pode faze-lo
O modelo é quem faz as cosias … e esta apenas esperando por ordens…

o controle sabe o que a view quer fazer, algo, e sabe que parte do modelo é capaz de fazer… então ao ver que um evento aconteceu na view, ele faz o evento passar da view para a parte correta no modelo, fazendo aquilo acontecer…

Lavieri
ingridfarabulini:
Ponto1: Cada letra do mvc é um pacote 'package'.
Não necessariamente... vc pode ter uma estrutura de pacotes mais complexa, mas pode ser assim tb.
ingridfarabulini:
Dúvida1: Se o main ou um outro objeto cria as instancias da visão, controle e modelo, como um irá conhecer o outro? Serão passados por referência? Ex:
public class AgendaVisao implements iAgendaVisao { }
public class AgendaControle implements iAgendaControle { }
public class Agenda {
   public static void main(String args[]) {
      AgendaModelo m = new AgendaModelo();
      AgendaVisao v = new AgendaVisao(m);
      AgendaControle c = new AgendaControle(v,m);

      m.addModeloListener(v);
      v.addVisaoListener(c);
   }
}
uma forma melhor de fazer isso é
public static void main(String args[]) {
    new AgendaController().start();
}
public class AgendaController {
    private AgendaModel agendaModel; 
    private AgendaView agendaView;

    public void start() {
         agendaModel= new AgendaModel();
         agendaView= new AgendaView(agendaModel); //isso não é bom <== estou apenas exemplificando
         agendaView.exibir();
    }
}

Exemplifiquei acima, conforme o modelo que vc apresentou, abaixo vou colocar uma forma que acredito ser melhor

quando falo que akilo não é bom... é pq o ideal é que seja assim como esta abaixo

public class AgendaController implements SalvarListener, ListarListener, ExcluirListener etcListener {
//acima coloquei vários listener, apenas para efeito didatico, para deichar tudo em um único controle

    private AgendaLogic agendaLogic; //agenda lógic é parte do modelo
    private AgendaView agendaView;

    public void start() {
         agendaLogic = new AgendaLogic();
         agendaView= new AgendaView();
         agendaView.exibir();
    }

    //evento escutando salvarListener
    public void salvarListener(EventoSalvar eventoSalvar) {
        Pessoa pessoa = eventoSalvar.getPessoa(); //aqui eu pego a pessoa populada a partir do evento salvar
        //o agenda view poderia ser resgatado através de algo como eventoSalvar.getSource();
        agendaLogic.salvar(pessoa);
        agendaView.getBotaoSalvar().setEnable(false);
        agendaView.showMessage("Pessoa salva com sucesso");
        //vc pode mudar de tela ou fazer outras coisas...
    }

    public void excluirListener(EventoExcluir eventoExcluir) {
        agendaLogic.excluir(eventoExcluir.getPessoa());
       //... etc
    }
}

enfim... essa é a minha forma de fazer

Lavieri

ingridfarabulini:
Dúvida2: Como o controle seleciona uma nova visão? Ele vai instanciar uma nova visão, um novo modelo, ou seja, vai fazer o papel que está fazendo o main acima ( do código )?

uma forma de fazer ?

new ControleDeOutraView().start(); this.finish();

outra forma de fazer ???

controlePrincipal.startView2(); //ou seja, todo controle tem uma referencia ao controle principal, que sabe como iniciar o controle de cada view this.finish();

vai puxar sim… como no exemplo que coloquei mais a cima… ele puxa informações da view, e repassa para o modelo… a VIEW não deve alterar o estado do modelo… isso é trabalho do controlle … (da ate pra alterar, mas ai tem q ser por meio indireto com observers… e nesse caso o resposável por registrar os observers é o controle)

não vou entrar no merito do MVC ou MVP, não li muito sobre MVP … mas continuo afirmando que a resposta é que o MVC foi sim criado pra isso também…
o Controller é quem altera o estdo do modelo… e o controle tem ligações de forma solida tanto com a view com com o modelo… portanto ele pode sim pegar as informações da VIEW e repassar ao modelo…

vc esta interagindo com a view… a view pode ter milhoes de respostas para as suas ações… por exemplo… dar FOCO pode siginificar alterar a cor do contorno do field para vermelho… isso é a view quem faz…

o Controller pode é registrar observers para ouvir ações do usuário e assim também responder a esses eventos… mas ele só consegue responder aos eventos pq a VIEW esta interagindo… é a view quem dispara a varrer todos os listener e enviar os eventos para quem escuta… portanto a interação é com a view

Como falei acima, não é o controle quem define as coisas… o controle apenas faz a “implementação” ele … conhece o modelo e a view, portanto o controle fazo meio de campo… as interações com a view são com a view… toda interação com a VIEW gera um evento… o controle pode capturar o evento, e fazer ele ir para no modelo, pegar infos do modelo e colocar nos lugares corretos da view…

vc inicia o programa com new ControllerX.start(); apenas por comodidade… isso não quer dizer que o programa é o controle apenas é mais facil assim…

pedromuyala

ingridfarabulini:

Pedro Muyala,
Concordo com você quando fala sobre ‘embasamento teórico’ mas um pouco de código também ajuda a entender, não acha? Até mesmo algumas de suas postagens anteriores (lá nas páginas 9, 10) alguns amigos explicavam como montar o mvc através de códigos mesmo… chegou a falar até de exception’s se não me engano. Na verdade as minhas dúvidas são bem técnicas, mesmo eu me apreendendo em um exemplo simples, como o de uma agenda. E concordo quando diz que um pattern deveria ser de um Único Entendimento. Na próxima postagem vou fazer perguntas mais específicas e separadas por números para que as respostas fiquem bem definida para aquela pergunta e não para um todo. espero também estar ajudando assim no seu tópico.

Obrigada a todos meninos! :smiley: Estou muito feliz por todos. ;)

Olá Ingrid, tudo certo?

Sim com certeza o uso de código-exemplo ajuda. Na verdade, como você mesma alega, é melhor aprender o básico. O básico, na minha humilde opinião, é teorico. Entendendo bem as complexidades teoricas aí sim poderá designar do seu tempo para sustentar a parte de codificação. Desculpa se me expressei mal, não quis izer que não era para postar código, longe disso, quem sou eu para dizer isso. :oops:

:arrow: Mas olha depois dessa explicação acima do gujman lavieri (por sinal, a senhora faz perguntas muito inteligentes, até parei de perguntar um pouco para não quebrar seu raciocínio) ao meu ver o difícil agora é não conseguir entender… ficou muito visível e perceptível o funcionamento de um MVC, se bem que é aquilo que comentou anteriormente que olhando para a figura e olhando para a forma de implementar tá tudo diferente… nunca iria imagina que na verdade a seta tarcejada que vai do model para a view significava outra coisa! Nunca imaginaria que os eventos de notificação podem ser descarregados no controle… Acho que ninguém mais vai discordar dessa explicação acima não enxergo outra forma de fazer.

Enfim só posso agradecer aos dois pelo bom andamento do tópico e obviamente a todos os demais que vieram colaborando. :slight_smile:
Se tiver dúvidas, sugestões, opiniões diferentes, visões diferentes ou críticas, por favor não deixe de postar! Só assim podemos nos ajudar. :wink:
[size=14]SUCESSO A TODOS! Continuem conosco.[/size]

rylphs

pedromuyala, desculpe me intrometer no seu tópico, mas estava pesquisando sobre MVC e acabei achando esse tópico que por sinal esclareceu muitas coisas. Ainda tenho algumas dúvidas e gostaria que colocá-las aqui.

  1. Se entendi direito, o MVC é aplicado a uma camada só, geralmente a camada de apresentação, é isso mesmo? E no caso do MVP, seria a mesma coisa?
  2. Nesse caso, os modelos que eu estaria lidando só estariam relacionados a essa camada de apresentação, como um tableModel por exemplo?
  3. No caso de uma aplicação desktop com swing, ele já implementa o MVC? O que eu teria que implementar nesse caso? Como faria a interação MVC dentro da apresentação?
  4. Se eu precisasse persistir os dados de um form de cadastro, quem faria a conversão do modelo da apresentação para o modelo de domínio? Seria o presenter do MVP (caso use MVP)?
  5. Seria a mesma coisa no caso de eu precisar obter os dados de um banco de dados e exibí-los em um JTable?

Me desculpem se o que estou perguntando é muito óbvio. Eu achava que entendia o MVC, mas lendo esse tópico e alguns artigos a respeito vejo que a coisa é um pouco diferente.
Parabéns pedromuyala pela iniciativa, esse tópico já me esclareceu muita coisa. :wink:

Abraços, Raphael.

Lavieri

heheh eu ia procurar essa thread agora… não estou respondendo o colega acima, mas gostaria de complementar um pouco as informações que coloquei mais acima…

Os tais beans de informações que falei, que transitam entre todas as camadas e que fazem parte do modelo, eles podem ser melhor representado pelo Modelo de Dominio…

segue uma ilustração que demonstra como o Domain Model tem passe livre por todas as camadas…

desta imagem vale lembrar que:

  • Business Layer e Data Access Layer fazem parte do Modelo, e apenas do modelo…
  • Presentation Layer faz parte da View
  • O Controller se localiza entra a Presentation e a Business Layer, mediando os 2, para que elas sejam fracamente acopladas…

Obs.: apeas do caminho mostrado na ilustração ser do cliente passando informações para o modelo, essas ligações entre as camadas são vias de mão dupla, e o Domain Model, tranzita entre as camadas, tanto indo em direção ao database, como ao cliente…

Portanto, os beans ou entidades que tranzitam com informações fazem parte do “Domain Model”, e apesar de pertencer ao M do MVC, tem tranzito livre entre as camadas…

Em alguns casos em projetos modulados o Domain Model pode ser separado em um jar… e no minimo, para uma boa organização, o Model deve ser separado em um pacote… segue um exemplo de um projeto meu…

pedromuyala

Boa tarde companheiros gujeiros, é feriado!

Intormeter? Que é isso! O tópico está aqui para isso mesmo. O que eu tenho da minha parte a dizer é desejar os PARABÉNS por estar participando.
Suas perguntas são identicas a de muitas pessoas e devem ser respondidas. Eu sempre estou pedindo para os companheiros postarem suas dúvidas, perguntas, críticas, sugestões… sempre!
E para manter a qualidade, vou fazer um “quote” para cada pergunta.

Não. O modelo MVC (assim como o MVP, uma variante do MVC) pode ser aplicado dentro de qualquer uma das camadas que tiver. Lógico, por força maior, ele será implementado “na maioria das vezes” nas camadas que interagem com o usuário. Ex: Cliente e Apresentação. Vale sempre lembrar que o MVC não faz “jamper” entre camadas, ele não está ligando camadas uma a outra.

TableModel é um modelo que faz parte dos componentes do Java Swing. Quando você cria um objeto JTable você está criando uma instancia do controlador JTable, ou seja, JTable é um controlador. Sua visão e seu modelo são imediatamente criados também. Dentro da sua camada de apresentação esses três objetos estarão presentes (MVC). Quando você clica em um campo da visão do JTable, na verdade, o que ocorre é uma interação do usuário com o controlador JTable. Esse, por sua vez e se necessário, lança um evento para quem quiser ouvir (podendo ser um outro controlador). Você poderá criar outros objetos que farão parte da camada de apresentação. Vale lembrar que, para existir alta coesão e baixo acoplamento, legal seria esses objetos trabalharem apenas na sua camada de origem, sendo que para se comunicar com camadas inferiores ocorre-se uma tradução. (Vai entender melhor vendo este link.)

Na verdade, os componentes swing JFrame, JPanel, JTextField, JButton, etc. são controladores. Quando você vê na tela uma janela aberta, o que está enxergando é a visão do componente. O modelo também está lá presente aguardando que algo seja consultado ou modificado. A visão exibe os dados presentes no modelo naquele momento, estando apta a se reenderizar sempre que o respectivo modelo for alterado. Quem está mediando essas partes é o controlador, como explicado nas postagens do Lavieri acima. Isso tudo está na VISÃO! Mas, espera aí, eu perguntei em uma aplicação? Como faria a interação MVC dentro da apresentação?

Veja a imagem abaixo:

Tudo isso acima está na Camada de Apresentação. Lembre-se: Camadas são abstratas. No Swing, o main é um controlador (não aparece na imagem). Ele cria o objeto controlador da sua aplicação(Ex: JCadastro.). JCadastro cria um objeto de JFrame (controlador instanciou outro controlador). JFrame cria um objeto de JPanel (novamente controlador instanciando outro controlador). JPanel cria um objeto de JTable, mantendo a lógica. Repare que cada controlador (JFrame, JPanel,…) instancia seu respectivo Modelo e Visão (até JCadastro) e que cada controlador pode lançar um evento externo. Quando o usuário pressiona uma tecla em uma célula da JTable quem está recebendo o evento de “tecla x pressionada” não é a visão, mas sim o controlador JTable. O controlador vai encaminhar essa informação para o modelo que vai se atualizar e fazer com que a visão se reenderize e exiba a tecla x pressionada dentro da célula. Repare que, ele realizou toda a sua função prevista dentro da visão da sua camada de apresentação, o que responde a sua pergunta. Mas quem gerou o evento de “tecla x pressionada”? Foi algum objeto controlador responsável pelo teclado.

Agora vem o detalhe importante, que fará as coisas terem sentido. Observe a imagem e localize o JTable em azul. Perceba que NÃO está sendo mostrado na imagem o evento que o modelo lança para a visão (que na verdade é intermediado pelo controle, segundo Lavieri nos posts acima) sempre que necessário realizar uma reenderização. MAS é mostrado em um círculo os eventos que são de comunicação externa, ou seja, com o outro controlador. Entenda: Assim como o objeto controlador de teclado gerou e lançou um evento para o JTable, o JTable vai gerar e lançar um evento para o controlador da Camada de Apresentação (que vai estar escutando a visão e esperando por eventos gerados nela).

Sim. No caso de usar o MVP.

Sim. Para esclarecer mais dúvidas das duas situaçãoes, recomendo este link aqui.

E PELO AMOR DE DEUS não sei se o que respondi está correto. Eu venho estudando este tópico quase que diariamente, procuro fontes na Internet, no meu dia-a-dia… tudo que respondo é baseado naquilo que estou entendendo, ou seja, pode muito provavelmente ter inúmeros erros! E peço por favor para todos que prestem muita atenção na minha respostas e me alertem de erros porque senão acabo prejudicando muitos companheiros no lugar de estar ajudando.

Muito obrigado mais uma vez pela postagem, espero que não abandone o tópico. Um abraço. :wink:

pedromuyala

Olá Lavieri, tudo bom? Obrigado rapaz por estar ajudando aqui com o tópico.

Lendo isso preciso perguntar porque se for real vai derrubar alguns dos conceitos que aprendi aqui mesmo neste tópico: Percebi que você distribui o MVC pelas camadas, melhor dizendo, “jampeou” as camadas, isso é correto? :shock:

Assim eu até este momento entendia que o MVC era aplicado na camada, assim:

  • §resentation Layer (onde está presente o MVC);
  • (B)usiness Layer;
  • (D)ata Access Layer;

Para P se comunicar com B, o objeto do modelo em P chama o método necessário do objeto da visão presente em B.
Para B se comunicar com D, o objeto do modelo em B chama o método necessário do objeto da visão presente em D.
Para D se comunicar com B, o objeto do modelo em D chama o método necessário do objeto da visão presente em B.
Para B se comunicar com P, o objeto do modelo em B chama o método necessário do objeto da visão presente em P.
Isso é o que eu sei. Não sei se existe algum padrão para comunicação entre camadas (andares) mais eficiente, isso era uma das minhas próximas perguntas. :?
Mas uma certeza que tinha até este momento é que o MVC != Camadas, segundo PCalcado no Fragmental e Sergio Taborda e até mesmo você!

Outra coisa que não entendi é esse “Domain Model” isolado e utilizável para todas as camadas.
Por favor Lavieri, peço que me explique onde estou errando, se for possível, claro?

[size=14]E pessoal não se envergonhem de fazer as perguntas, críticas, sugestões, opiniões contrárias… Tudo vai colaborar a todos os companheiros!
Mais uma vez obrigado a todos da administração do GUJ e seus moderadores pela oportunidade.
Ficarei no aguardo por respostas![/size] :wink:

Lavieri

Já li isso do MVC dentro de uma camada, no blog do sergio taborda, eu discordo, e vc pode encontrar isso em N bibliografias, q ainda vou discordar, até alguem me dar um motivo válido....

O Swing é feito com MVC, mas isso não quer dizer que MVC = VIEW ... mvc é para separação dos seus componentes....

por exemplo, veja esse texto retirado do Wikipidia http://pt.wikipedia.org/wiki/MVC

"Wiki":
Note: A partir do momento em que dividimos os nossos componentes em Camadas podemos aplicar o MVC nestas. Geralmente isto é feito definindo a Camada de Negócios como o Model, a Apresentação como a View. O componente Controller exige um pouco mais de controle. Logo, cuidado para não confundir MVC com separação de camadas. Camadas dizem como agrupar os componentes. O MVC diz como os componentes da aplicação interagem.

Portanto na minha opinião, e na retirada deste texto, MVC e camadas não tem nada a ver um com outro... tanto que quando falei do MVC, o M (Model) agrupa 2 camadas, "businnes" e "persistence", o Domain Model é criado dentro do business, faz parte dele, mas transita dentro de todas as camadas.

A camada de persistence não aparece na imagem dos meus pacotes que coloquei aqui como exemplo, elas não aparecem pq minha camada de persistencia fica em um .jar do meu projeto, mas também é uma camada bem definida e separada...

..............

pedromuyala:
Outra coisa que não entendi é esse "Domain Model" isolado e utilizável para todas as camadas.
Bom, vc já trabalhou com Hiberante ou outro domain store ? se já fica bem fácil de entender, se não vou tentar explicar...

Em seu projeto sempre existem objetos de dominio, que contem informações, esses objetos são os que são persistidos, como são persistidos tem que descer até a camada de persistencia, eles precisam ser recuperados, e processados na camada de negocio, a camada de apresentação precisa exibir suas informações portanto eles vão até la também....

Vamos a um exemplo pratico...

package br.com.guj.livraria.domain; //objeto de dominio
public class Livro {
    private String nome;
    private double preco;
    private Categorai categoria;
    public String getNome(){...}
    public void setNome(String nome){...}
    public double getPreco(){...}
    public void setPreco(double preco){...}
    public Categoria getCategoria(){...}
    public void setCategoria(Categoria categoria){...}
}

Conciderando o que falei.... Model engobla o dominio (ou seja esse livro) o businees (as regras de negocio) e o persistence (ou seja a cama de persistencia)...

pckage br.com.guj.livraria.business; //regra de negocio
public class AcervoService {
    private DomainStore livraria; //esse vem da camada de persistencia
    private Queries queries; //esse vem da camada de negocio mas faz buscas na camada de persistencia
    private Validador validador; //esse é da propria camada de negocio
    public void addLivro(Livro livro) {
         if (validador.valido(livro));
            livraria.add(livro);
    }
    public void devolverLivro(Livro livro) {
         Emprestimo emprestimo = queries.forEmprestimo().ultimoByLivro(livro);
         emprestimo.setDevolvido(true);
         emprestimo.setDataDevolucao(new Date());
         livraria.merge(empretimo); //merge é o mesmo que atualizar
    }
    public boolean emprestarLivro(Livro livro,Pessoa pessoa) {
         Emprestimo emprestimo = queries.forEmprestimo().ultimoByLivro(livro);
         if (emprestmo != null) //caso o livro esteja emprestado não pode emprestar
            return false;
         emprestimo = new Emprestimo(livro,pessoa);
         livraria.merge(empretimo);
         return true;
    }
}

bom a partir daqui temos que a camada de persistencia pode conhecer ou não a camada de negocio (business), depende do seu nivel de abstração, usando Hibernate por exemplo, a camada de negocio nem precisa conhecer a de negocio....

a camada de negocio definitivamente não conehce a VIEW, nem um eventual CONTROLE, necessário para acoplar a view a camada de negocio.... assim nela não há códigos para view nessa camda....

o camda "view" quer por exemplo exibir um livro, para fazer isso, ela usa um objeto de DOMINIO, o objeto "Livro" esse é o objeto que tranzita entre todas as camadas, as vezes é possivel adaptar um objeto para a view não ter q manipular direamente um objeto de dominio, mas geralmente não se faz isso...

em um dado momento, escolhido o livro, o usuário quer tomar ele emprestado.... nesse momento ao clicar no botão "EMPRESTAR" da view, o objeto de negocio AcervoService deve ser ativado, usando-se o método emprestarLivro(livro,pesso) ... a view não precisa conhecer as regras de negocio, então no MVC controi-se um controle para mediar essa chamada... então

View no controle

pckage br.com.guj.livraria.controll; //controle para se ligar com uma view JSP

public AcervoController {
//...
    public void emprestarLivro() { //aki exitem mil maneira de recuperar os objetos da view
         //vou mostar uma da web.
         String idString = (String)request.getAttribute("livro.id"); //essa string vem em um post de um form.
         Integer id = Integer.valueOf(id);
         Livro livro = acervoService.buscarLivro(id);
         Usuario usuario = (Usuario)session.getAttribute("usuario"); //um usuário logado na sessão
         Pessoa pessoa = usuario.getPessoa();
         request.setAttribute("livro",livro); //colocando o livro para pode ser exibido em uma página por exemplo
         if (acervoService.emprestarLivro(livro,pessoa));
              response.sendRedirect("/pagianDeSucesso.jsp");
         else
              response.sendRedirect("/pagianDeFracasso.jsp");
    }
//....
}

bom la na view vc também vai usar o objeto livro para exibir as informações do livro que foi emprestado....

enfim... espero ter ajudado...

rylphs

Obrigado pedromuyala, pela atenção. Acho que agora estou sacando melhor a coisa.

pedromuyala:

Não. O modelo MVC (assim como o MVP, uma variante do MVC) pode ser aplicado dentro de qualquer uma das camadas que tiver. Lógico, por força maior, ele será implementado “na maioria das vezes” nas camadas que interagem com o usuário. Ex: Cliente e Apresentação. Vale sempre lembrar que o MVC não faz “jamper” entre camadas, ele não está ligando camadas uma a outra.

Me desculpa, não perguntei direito. Eu perguntei exatamente se o MVC não fazia essa ligação entre as camadas, mas já entendi. Eu estava chegando a essa mesma conclusão, mas lendo o post do Lavieri acima e vendo algumas definições na internet, estou mudando um pouco de opinião. Conforme aquele link falando sobre a evolução do MVC:

Essa é opinião de um ignorante no assunto, mas pelo que eu entendi, a idéia inicial do mvc era a de ligar justamente a parte de visualização com a parte de negócios. Você pode ser mais específico e aplicar a idéia na camada de apresentação como o swing faz, ou você pode considerar isso a um nível mais abstrato e implementar isso nas camadas como um todo. Well, it’s only my two cents!

pedromuyala

Fala Lavieri, boa tarde! :slight_smile:

Eu sei que não citou isso, mas pode ter certeza que confio claramente no que está afirmando. Tanto é verdade que estou perguntando sobre seus exemplos porque estou confiando cegamente naquilo que está afirmando. E digo mais: Das quinze páginas postadas que acompanho durante a quase um ano você está sendo a pessoa esclarecedora sobre o assunto, transformando a explicação técnica de forma popular, legível, exemplificada, lê as postagens e entende muito bem as perguntas antes de responder e quando responde se arma de argumentos fortes para não restarem dúvidas. Não que esteja desmerecendo o bom trabalho de todos os companheiros que por sinal já ajudaram e muito. :-o

Exatamente o que pretendia fazer. Após definir o MVC na Camada (o que já não estou acreditando mais, como você mesmo diz, que me apresentem algo válido do porque não trabalhar na forma que mostrou acima) minha principal próxima questão seria: Como as camadas interagem uma com a outra, sendo que, por exemplo, a Apresentação usa MVC mas a Camada de Negócios não usa, como elas se falariam, então? :roll: :roll: :roll:

Mas você já esclareceu na sua última postagem acima. :stuck_out_tongue: Está mais do que claro, só posso agradecer por ter exposto sua idéia aqui. É isso que peço a todos os companheiros que mostrem sua forma de pensar sobre o MVC mesmo que sejam interpretações diferentes. Esse assunto que muitas vezes é mal explicado tem que ficar claro para todos. Esse é o objetivo das três letrinhas.

Lavieri, parabéns. Espero que continue aqui conosco sempre atento e sempre que puder acrescentar, por favor, não se acanhe, poste.
Um abração companheiro, mais uma vez muito obrigado pela colaboração. Sucesso. :wink:

D

O que é isto, span no GUJ, não, por favor não.

Lavieri

@pedromuyala

é o seguinte… MVC é uma separação de componentes, vc pode muito bem aplica-lo a uma única camada, afinal toda camda tem sua VIEW (a interface que ela expoem para as outras camadas usarem) tem seu modelo de negocio, ou seja a implementação real, o como ela funciona… tem objetos de dominio, ou seja informações que ela passa para fora da camada a través de suas interfaces… e em projetos maiores, vc pode precisar de um controle, isso serve mais quando vc tiver mais de uma implementação…

Quer um exemplo de onde isso ocorre ?

javax.persistence.*;

o JPA, Java Persistence API é a view do especificação, ela é bem difinida, é nela há todas as interfaces usadas quando vc trabalha com a API…

O Hiberante ja tinha um objeto que fazia tudo que esta API queria… então, o Hiberante criou um adaptador para ligar as regras de Negocio dele (ou seja um Session do hiberante) a view do JPA…

sendo assim, vc pode dizer que nesse caso…

VIEW = a especificação JPA MODEL = a session do Hiberante CONTROLLER = o adaptador, que transforma uma requisição do JPA em uma requisição que a Session entende.

Enfim a view é escrita sem se importar com a implementação
o Modelo foi escrito antes mesmo dessa view existir (Session do hiberante veio antes da especificação do JPA)
o Controller foi feito para mediar, essas duas partes que não precisam se conhecer.

neste caso é um uso meio ao contrario do MVC hehehe… afinal vc tem 1 VIEW o JPA e tem várias dominios que usam essa mesma view… há varias implementações desta especificação, TopLink, OpenJPA…

Enfim MVC é a forma que vc vai organizar as coisas, ele se preucupa principalmente com a separação de responsabilidade e com o baixo acoplamento.

Se vc não conhce hiberante ou jpa e não entendeu o exemplo que dei, não fique triste, um dia vc vai acabar usando Hibernate ou Jpa ^^

Obs.: Não estou aqui afirmando com 100% de certeza, as implementações de JPA usam MVC! … não é isso … o que estou falando é que a forma que hiberante implementa a especificação se aproxima bastante do MVC…

pedromuyala

Putz Spam denovo é de doer o coração hein! Lembro que no começo também ocorreu algo relacionado a SPAM! Lá nas primeiras postagens. :shock:
Mas se for, entenda bem, SE FOR para ajudar aí o pessoal a continuar mantendo o GUJ lindo do jeito que está… pode colocar mais kkkkkk… :stuck_out_tongue:

Opa Lavieri, beleza homem?
Mais uma vez obrigadão por toda atenção e tempo que está desprendendo em ajudar cara, parabéns mesmo.
A cada postagem sua a coisa vai ficando cada vez mais transparente e até mesmo fácil. :-o

E pelo que parece os companheiros Gujeiros também estão de pleno acordo com seu fundamento cara, até o momento está sendo bem aceito, reparou?
A sua idéia até agora é a única que não foi rebatida por ninguém, o que é um ótimo sinal, é finalmente o entendimento geral que procuro nas pessoas.
Todos devem conhecer o padrão da mesma forma, esse é o objetivo.

Vou ler e entender sua última postagem com calma volto para responder, caso haja dúvida.
Felicidades, volto a postar o mais breve possível! :wink:

I

Olá meninos, já cheguei! :smiley:

Desculpem não ter escrito antes mas aproveitei esses dias para ler todos as postagens desde o início da conversa e tentar ao menos mostrar algum resultado.
Bom tentei seguir os conselhos da galera. Para usar o Observer, segui o link que o André Fonseca postou. Não coloquei exception até este momento, como indicou o Bruno Laturner. A estrutura do controle segui as explicações do Lavieri. Também não implementei as validações até mesmo porque fiquei com algumas perguntas em aberto, antes de continuar, preciso esclarecê-las.

Vamos ao código:

Inicialização:

public class AgendaIngrid {
   		
       public static void main(String args[]) {
         new AgendaControle();
      }
   }

Visão:

import javax.swing.*;
   import java.awt.event.*;

    public class AgendaView extends JFrame {
     
      private JTextField nome, eMail, telefone;
      private JButton bCadastrar;
       
       public AgendaView() {
         JPanel p = new JPanel();
         p.add(new JLabel("Nome:"));
         p.add(nome = new JTextField(10));
         p.add(new JLabel(" - Telefone:"));
         p.add(telefone = new JTextField(10));
         p.add(new JLabel(" - E-Mail:"));
         p.add(eMail = new JTextField(10));
         p.add(bCadastrar = new JButton("Cadastrar Pessoa >>"));
         add(p);
         setTitle("Agenda Ingrid vs1.0");
         setSize(720,70);
         setResizable(false);
         setDefaultCloseOperation(EXIT_ON_CLOSE);
         setVisible(true);
      }
   
       public void setPessoa(AgendaBean ab) {
         this.setNome(ab.getNome());
         this.setTelefone(ab.getTelefone());
         this.setEMail(ab.getEMail());
      }
   	
       public AgendaBean getPessoa() {
         AgendaBean ab = new AgendaBean();
         ab.setNome(this.nome.getText());
         ab.setTelefone(this.getTelefone());
         ab.setEMail(this.getEMail());
         return ab;
      }
   	
       public void addBotaoCadastrar(ActionListener al) {
         bCadastrar.addActionListener(al);
      }
   	   	
       public void setNome(String nome) {
         this.nome.setText(nome);
      }
   	
       public String getNome() {
         return nome.getText();
      }
   	
       public void setTelefone(Long telefone) {
         this.telefone.setText(telefone.toString());
      }
   	
       public Long getTelefone() {
         return new Long(telefone.getText());
      }
   	
       public void setEMail(String eMail) {
         this.eMail.setText(eMail);
      }
   	
       public String getEMail() {
         return eMail.getText();
      }
   	
   }

Controle:

import java.awt.event.ActionListener;
   import java.awt.event.ActionEvent;

    public class AgendaControle {
    
      private AgendaBean b;
      private AgendaModelo m;
      private AgendaView v;
      
       public AgendaControle() {
         
         this.m = new AgendaModelo();
         this.b = new AgendaBean();
         this.v = new AgendaView();
      	
         m.addModeloListener(
                new ModeloListener() {
                   public void atualizar(ModeloEvent me) {
                     v.setPessoa((AgendaBean) me.getSource()); // Pergunta 1
                  }
               }); 
      	
         v.addBotaoCadastrar(
                new ActionListener() {
                   public void actionPerformed(ActionEvent ae) {
                     m.cadastrar(v.getPessoa()); // Pergunta 2
                  }
               });
      }
      
   }

Modelo:

import java.util.*;
   
    public class AgendaModelo {
    
      private AgendaBean b; // Pergunta 3
    
      private Collection <ModeloListener> modeloListeners = new ArrayList<ModeloListener>();
   
       public void cadastrar(AgendaBean b) {
         this.b = b;
      	// Acessa a camada inferior para persistir...
         this.notificar();
      }
   	
       public synchronized void addModeloListener(ModeloListener ml) {
         if(!modeloListeners.contains(ml)) {
            modeloListeners.add(ml);
         }
      }
   	
       public synchronized void removeModeloListener(ModeloListener ml) {
         modeloListeners.remove(ml);
      }
   	
       private void notificar() {
         Collection <ModeloListener> ml;
         ModeloEvent evento = new ModeloEvent(b);
           
         synchronized (this) {
            ml = (Collection)(((ArrayList) modeloListeners).clone());
         }
      
         for (ModeloListener m : ml) {
            m.atualizar(evento);
         }
      }
   }
public class AgendaBean {
    
      private String nome, eMail;
      private Long telefone;
   
       public AgendaBean() {
         this.nome="N/C";
         this.eMail="N/C";
         this.telefone = new Long(0);
      }
   	
       public void setNome(String nome) {
         this.nome = nome;
      }
   		
       public String getNome() {
         return this.nome;
      }
   	
       public void setEMail(String eMail) {
         this.eMail = eMail;
      }
   	
       public String getEMail() {
         return this.eMail;
      }
   	
       public void setTelefone(Long telefone) {
         this.telefone = telefone;
      }
   	
       public Long getTelefone() {
         return this.telefone;
      }
   }
public interface ModeloListener extends java.util.EventListener {
       void atualizar(ModeloEvent e);
   }
public class ModeloEvent extends java.util.EventObject {
       public ModeloEvent(Object source) {
         super(source);
      }
   }

As perguntas estão no código do controle e no modelo. A 1 e 2 estão comentadas no código do controle, a 3 no modelo.

A pergunta 1 gostaria de saber se está correta a forma de o Observer trazer os dados do modelo para o controle que passa para a visão. Fiquei desconfiada porque no exemplo que segui o controle não faz isso… mas não consegui visualizar outra forma.

A pergunta 2 gostaria de saber se está certa a forma dos dados da visão ser levada ao controle que passa ao modelo? No exemplo que segui o controle parece coletar os dados não diretamente do método get() mas sim do evento. No caso, o source do evento é o JButton… seria obrigada a implementar um Observer para a minha visão toda?

A pergunta 3 é simples mas não sei: É certo instanciar o bean alí? :roll:

Também olhei a última explicação do Lavieri… no caso o controle não pertence a camada nenhuma? AgendaModel.class seriam as regras de negócio?
Acima temos a classe AgendaView.class que está na camada de apresentação, AgendaControle e AgendaIngrid não pertencem a camada nenhuma e as outras o modelo :?:

Acho estar conseguindo… :smiley: Obrigada…
Ficarei aguardando meninos uma confirmação :lol: ou reprovação :cry:

rderoci

Olá pessoal, sou novo aqui e estou cheio de dúvidas… Já lí boa parte do Tópico mas as dúvidas persistem, são elas:

Quanto ao Fluxo do MVC e MVP:

MVC:

  1. O Controller recebe ações do usuário, nunca a view?
  2. O Controller apenas delega o eventos recebidos da View atualizando o Modelo?
  3. Quem notifica a view das mudanças realizadas no Model pelo Controller: O controller? Através do Observer? Ou pelos dois, dependendo de algo que eu não sei? rs
  4. O Controller fala com a visão?

MVP:

  1. A View é quem recebe ações do usuário, nunca o Presenter?
  2. A view notifica o Presenter que delega a atualização/consulta ao Model?
  3. Quem notifica a view das mudanças realizadas no Model pelo Presenter: O Presenter? Através do Observer? Ou pelos dois, dependendo de algo que eu não sei? rs
  4. O presenter fala com a visão?

Queria saber o processo de cada um deles, assim conseguiria entender mais dos dois e conseguiria tirar uma outra dúvida, qual a diferença entre os 2?

Valeu;

pedromuyala

Mesmo não sendo a pessoa certa para responder isso, enquanto isso, vou tentar ajudar. :wink:
Para manter a boa organização, vou citar pergunta por pergunta.

Eu entendo que está correto.

Eu entendo que a forma implementada não é correta. Faria a implementação que citou no final da pergunta (até mesmo olhando um exemplo da página quatorze)

Ao meu ver sim. Senão não tem como você atualizar a visão mandando um evento só com o source da regra. :shock:

ingridfarabulini:
Também olhei a última explicação do Lavieri… no caso o controle não pertence a camada nenhuma? AgendaModel.class seriam as regras de negócio?
Acima temos a classe AgendaView.class que está na camada de apresentação, AgendaControle e AgendaIngrid não pertencem a camada nenhuma e as outras o modelo :?:

Essa prefiro deixar para ele responder hehehehe…

Obrigado por continuar usando o tópico, está colaborando muito! :lol:

sergiotaborda

Não tenho muito tempo agora, então vamos a uma coisa rápida

O problema da sua implementação, Ingrid, é que a classe AgendaControle é na realidade um Presenter e o que vc está tentando fazer é um MVP , não um MVC.
É por isso que está confusa. Vc está fazendo um excelente MVP e achando que é uma porcaria de MVC :slight_smile:

Dito isso, a implementação está em geral correta ( para um mvp)
Apenas alguns detalhes

  1. se usa o agenda bean, não precisa ter get/set para os campos.
  2. telefones são Strings e não integer ( telefones não se somam)
  3. falta um inicio ao seu programa . programas não devem iniciar-se em construtores

Ficaria algo assim

public class AgendaIngrid {
   		
       public static void main(String args[]) {
         AgendaPresenter presenter = new AgendaPresenter();
          // construtores não começam as coisas... 
            presenter.start();
      }
   }

Visão:

import javax.swing.*;
   import java.awt.event.*;

    public class AgendaView extends JFrame {
     
      private JTextField nome, eMail, telefone;
      private JButton bCadastrar;
       
       public AgendaView() {
         JPanel p = new JPanel();
         p.add(new JLabel("Nome:"));
         p.add(nome = new JTextField(10));
         p.add(new JLabel(" - Telefone:"));
         p.add(telefone = new JTextField(10));
         p.add(new JLabel(" - E-Mail:"));
         p.add(eMail = new JTextField(10));
         p.add(bCadastrar = new JButton("Cadastrar Pessoa >>"));
         add(p);
         setTitle("Agenda Ingrid vs1.0");
         setSize(720,70);
         setResizable(false);
         setDefaultCloseOperation(EXIT_ON_CLOSE);
        
      }
   
       public void setPessoa(AgendaBean ab) {
         this.setNome(ab.getNome());
         this.setTelefone(ab.getTelefone());
         this.setEMail(ab.getEMail());
      }
   	
       public AgendaBean getPessoa() {
         AgendaBean ab = new AgendaBean();
         ab.setNome(this.nome.getText());
         ab.setTelefone(this.getTelefone());
         ab.setEMail(this.getEMail());
         return ab;
      }
   	
       public void addBotaoCadastrar(ActionListener al) {
         bCadastrar.addActionListener(al);
      }
   	   	
   	
   }

Presenter:

import java.awt.event.ActionListener;
   import java.awt.event.ActionEvent;

    public class AgendaPresenter {
    
   // só tem acesso ao m e ao v, isso é um presenter. (controles não têm acesso ao v)
      private AgendaModelo m;    
      private AgendaView v;
      
       public AgendaControle() {
         
         this.m = new AgendaModelo();
         this.v = new AgendaView();
      	
         m.addModeloListener(
                new ModeloListener() {
                   public void atualizar(ModeloEvent me) {
                        // ok. Veja que este codigo está realmente no presenter 
                       // e ele que está dicidindo o que fazer com o evento

                       v.setPessoa((AgendaBean) me.getSource()));  


                  }
               }); 
      	
         v.addBotaoCadastrar(
                new ActionListener() {
                   public void actionPerformed(ActionEvent ae) {
                          // idem ao de cima
                     m.cadastrar(v.getPessoa()); 
                  }
               });
      }
      
       public void start(){

               // mostra a view 
                  v.setVisible(true);
         }
   }

Modelo:

import java.util.*;
   
    public class AgendaModelo {
    
  // o cadastro é simulado aqui por um bean
// poderiamos invocar um serviço ou qq outra coisa.
      private AgendaBean b; 
    
      private Collection <ModeloListener> modeloListeners = new ArrayList<ModeloListener>();
   
       public void cadastrar(AgendaBean b) {
         this.b = b;
      	// Acessa a camada inferior para persistir...
 
            // se acessase nao precisariamos de ter o bean como atributo aqui.
           // por exemplo : session.saveOrUpdate(b);

         this.notificar();
      }
   	
       public synchronized void addModeloListener(ModeloListener ml) {
         if(!modeloListeners.contains(ml)) {
            modeloListeners.add(ml);
         }
      }
   	
       public synchronized void removeModeloListener(ModeloListener ml) {
         modeloListeners.remove(ml);
      }
   	
       private void notificar() {
         Collection <ModeloListener> ml;
         ModeloEvent evento = new ModeloEvent(b);
           
         synchronized (this) {
            ml = (Collection)(((ArrayList) modeloListeners).clone());
         }
      
         for (ModeloListener m : ml) {
            m.atualizar(evento);
         }
      }
   }
rderoci

rderoci:
Olá pessoal, sou novo aqui e estou cheio de dúvidas… Já lí boa parte do Tópico mas as dúvidas persistem, são elas:

Quanto ao Fluxo do MVC e MVP:

MVC:

  1. O Controller recebe ações do usuário, nunca a view?
  2. O Controller apenas delega o eventos recebidos da View atualizando o Modelo?
  3. Quem notifica a view das mudanças realizadas no Model pelo Controller: O controller? Através do Observer? Ou pelos dois, dependendo de algo que eu não sei? rs
  4. O Controller fala com a visão?

MVP:

  1. A View é quem recebe ações do usuário, nunca o Presenter?
  2. A view notifica o Presenter que delega a atualização/consulta ao Model?
  3. Quem notifica a view das mudanças realizadas no Model pelo Presenter: O Presenter? Através do Observer? Ou pelos dois, dependendo de algo que eu não sei? rs
  4. O presenter fala com a visão?

Queria saber o processo de cada um deles, assim conseguiria entender mais dos dois e conseguiria tirar uma outra dúvida, qual a diferença entre os 2?

Valeu;

Desculpa persistir, mas quando der, nao se esqueçam de responder minha pergunta… rs
Preciso muito dessas respostas, visto que em cada canto que eu vejo tenho uma resposta diferente e com isso não consigo me aprofundar no assunto…

Obrigado desde já, galera! Fico no aguardo!

pedromuyala

Opa boa tarde! Obrigado por iniciar a sua participação aqui no tópico!

Sim. Quando ocorre uma ação do usuário (click de mouse, pressionamento de tecla, ActionListener, FocusListener,…) esse evento é gerado por um controle e lançado para fora de forma que se outro controle externo estiver escutando (tem um Listener para aquele evento), pode recebê-lo e tratá-lo. Para entender melhor, imagine que na sua visão você inseriu um JButton. Na verdade o que está vendo na sua visão é a visão do JButton. Ao pressionar um botão do mouse sobre ele, um evento é gerado. Mas quem gera esse evento? O controlador, ou seja o próprio JButton. Após o pressionamento do botão, além de gerar esse evento (ActionEvent) ele também faz uma alteração no modelo. Repare que a visão do JButton ao pressionar um botão muda duas vezes de figura, o que reflete duas vezes alterações em seu modelo. Tendo isso em mente, o seu controlador vai registrar um ouvinte na visão que ficará aguardando os eventos lançados pelos controladores que nessa visão estiverem presentes. A imagem mostra isso:

Sim. Aqui pede-se para que use o mínimo possível de lógica.

Então, aqui existe um certo “desacordo” entre companheiros, mas se ler as últimas postagens com bastante atenção, o que realmente torna-se relevante para decidir é a questão da alta coesão e baixo acoplamento. É melhor o controle receber essa notificação da visão e mandar fazer algo na visão. Não está errado, como defendeu o Lavieri em suas postagens. Repare em um desenho do MVC que existe uma seta tarcejada que vai do modelo para a visão, significa chamada indireta, o que justifica a implementação do mesmo. Porém se olhar para imagem, ela indica no MVC que o Ouvinte do modelo deve estar na visão, ou seja o controle atualiza o modelo que notifica a visão da sua alteração e então a visão reenderiza usando o modelo. Veja a imagem:

No MVC pelo que vejo ele só muda a visão que está sendo exibida no momento, como pode apreciar na primeira imagem. Ele não injeta dados na visão.

Não. É o Presenter. (Veja exemplo de código mostrado pela usuária farabulini)

O Presenter que delega a atualização/consulta ao Model. Ele recebe os eventos da visão.

O mais correto seria o Presenter, porém existe um padrão chamado MVPC onde é feito das duas maneiras.

Sim.

Na verdade, o MVP e MVPC é uma derivação do MVC. A diferença é que a lógica de apresentação fica isolada da apresentação em si. MVC surgiu nos tempos do Smalltalk onde controlava um único Widget por vez. Já o MVP foi criado para poder controlar vários Widget’s se uma só vez. Esse link vai responder qualquer dúvida que tenha a esse respeito.

OK? Parabéns por não ter aberto um novo tópico, evitando duplicar tópicos e repetições teóricas, mantendo o bom funcionamento do fórum.
Se continuar com dúvidas volte a postá-las! Felicidades, um abraço, espero ter colaborado.

rderoci

pedromuyala:
Opa boa tarde! Obrigado por iniciar a sua participação aqui no tópico!

Sim. Quando ocorre uma ação do usuário (click de mouse, pressionamento de tecla, ActionListener, FocusListener,…) esse evento é gerado por um controle e lançado para fora de forma que se outro controle externo estiver escutando (tem um Listener para aquele evento), pode recebê-lo e tratá-lo. Para entender melhor, imagine que na sua visão você inseriu um JButton. Na verdade o que está vendo na sua visão é a visão do JButton. Ao pressionar um botão do mouse sobre ele, um evento é gerado. Mas quem gera esse evento? O controlador, ou seja o próprio JButton. Após o pressionamento do botão, além de gerar esse evento (ActionEvent) ele também faz uma alteração no modelo. Repare que a visão do JButton ao pressionar um botão muda duas vezes de figura, o que reflete duas vezes alterações em seu modelo. Tendo isso em mente, o seu controlador vai registrar um ouvinte na visão que ficará aguardando os eventos lançados pelos controladores que nessa visão estiverem presentes. A imagem mostra isso:

Sim. Aqui pede-se para que use o mínimo possível de lógica.

Então, aqui existe um certo “desacordo” entre companheiros, mas se ler as últimas postagens com bastante atenção, o que realmente torna-se relevante para decidir é a questão da alta coesão e baixo acoplamento. É melhor o controle receber essa notificação da visão e mandar fazer algo na visão. Não está errado, como defendeu o Lavieri em suas postagens. Repare em um desenho do MVC que existe uma seta tarcejada que vai do modelo para a visão, significa chamada indireta, o que justifica a implementação do mesmo. Porém se olhar para imagem, ela indica no MVC que o Ouvinte do modelo deve estar na visão, ou seja o controle atualiza o modelo que notifica a visão da sua alteração e então a visão reenderiza usando o modelo. Veja a imagem:

No MVC pelo que vejo ele só muda a visão que está sendo exibida no momento, como pode apreciar na primeira imagem. Ele não injeta dados na visão.

Não. É o Presenter. (Veja exemplo de código mostrado pela usuária farabulini)

O Presenter que delega a atualização/consulta ao Model. Ele recebe os eventos da visão.

O mais correto seria o Presenter, porém existe um padrão chamado MVPC onde é feito das duas maneiras.

Sim.

Na verdade, o MVP e MVPC é uma derivação do MVC. A diferença é que a lógica de apresentação fica isolada da apresentação em si. MVC surgiu nos tempos do Smalltalk onde controlava um único Widget por vez. Já o MVP foi criado para poder controlar vários Widget’s se uma só vez. Esse link vai responder qualquer dúvida que tenha a esse respeito.

OK? Parabéns por não ter aberto um novo tópico, evitando duplicar tópicos e repetições teóricas, mantendo o bom funcionamento do fórum.
Se continuar com dúvidas volte a postá-las! Felicidades, um abraço, espero ter colaborado.

Não entendi essa parte em negrito que você diz a diferença entre os dois… de resto, muito obrigado!!!

No MVC nós temos 1 controller para 1 view e no MVP temos 1 Presenter para n views? Seria isso?

Acrescentando, peguei uma apostila que me diz o seguinte:

MVP versus MVC
?Há mais similaridades do que diferenças entre o MVP e o MVC.
?Diferença principal:
?No MVC, o controller é responsável por capturar as ações do usuário (e.g., mouseDown, keyDown).
?No MVP, é o view que captura as ações do usuário; o presenter então trata esses eventos, atualizando o model.

pedromuyala

Não. Várias visões podem ser controladas por um controlador/presenter. No MVC (Smalltalk) você tem o Widget e um controlador específico para ele. No MVP você tem vários Widget’s controlados por um presenter.

rderoci:
Acrescentando, peguei uma apostila que me diz o seguinte:
MVP versus MVC
?Há mais similaridades do que diferenças entre o MVP e o MVC.
?Diferença principal:
?No MVC, o controller é responsável por capturar as ações do usuário (e.g., mouseDown, keyDown).
?No MVP, é o view que captura as ações do usuário; o presenter então trata esses eventos, atualizando o model.

Não. Na minha opinião:

  • O componente view do MVP é uma estrutura composta de controles de interface com o usuário.
  • Esse componente não contém qualquer comportamento que descreve como os controles reagem à eventos de sistema (ações do usuário).
  • A reação às ações do usuário é posicionada em um objeto separado, o componente presenter.
  • Os manipuladores para as ações do usuário ainda existem nos controles, mas esses manipuladores meramente passam (delegam) o processamento para o presenter.

Mas, não acredite em mim. Você se baseou em uma apostila não? Então, prefiro que não acredite em mim, só estou expondo o que entendo.
Obrigado por estar aqui, um abraço. :slight_smile:

I

sergiotaborda:
Não tenho muito tempo agora, então vamos a uma coisa rápida

O problema da sua implementação, Ingrid, é que a classe AgendaControle é na realidade um Presenter e o que vc está tentando fazer é um MVP , não um MVC.
É por isso que está confusa. Vc está fazendo um excelente MVP e achando que é uma porcaria de MVC :slight_smile:
Dito isso, a implementação está em geral correta ( para um mvp)

Sérgio… Obrigada por me ajudar moço, estou muito grata por me atender. :smiley:
Pois é imaginava que seria um MVP mesmo, conforme cheguei a discutir em algumas postagens atrás… :smiley:

Não consigo fazer a implementação em MVC. :cry: Mas vou tentar mais uma vez fazer e postar o código… Sempre que faço tem algo errado… :roll:
Esse MVP até saiu porque segui um exemplo do presenter postado aqui. Mas MVC concluí que nem sei mais por onde começar. :cry:

Ahh e todo esse código pertence a camada de apresentação? Está tudo em um só andar?

Você notou o comentário que coloquei no modelo ‘\ Acessa a camada inferior para persistir…’ e acrescentou um exemplo: ‘session.saveOrUpdate(b);’. No caso, o modelo da camda de apresentação está chamando o objeto ‘session’ da camada de persistência. Esse objeto é uma interface? A camada de persistência usa alguma arquitetura? Obrigada :smiley:

sergiotaborda

Eu já disse isto antes, mas , aplicações desktop se fazem com MVP. Frameworks gráficos como o swing se fazem com MVC.
Não tente fazer com mvc que não vai dar. Vc está no caminho certo, continue nele.

Sim.

Ai eu usei o exemplo de um objeto do hibernate, mas em geral é uma interface de serviço. o modelo é onde vc chama objetos da camada inferior

A camada de persistencia tb tem arquiteturas especificas. Otrora o DAO era famoso, mas hoje é obsuleto. Hoje em dia se usa o padrão DomainStore.
Vale lembrar que entre a camada de apresentação e a de persistencia ainda está a camada de dominio. Esta é a mais importante.
Nessa camada vc tem padrões como Entity, Value Object, Service e Repository.
Os services são portas de entrada chamadas pelo andar de apresentação e os repositorios são “portas de saida” para o andar de integração (persistencia).

Todos os andares têm padrões particulares a eles.

I

Olá Sérgio… puxa que bom saber que estou no caminho certo. :smiley: :smiley:
A camada de domínio seriam as classes do diagrama de classes? É onde as coisas realmente acontecem.
Acredito que na parte de apresentação já não tenho mais dúvidas…
Agora vou estudar essa parte, muito obrigada por me ajudar… muito… t+

sergiotaborda

rderoci:
Olá pessoal, sou novo aqui e estou cheio de dúvidas… Já lí boa parte do Tópico mas as dúvidas persistem, são elas:

Quanto ao Fluxo do MVC e MVP:

MVC:

  1. O Controller recebe ações do usuário, nunca a view?
  2. O Controller apenas delega o eventos recebidos da View atualizando o Modelo?
  3. Quem notifica a view das mudanças realizadas no Model pelo Controller: O controller? Através do Observer? Ou pelos dois, dependendo de algo que eu não sei? rs
  4. O Controller fala com a visão?

MVP:

  1. A View é quem recebe ações do usuário, nunca o Presenter?
  2. A view notifica o Presenter que delega a atualização/consulta ao Model?
  3. Quem notifica a view das mudanças realizadas no Model pelo Presenter: O Presenter? Através do Observer? Ou pelos dois, dependendo de algo que eu não sei? rs
  4. O presenter fala com a visão?

Queria saber o processo de cada um deles, assim conseguiria entender mais dos dois e conseguiria tirar uma outra dúvida, qual a diferença entre os 2?

Valeu;

O Pedro já respondeu , mas eu queria apenas emendar o seguinte. “Oficialmente” é a View que recebe os eventos do usuário como os cliques e aperto de teclas.
Esses eventos são enviados ao controlador (no mvc) e ele decide o que fazer ( por isso que é o controlador) em relação ao modelo. Ou seja, se deve mudar ou não o modelo.
Por exemplo, quando vc usa um TextField e aperta uma letra a view recebe esse evento e o repassa ao controlador, o controlador então decide passar isso ao modelo (a classe Documet)
O modelo então se atualiza, ou não e se sim, envia um evento. A view recebe esse evento e se re-renderiza para mostrar a letra. VEja que ela não mostra a letra até que o modelo o diga.

No mvp é semelhante, a view recebe os eventos de clique e aperto de teclas, mas agora ela vai transformar isso em gestos. Gestos são eventos que significam algumas coisa especial como salvar, sair, gravar, recarregar, imprimir, etc… e passa esses gestos ao Presenter. A view do mvp é mais inteligente que a do mvc. Ela sabe traduzir cliques “puros” em eventos com significado.
O presenter então responde a esses eventos sem ter que os intrepretar.

a diferença é que o MVC é usado para coisa baixo nivel e por isso é excelente para criar o cliente gráfico ( andar cliente) Mas o cliente é burro. Ele sabe que tem que reagir mas não sabe ao quê está reagindo. O MVP é mais alto nivel ( andar apresentação). O V do mvp pode conter toda uma estrutura sofisticada que pode incluir o MVC inteiro. É isso que vc faz quando usa swing. Vc cria o cliente swing e amarra algumas coisas, o resto vc deixa para outro alguem decidir. Mas todo o cliente swing é a sua view, o decisor é o Presenter. ( Veja, camada de apresentação => presenter)

É importante ter a noção que é a view que recebe os eventos do usuário. É ela que sabe destingir um clique em um butão de um clique numa imagem ou de apertar uma tecla. O fato de ser o controlador ou o presenter a decidir o que fazer, não tira o mérito de ser a view o unico elo de ligação que o usuário tem. A view é o que ele “vê” e ele só vê a view. Digo “vê” por que na realidade a placa de som tb faz parte da view :slight_smile: não apenas a tela.

I

Olá rapazes…

Alguém sabe como corrigir o aviso ao clonar os Listener’s? “uses unchecked or unsafe operations” :cry:
Ao que parece é um erro de tipagem do ArrayList. É justamente a implementação do pattern Observer.

public class ModeloEvent extends java.util.EventObject {
       public ModeloEvent(Object source) {
         super(source);
      }
   }
public interface ModeloListener extends java.util.EventListener {
       void atualizar(ModeloEvent e);
   }
import java.util.*;
   
    public class Modelo {
    
      private Collection <ModeloListener> modeloListeners = new ArrayList<ModeloListener>();
   
       public void cadastrar() {
         this.notificar();
      }
   	
       public synchronized void addModeloListener(ModeloListener ml) {
         if(!modeloListeners.contains(ml)) {
            modeloListeners.add(ml);
         }
      }
   	
       public synchronized void removeModeloListener(ModeloListener ml) {
         modeloListeners.remove(ml);
      }
   	
       private void notificar() {
         Collection <ModeloListener> ml;
         ModeloEvent evento = new ModeloEvent(this);
           
         synchronized (this) {
            ml = (Collection)(((ArrayList) modeloListeners).clone()); // Será aqui o problema??
         }
      
         for (ModeloListener m : ml) {
            m.atualizar(evento);
         }
      }
   }

Obrigada :smiley:

sergiotaborda

ingridfarabulini:
Olá rapazes…

Alguém sabe como corrigir o aviso ao clonar os Listener’s? “uses unchecked or unsafe operations” :cry:
Ao que parece é um erro de tipagem do ArrayList. É justamente a implementação do pattern Observer.

Primeira coisa, não use java.util.EventListener nem java.util.EventObject
Segunda coisa, não use clone.
Terceiro, não precisa ficar copiando a coleção que detem os listeners.
Isso é simplesmente inutil.

A coleção certa para manter os listeners é CopyOnWriteArraySet.
Sendo um Set só uma copia de cada listerns srá registrado. Isso é bom, porque impede que o listerer seja avisado duas vezes do mesmo evento
Por outro ladd esta lista deixa que haja iteração ao mesmo tempo que ha adição e remoção de itens, o que é ideal se, por acaso, algum listener for associado enquando
o loop de disparo do evento estiver corrento. ISto é rarissimo já que a amarração de listeners acontece numa fase de preparação anterior ao real funcionamento, mas
nunca é demais prevenir.

Dê uma olhada numa forma “simples” de trabalhar com eventos.

rylphs

Gente, parece que até que enfim estou entendendo melhor MVP e MVC . Obrigado a todos :wink:

Ainda tenho uma dúvida: No caso do MVP é o presenter que cria a view e define seu conteúdo? Qual a vantagem disso em uma aplicação desktop?

Digo isso porque estou implementando algo para desktop e pensei em algo como a imagem em anexo. Nesse caso, o presenter criaria a view, mas não definiria seu conteúdo explicitamente em algo como: view.setNome() Ao invés disso se comunicaria com a mesma através do model correspondente. O que vocês acham? Me desculpem pela qualidade da imagem, não sei se dá pra entender a idéia.

pedromuyala

Fala rylphs.

Sim, o Presenter instancia a visão e o modelo.

Já em relação a imagem, parece estar bem diferente daquilo que pede o padrão, não?
O Presenter falando diretamente com negócios está estranho. E o modelo da Camada de Apresentação?
Se quer fazer binding direto, esqueça o MVP e MVC e siga o Autonomous view.

Mas acredito que esse link vai te ajudar bastante: http://www.guj.com.br/posts/list/128303.java#795528

Abraço. :wink: Poste suas perguntas sem medo de ser feliz!

sergiotaborda

rylphs:
Gente, parece que até que enfim estou entendendo melhor MVP e MVC . Obrigado a todos :wink:

Ainda tenho uma dúvida: No caso do MVP é o presenter que cria a view e define seu conteúdo? Qual a vantagem disso em uma aplicação desktop?

Não é o presenter que instancia a view. É uma outra classe que não pertence ao MVP, por exemplo a classe onde fica o main.
Esta classe instancia o view, o presenter e o model e os amarra corretamente (faz set ou passa no construtor).
Se usar um motor de injeção é mais facil ainda.

A vantagem é que vc pode sofisiticar a sua view o quanto quiser. pode por exemplo mudar de swing para javafx sem mudar o presenter ou o model.


Digo isso porque estou implementando algo para desktop e pensei em algo como a imagem em anexo. Nesse caso, o presenter criaria a view, mas não definiria seu conteúdo explicitamente em algo como: view.setNome() Ao invés disso se comunicaria com a mesma através do model correspondente. O que vocês acham? Me desculpem pela qualidade da imagem, não sei se dá pra entender a idéia.

não existe um model que é passado entre a view e o presenter. Existem diferentes beans que são passados. Mas eles não são o M do MVP.

rylphs

pedromuyala:
Fala rylphs.

Sim, o Presenter instancia a visão e o modelo.

Já em relação a imagem, parece estar bem diferente daquilo que pede o padrão, não?
O Presenter falando diretamente com negócios está estranho. E o modelo da Camada de Apresentação?
Se quer fazer binding direto, esqueça o MVP e MVC e siga o Autonomous view.

Mas acredito que esse link vai te ajudar bastante: http://www.guj.com.br/posts/list/128303.java#795528

Abraço. :wink: Poste suas perguntas sem medo de ser feliz!

Desculpe, pedro, acho que baguncei um pouco as coisas. O modelo da camada de apresentação seria somente um bean que seria passado pro presenter. O presenter faria a tradução desse bean para o modelo de negócios e vice-versa. O que chamei de business seria algum modelo da camada de negócios (deveria ter colocado “business model”). Como é o presenter que instancia o modeo (pelo menos era o que eu achava até o post do sergiotaborda), inevitavelmente ele teria que se comunicar diretamente com o modelo da camada de negócios. Não é isso? Vou dar uma olhada no “autonomous view” também. Brigadão!

sergiotaborda:
Não é o presenter que instancia a view. É uma outra classe que não pertence ao MVP, por exemplo a classe onde fica o main.
Esta classe instancia o view, o presenter e o model e os amarra corretamente (faz set ou passa no construtor).

Eu pensava que o main seria um presenter, ou pelo menos um controller. Nesse caso o main instanciaria todas as views, presenters e models? Não ficaria pouco coeso?
De qualquer forma o presenter não tem que conhecer a view? Não é ele que vai chamar os gets e sets da mesma? Da mesma forma com o model. Ele não teria que conhecer os métodos do model? Então porque não deixar a instanciação por conta do presenter, cada presenter instanciando a view e model que lhe cabe?

Desculpe a minha ignorância, mas o que seria um “motor de injeção”? [tosco on] Alguma máquina a trabalho do ministério da saúde? :smiley: [tosco off]

Me desculpa se estou falando besteira. Só estou tentando entender melhor as coisas. Obrigado!

sergiotaborda

Não. O problema não é coesão, é acoplamento. A coesão é a mesma.

Conhecer não significa instanciar.
Conhecer significa -apenas- saber que métodos chamar.

É um mecanismo que constroi os objetos e injeta neles (dá set, ou via construtor) os objetos que ele precisa.
O Spring é um exemplo de um framework que faz isto. (E antes que alguem pergunte: sim. dá para usar spring no desktop)

rylphs

Entendo que o acoplamento ficaria menor. Mas o main seria o único a instanciar todas as classes?

Que legal, eu não sabia. Vou pesquisar a respeito.

sergiotaborda

Entendo que o acoplamento ficaria menor. Mas o main seria o único a instanciar todas as classes?

Eu usei o main como exemplo. Vc pode criar classes especificas para montarem as classes reais da aplicação.
Isso deve fazer parte da sua plataforma de aplicação , aka infraestrutura.

I

Olá meninos! Tudo bem com vocês? :smiley:

sergiotaborda:
O problema da sua implementação, Ingrid, é que a classe AgendaControle é na realidade um Presenter e o que vc está tentando fazer é um MVP , não um MVC.
É por isso que está confusa. Vc está fazendo um excelente MVP e achando que é uma porcaria de MVC :slight_smile:

public class AgendaIngrid {
   		
       public static void main(String args[]) {
         AgendaPresenter presenter = new AgendaPresenter();
          // construtores não começam as coisas... 
            presenter.start();
      }
   }

Presenter:

import java.awt.event.ActionListener;
   import java.awt.event.ActionEvent;

    public class AgendaPresenter {
    
   // só tem acesso ao m e ao v, isso é um presenter. (controles não têm acesso ao v)
      private AgendaModelo m;    
      private AgendaView v;
      
       public AgendaPresenter() {
         
         this.m = new AgendaModelo();
         this.v = new AgendaView();
      	
         m.addModeloListener(
                new ModeloListener() {
                   public void atualizar(ModeloEvent me) {
                        // ok. Veja que este codigo está realmente no presenter 
                       // e ele que está dicidindo o que fazer com o evento

                       v.setPessoa((AgendaBean) me.getSource()));  


                  }
               }); 
      	
         v.addBotaoCadastrar(
                new ActionListener() {
                   public void actionPerformed(ActionEvent ae) {
                          // idem ao de cima
                     m.cadastrar(v.getPessoa()); 
                  }
               });
      }
      
       public void start(){

               // mostra a view 
                  v.setVisible(true);
         }
   }

sergiotaborda:
rylphs:
Gente, parece que até que enfim estou entendendo melhor MVP e MVC . Obrigado a todos :wink:

Ainda tenho uma dúvida: No caso do MVP é o presenter que cria a view e define seu conteúdo? Qual a vantagem disso em uma aplicação desktop?

Não é o presenter que instancia a view. É uma outra classe que não pertence ao MVP, por exemplo a classe onde fica o main.
Esta classe instancia o view, o presenter e o model e os amarra corretamente (faz set ou passa no construtor).
Se usar um motor de injeção é mais facil ainda.

Fiquei confusa novamente… :frowning: Lendo as últimas postagens, acreditava que a resposta do Pedro era correta. Até porque no MVP o Presenter está instanciando a minha view e meu modelo…
Pensei que estava excelente. :cry: E agora, como vou corrigir isto?

Obrigada…

V

Pois é, pessoal. Eu acompanhei as postagens da últimas duas páginas e pensava ter entendido bem. Só vim aqui para tirar uma pequena dúvida. Porém, as últimas postagens também me deixaram um pouco confuso. Afinal, a interpretação do mvp pelo rylphs, na minha opinião, foi equivalente ao código postado pela ingridfarabulini.

Se os senhores pudessem fazer uma revisão do que foi discutido desde a página anterior, eu acho que as ambiguidades seriam esclarecidas.

Abraços,
Victor

pedromuyala

Opa pessoal, muitíssimo obrigado por estarem atentos ao tópico!
Quero mandar um abraço à todos que estão colaborando.

Entendo que o acoplamento ficaria menor. Mas o main seria o único a instanciar todas as classes?

Eu usei o main como exemplo. Vc pode criar classes especificas para montarem as classes reais da aplicação.
Isso deve fazer parte da sua plataforma de aplicação , aka infraestrutura.

Como estamos falando de MVP, já que estamos programando em alto nível…
Eu entendo quando o Sérgio diz que é melhor uma classe específica passar as instancias da visão e do modelo para o Presenter.
Sendo assim, o que o Presenter conhece, então, seriam as interfaces da visão e do modelo? É isso que quer passar??
Pois conhecendo somente a interface, também posso trocar a minha visão swing para JavaFX sem ter problemas.

E também acho que a Ingrid está fazendo um excelente MVP. Não é por causa de um pequeno “erro” de instanciação que vamos matar todo o conhecimento que está por trás do código que ela criou. :roll:

Outra coisa, o main é um controlador sim. Um componente do swing também é um controlador. E a visão envia gestos via Observer para o Presenter, pois esses eventos ocorrem de forma assíncrona. Agora aí está minha dúvida: No MVP se tenho dez componentes swing na visão, vamos dizer de JButton’s, se eu clico em um deles o listener que está escutando os eventos desse botão (que está presente na visão) recebe esse evento e então cria um novo evento para que o listener do Presenter o receba? Não né?
A forma que a Ingrid implementou é a correta, certo?

Abraço companheiros, orgulho em tê-los aqui. Muito sucesso e paciência a todos!
Felicidades.

sergiotaborda

A instanciação é um assunto separado do MVP, MVC, etc…
É um problema de OO básico.

Quando digo que não é o presenter que instancia eu quero dizer que é melhor fazer assim

public class Agenda{
   		
       public static void main(String args[]) {
         AgendaView view = new AgendaView();
        AgendaModel model = new AgendaModelo();
       

         AgendaPresenter presenter = new AgendaPresenter(view, model);
          // construtores não começam as coisas... 
            presenter.start();
      }
   }

Em vez de fazer isso dentro do contrutor.
Isso é uma prática OO geral para todos os objetos chamada Inversão de Dependencia.
Porque é legal ?
Porque agora eu posso fazer isto

public class Agenda{
   		
       public static void main(String args[]) {
         AgendaView view = new NovaAgendaViewMaisBonita();
        AgendaModel model = new AgendaModelo();
       

         AgendaPresenter presenter = new AgendaPresenter(view, model);
          // construtores não começam as coisas... 
            presenter.start();
      }
   }

Viram ? O presenter não mudou nada.
Eu tou usando o mai, mas poderia fazer assim

public class Configurador(){

               AgendaPresenter presenter;

            public voi configurar(){
              AgendaView view = new NovaAgendaViewMaisBonita();
              AgendaModel model = new AgendaModelo();
       

               presenter = new AgendaPresenter(view, model);
           }

    }
    public class Agenda{
   		
       public static void main(String args[]) {
      
          Configurador conf = new Configurador();

          conf.configurar();

          
           AgendaPresenter presenter = conf.getPresenter();

            presenter.start();
      }
   }

Agora eu posso mudar as classes apenas no configurador assim

public class Configurador(){

               AgendaPresenter presenter;

            public voi configurar(){
              AgendaView view = new NovaAgendaViewMaisBonita();
              AgendaModel model = new AgendaModelo();
       
               presenter = new AgendaPresenterComNovasRegras(view, model);
           }

    }

Sim, é muito bom que AgendaView , AgendaModel e AgendaPresenter sejam interfaces. Não é obrigatório, mas é muito melhor design, porque é ainda mais desacoplado.
Alta coesão, baixo acoplamento. Esse é sempre o objetivo de todos os designs OO.

Como disse o Pedro, este detalhe da inicialização das classes não mancha o design MVP feito. É apenas a cereja no topo do sorvete… (mas uma cereja que deveria estar no topo de todos os sorvetes … inversão de dependencia é uma prática básica de OO em qq camada, em qualquer arquitetura, em qualquer linguagem ou plataforma)

V

Olá, senhores. Obrigado pelos esclarecimentos.

Eu tenho uma dúvida:

Se eu tiver uma classe JFrame com JInternalFrame's, eu posso ter uma classe presenter para cada JInternalFrame? No meu caso, ainda tenho, em um dos JInternalFrame's, um JDialog. É, resumidamente, assim:

Presenter para a janela principal:

public class PrincipalPresenter{

private PrincipalView principalView;
//atributos
//métodos
}

A classe model Formulario:

public class Formulario{

private List <Questao> questao;
//atributos
//métodos
}

Eu tenho um JInternalFrame que tem FormularioView, FormularioPresenter, etc. Em FormularioPresenter eu também tenho um objeto Formulario.

public class FormularioPresenter{

private FormularioView formularioView;
private Formulario formulario; //model
private QuestaoPresenter questaoPresenter;
//atributos
//métodos
}

Associado a esse JInternalFrame, eu tenho uma classe JDialog, mais precisamente, QuestaoView, com seus respectivos QuestaoPresenter, etc.

public class QuestaoPresenter{

private QuestaoView questaoView;
private Questao questao; // model
//atributos
//métodos
}

A pergunta: como eu faço para informar o objeto Formulario sobre os objetos Questao inseridos a partir de QuestaoView?

Desculpem-me se não fui claro!

Abraços,
Victor

I

Olá meninos, oi Sérgio :smiley:
Obrigada moço, entendi direitinho o que quis expor…

sergiotaborda:

A instanciação é um assunto separado do MVP, MVC, etc…
É um problema de OO básico.

Sim, é muito bom que AgendaView , AgendaModel e AgendaPresenter sejam interfaces. Não é obrigatório, mas é muito melhor design, porque é ainda mais desacoplado.
Alta coesão, baixo acoplamento. Esse é sempre o objetivo de todos os designs OO.

Como disse o Pedro, este detalhe da inicialização das classes não mancha o design MVP feito. É apenas a cereja no topo do sorvete… (mas uma cereja que deveria estar no topo de todos os sorvetes … inversão de dependencia é uma prática básica de OO em qq camada, em qualquer arquitetura, em qualquer linguagem ou plataforma)

Vou implementar o meu novo código seguindo sua orientação e voltarei a postar.
Mas vou estudá-lo antes de sair fazendo qualquer coisa. Muito obrigada, agradeço a todos. :smiley:

I

Olá meninos, tudo bem com vocês? :smiley:

Quem chegou a ler minha postagem anterior, provavelmente esteve aguardando aquilo que falei… pois agora sim, fiz um verdadeiro MVP (pelo menos acredito que sim) :stuck_out_tongue:
Fiz todas as alterações certinhas indicadas pelo Sergio… tanto no Observer quanto na Inversão de Dependência.

public class AgendaIngrid {
     
       public static void main(String args[]) { 
       
         AgendaConfig conf = new AgendaConfig();
         conf.config();
         AgendaPresenter presenter = conf.getPresenter();
         presenter.start(); 
      } 
   }
public class AgendaConfig { 
    
      AgendaPresenter presenter; 
       
       public void config() { 
         AgendaView view = new AgendaView();
         AgendaModelo model = new AgendaModelo();
         
         presenter = new AgendaPresenter(model, view);
      }
   	
       public AgendaPresenter getPresenter() {
         return presenter;
      }
   }
import javax.swing.*; 
   import java.awt.event.*;
	 
    public class AgendaView extends JFrame { 
      private JTextField nome, eMail, telefone; 
      private JButton bCadastrar; 
   
       public AgendaView() { 
         JPanel p = new JPanel(); 
         p.add(new JLabel("Nome:")); 
         p.add(nome = new JTextField(10)); 
         p.add(new JLabel(" - Telefone:")); 
         p.add(telefone = new JTextField(10)); 
         p.add(new JLabel(" - E-Mail:")); 
         p.add(eMail = new JTextField(10)); 
         p.add(bCadastrar = new JButton("Cadastrar Pessoa >>")); 
         add(p); 
         setTitle("Agenda Ingrid vs1.1"); 
         setSize(720,70); 
         setResizable(false); 
         setDefaultCloseOperation(EXIT_ON_CLOSE); 
      } 
   	
       public void setPessoa(AgendaBean ab) { 
         this.nome.setText(ab.getNome()); 
         this.telefone.setText(ab.getTelefone()); 
         this.eMail.setText(ab.getEMail()); 
      } 
   	
       public AgendaBean getPessoa() { 
         AgendaBean ab = new AgendaBean(); 
         ab.setNome(this.nome.getText()); 
         ab.setTelefone(this.telefone.getText()); 
         ab.setEMail(this.eMail.getText()); 
         return ab; 
      } 
   	
       public void addBotaoCadastrar(ActionListener al) { 
         bCadastrar.addActionListener(al); 
      } 
   }
import java.awt.event.ActionListener; 
   import java.awt.event.ActionEvent; 

    public class AgendaPresenter { 
   
      private AgendaModelo m; 
      private AgendaView v; 
   
       public AgendaPresenter(AgendaModelo model, AgendaView view) { 
         this.m = model; 
         this.v = view; 
      
         m.addModeloListener( 
                new ModeloListener() { 
                   public void onAtualizar(ModeloEvent me) { 
                     v.setPessoa((AgendaBean) me.getSource()); 
                  } 
               });
      			 
         v.addBotaoCadastrar( 
                new ActionListener() { 
                   public void actionPerformed(ActionEvent ae) { 
                     m.cadastrar(v.getPessoa()); 
                  } 
               }); 
      }
   	 
       public void start(){ 
         v.setVisible(true); 
      }
   	 
   }
import java.util.*;
   import java.util.concurrent.*;
   
    public class AgendaModelo {
    
      private AgendaBean b;
   	    
      private final Set<ModeloListener> modeloListeners = new CopyOnWriteArraySet<ModeloListener>(); 
   
       public void cadastrar(AgendaBean b) {
         this.b = b;
      	// Acessa a camada inferior para persistir...
         this.fireOnAtualizar();
      }
   	
       public void addModeloListener(ModeloListener ml) {
         this.modeloListeners.add(ml);
      }
   	
       public void removeModeloListener(ModeloListener ml) {
         this.modeloListeners.remove(ml);
      }
   	
       private void fireOnAtualizar() {
         ModeloEvent evento = new ModeloEvent(b);
      
         for (ModeloListener ml : modeloListeners) {
            ml.onAtualizar(evento);
         }
      }
   }
public class AgendaBean {
    
      private String nome, eMail, telefone;
   
       public AgendaBean() {
         this.nome="N/C";
         this.eMail="N/C";
         this.telefone="N/C";
      }
   	
       public void setNome(String nome) {
         this.nome = nome;
      }
   		
       public String getNome() {
         return this.nome;
      }
   	
       public void setEMail(String eMail) {
         this.eMail = eMail;
      }
   	
       public String getEMail() {
         return this.eMail;
      }
   	
       public void setTelefone(String telefone) {
         this.telefone = telefone;
      }
   	
       public String getTelefone() {
         return this.telefone;
      }
   }
public interface ModeloListener {
       void onAtualizar(ModeloEvent e);
   }
public class ModeloEvent {
    
      Object source;
   	 
       public ModeloEvent(Object source) {
         this.source = source;
      }
   	
       public Object getSource(){
         return source;
      }
   }

EEEEBBBAAA! Agora simmm… :lol:
Lembrando que ainda falta implementar as interfaces para Modelo, Visão e Presente para ter um melhor design!

Mas ainda tenho uma dúvida…
Veja a linha 16 do AgendaPresenter…

v.setPessoa((AgendaBean) me.getSource());

Aí minha pergunta é: A classe ModeloEvent tem um atributo do tipo Object. Ele poderia já ser do tipo AgendaBean :?:

Outra pergunta é: Dessa forma que está o código, está fácil para qualquer outro(a) programador(a) entender caso precise fazer alterações? Ou seja, é um MVP claro?
Existe algo que está visivelmente errado em termos de programação e padronização de OO e MVP?
O bean faz parte de qual camada? Eu sei que ele não é o M do MVP que está na camada de apresentação mas ele é de qual camada?

Obrigada meninos! Quero muito agradecer pela ajuda de todos que continuam ajudando. :smiley:

sergiotaborda

Quando se usa o “getSource” está se à espera que o retorno seja o objecto que deu origem ao evento.
A incongruencia vem dai. Vc não está usando para isso. Portanto , renomei o método para getAgenda e retorne um agenda bean.

Algumas nomenclauturas, por exemplo get/setPessoa na realidade fazem get/set de AgendaBean. Ou troca para get/set agenda ou muda o objeto para Pessoa.
Outra questão de nomenclatura é não se coloca o sufixo bean nos beans. Apenas Agenda é suficiente.

Essa pergunta é mais dificil do que parece. Se o bean é apenas usado para o MVP então ele pertence na camada de apresentação.
Se o bean é usado por outras camadas então ele pertence na camada de dominio ( abaixo da apresentação). Na realidade ele não pertene fisicamente à camada de dominio, já que ele transita por todas as camadas, mas pertence a ela lógicamente.

I

Olá Sergio, obrigada por responder! :smiley:
Fiz as alterações que me ensinou… que bom estar agora certinho.

Ah e também deixei o Bean com o nome Pessoa. Achei melhor porque a agenda é um grupo de pessoas com determinada organização alfabética.
Essa organização que é a Agenda (cadastrar, consultar,…). Não sei se estou pensando corretamente , mas …
Poderia ser uma agenda de compromissos. No lugar de pessoas, teria o Bean Compromisso. Acho eu :stuck_out_tongue:

Vou estudar a camada de domínio para definir onde esse Bean deverá pertencer…
Se voltar a ter dúvidas voltarei a postar aqui mesmo.

Obrigada, você me ajuda sempre! :smiley: T+

pedromuyala

Opa pessoal, prazer estar aqui com vocês companheiros Gujeiros!
Estive acompanhando o desenrolar deste tópico parece que estamos chegando ao um acordo real do que é MVP.

:roll: Nesse meio todo surgiu uma dúvida: No MVP, caso ocorra uma excessão no modelo por invalidação de algum dado ou até mesmo um erro diferente, ele deve lançar uma exception correto? Mas essa exceção será o Presenter quem deve estar preparado para receber e após isso repassar a View (throws em ambos) e ela se encarregará de como mostrará isso ao usuário ou o próprio modelo deverá ter um atributo de mensagem de erro e o Presenter será avisado pelo evento do Observer que ele (o modelo) foi alterado e deve reenderizar a visão para mostrá-lo ao usuário? [color=orange]OBS: Isso já foi discutido aqui no tópico mas foi falado em relação ao MVC e nunca ao MVP.[/color]

Olha quero desejar felicidades a todos os companheiros é um sonho realizado para mim ver que as pessoas estão interessadas pelo tópico. :thumbup:
É realmente deslumbrante para mim. Felicidades a todos muito sucesso parabéns a adm do GUJ e seus moderadores pelo ambiente agradabilíssimo disponível aqui. :wink:

I

Olá Pedro :smiley:

Vou tentar responder… :stuck_out_tongue:
Acredito que se a sua camada/andar de Apresentação estiver bem desenhado, não vão ocorrer exceções no 'M’odel do tipo Exception desta camada/andar. Mas isso não tenho certeza, melhor escutar a opinião de usuários com maior experiência. Quanto a validações elas não ocorrem na Apresentação mas sim na camada/andar de Domínio. O Model do 'M’VP na Apresentação é a porta de saída para o Domínio onde provavelmente chamará um serviço desta. Aí sim caso ocorra alguma invalidação/erro provavelmente este serviço irá retornar/lançar como resposta uma Exception que será tratada no 'M’odel de forma adequada para que a mensagem de erro seja mostrada na 'V’iew/nova 'V’iew. Me fiz entender? :stuck_out_tongue: :oops:

Olha pedro recomendo-lhe muiiitooo aguardar usuários com maior exepriência responder porque eu mesma não creio muito naquilo que digo kkkk… Me desculpa, mas só estou tentando ajuda-lo.
Fiquei muito curiosa também com o que vai aparecer de respostas daqui para frente no tópico… Espero não estar errada 8) Até +

pedromuyala

Opa Ingrid, tudo bem? Obrigado por tentar ajudar mas desculpa não capitei vossa mensagem! Não consegui entender :frowning:

ingridfarabulini:
Acredito que se a sua camada/andar de Apresentação estiver bem desenhado, não vão ocorrer exceções no 'M’odel do tipo Exception desta camada/andar. Mas isso não tenho certeza, melhor escutar a opinião de usuários com maior experiência. Quanto a validações elas não ocorrem na Apresentação mas sim na camada/andar de Domínio. O Model do 'M’VP na Apresentação é a porta de saída para o Domínio onde provavelmente chamará um serviço desta. Aí sim caso ocorra alguma invalidação/erro provavelmente este serviço irá retornar/lançar como resposta uma Exception que será tratada no 'M’odel de forma adequada para que a mensagem de erro seja mostrada na 'V’iew/nova 'V’iew. Me fiz entender? :stuck_out_tongue: :oops:

Olha pedro recomendo-lhe muiiitooo aguardar usuários com maior exepriência responder porque eu mesma não creio muito naquilo que digo kkkk… Me desculpa, mas só estou tentando ajuda-lo.
Fiquei muito curiosa também com o que vai aparecer de respostas daqui para frente no tópico… Espero não estar errada 8) Até +


Principalmente aqui:
O Model do 'M’VP na Apresentação é a porta de saída para o Domínio onde provavelmente chamará um serviço desta. Aí sim caso ocorra alguma invalidação/erro provavelmente este serviço irá retornar/lançar como resposta uma Exception que será tratada no 'M’odel de forma adequada para que a mensagem de erro seja mostrada na 'V’iew/nova 'V’iew.

O que tentou passar é que se ocorrer alguma invalidação na Camada de Negócios essa vai lançar uma exceção para a Camada de Apresentação onde o método do Model no MVP que chamou o serviço no domínio estará com throws esperando essa Exception? É isso? :roll:

Será que mais alguém arrisca a responder? :idea:

Obrigado companheiros Gujeiros, sucesso! :wink:

I

Sim, seria isso. Mas eu mesma estou com dúvidas acho melhor aguardar o pessoal mais experiente responder kkkk… :stuck_out_tongue:
Estou curiosa também para saber. :roll: Até breve…

sergiotaborda

pedromuyala:
Opa pessoal, prazer estar aqui com vocês companheiros Gujeiros!
Estive acompanhando o desenrolar deste tópico parece que estamos chegando ao um acordo real do que é MVP.

:roll: Nesse meio todo surgiu uma dúvida: No MVP, caso ocorra uma excessão no modelo por invalidação de algum dado ou até mesmo um erro diferente, ele deve lançar uma exception correto? Mas essa exceção será o Presenter quem deve estar preparado para receber e após isso repassar a View (throws em ambos) e ela se encarregará de como mostrará isso ao usuário ou o próprio modelo deverá ter um atributo de mensagem de erro e o Presenter será avisado pelo evento do Observer que ele (o modelo) foi alterado e deve reenderizar a visão para mostrá-lo ao usuário?

Exceções , como seu nome indica, são imprevisiveis. Podem sempre acontecer exceções que vc não previu.
Exceções podem acontecer em qq das partes do MVP e em qualquer parte do sistema. Lidar com exceções corretamente é um conhecimento paralelo a saber MVP. Mesmo nos outros andares e usando outros padrões vc tem que saber lidar com exceções.

A regra é: se a camada (aqui no sentido lato: andar, nodo, etc…) não sabe lidar com a exceção deve repassá-la à camada superior.
A ultima camada , não tendo a quem repassar deve logar a exceção e apresentar uma mensagem clara ao usuário.

Portanto, no caso do mvp ao acontecer uma exceção o Presenter deve instruir a view a mostrar a mensagem ao usuário. Em particular, para alguns tipos de erro o usuário poderá tomar alguma ação, portanto o presenter deve ter logica para tratar esses casos. Mas isso apenas trata os erros previstos. Sempre deve haver um codigo que trata os erros imprevistos. E isso deve estar na camada (de codigo) mais externa. Em ultimo caso no exceptionHandler da thread.

O model não deve capturar a exceção e repassá-la ao presenter. Ele deve simplesmente deixar a exceção chegar ao presenter.
O mesmo entre o presenter e a view para o caso de exceções não previstas.

Adelar

Muito útil esta discussão como exemplo de MVP em Swing. Me ajudou muito :smiley:

Adelar

Olá pessoal,
das formas de implementação do MVP a que me parece mais adequada é a PassiveView (link de um dos posts anteriores http://fabiolnm.blogspot.com/2009/12/do-mvc-para-o-mvp-model-view-presenter.html). Existe algum caso que esta abordagem não é recomendada (no sentido de tecnologias utilizadas no lado do cliente e formas de interação com o servidor)?

Att.

I

Adelar:
Olá pessoal,
das formas de implementação do MVP a que me parece mais adequada é a PassiveView (link de um dos posts anteriores http://fabiolnm.blogspot.com/2009/12/do-mvc-para-o-mvp-model-view-presenter.html). Existe algum caso que esta abordagem não é recomendada (no sentido de tecnologias utilizadas no lado do cliente e formas de interação com o servidor)?

Att.


Olá… :smiley:

Na minha opinião independentemente de como a sua arquitetura esteja distribuída, o MVP estará sempre presente no nodo Cliente no andar Apresentação ( Não entendeu a palavra ‘andar’? Clique aqui! ) principalmente se você deseja desenvolver software baseado na API Swing. Como você citou a existência de um servidor e provavelmente queira manter a aplicação lá, então os objetos do andar de Apresentação irão chamar métodos dos objetos no andar de Domínio/Negócio que servirá apenas como uma fachada aos objetos do andar de Integração, o qual realizará a comunicação com o nodo Servidor. Veja, não mudamos nada no andar Apresentação que pode continuar normalmente no nodo Cliente. Já WEB não sei informar, realmente não conheço. Para mim, cabe sim MVP no desenvolvimento de bons softwares assim como o próprio link que colocou cita MVP como sendo uma prática recomendada até mesmo pelo pessoal do Google.

Mas aguarde a opinião dos demais… sou muito leiga para opinar, não conheço o desenvolvimento WEB… espero estar certa.
Até mais… :slight_smile:

Adelar

É justamente com Swing que me refiro à arquitetura do cliente. Entretanto, devido às formas de interações com o servidor (chamadas assíncronas, chamadas aleatórias, etc.) a forma escolhida para adaptar a arquitetura poderia afetar o próprio modelo adotado, tornando algo simples em algo complexo de manter (a longo prazo principalmente, e por isto minha preocupação). Tenho lido sobre mas não encontrei evidências de casos em que não se deve aplicar este modelo (MVP PassiveView)… vendo isso creio que seja o mais adequado, principalmente para as manutenções e evoluções futuras do software.

Obrigado por opinar… qualquer dúvida volto aqui :smiley:

Att.

I

No caso, você está se referindo ao Swing sendo uma camada de código presente no andar Cliente do nodo Cliente de sua arquitetura.

Não vejo problemas neste caso. Se na sua arquitetura os andares dos nodos estiverem com suas responsabilidades bem definidas, não encontrará problemas complexos durante a manutenção. Lembre-se que o MVP ‘está presente/é usado’ no andar de Apresentação. O andar Modelo não poderá ser afetado pelo andar Apresentação. Se isto acontece, existe um problema na sua arquitetura. :shock:

Sim o MVP é uma best practice no Google I/O 2009 para o desenvolvimento de aplicações GWT. Mas cabe muito bem qualquer seja a camada de código presente no Cliente (Só não sei dizer em WEB).

Obrigada :smiley:

C

Pessoal Muito Obrigado! :smiley:
Realmente um tópico bastante esclarecedor e muito didático! parabéns a todos!!

Abraços

D

reabrindo a discussão que creio eu ja bastante debatida no forum, seria correto a view ter um metodo que exibe uma mensagem na tela?
tipo:

Option displayMessage( TypeMessage type, String Message);

onde o option retornaria a opção selecionada pelo usuário( se ele clicou em ok, No, cancel etc…) e esse método
ser chamado pelo presenter para delegar mensagens para a view exibir? por exemplo no caso de o presenter querer repassar uma mensagem contendo a descrição de uma exceção.

att, Paulo Rogerio.

Criado 9 de junho de 2009
Ultima resposta 14 de fev. de 2011
Respostas 270
Participantes 30