Dúvida em estrutura em MVC

33 respostas
S

Olá, estou fazendo meu TCC e estou em dúvida quanto a estrutura do projeto, cria três pacotes que são util, bussiness, control e model, em business coloquei as classes DAO, em control pus as actions, em model coloquei as classes mapeadas do banco e em util coloquei classes usadas em geral no sistema como o validador de CPF/CNPJ, hibernateUtil entre outras. Esse estrutura está correta?

Minha outra dúvida é quanto a uso de interface, não estou falando de telas do sistema, mas das interfaces que devem ser implementadas nas classes, isso é obrigatório faz parte do MVC e em quanto isso é util?

33 Respostas

R

eu acho que os DAOs pertencem a camada de model, as suas classes de serviço (que implementam regras de negócio) é que ficam com o business.

Quanto à duvida de interfaces, tem um post do ViniGodoy onde ele fala sobre isso. ele usa listas como exemplo, mas a idéia pode ser aplicada a qualquer caso.

http://www.guj.com.br/java/55387-quanto-list-x--new-arraylist-e-melhor-do-que-arraylist-x--new-arraylist

só mais 2 observações, que não consigo não comentar:

1 - você criou 4 pacotes, não 3.
2 - é business, não bussiness.

J

digaoneves:
eu acho que os DAOs pertencem a camada de model, as suas classes de serviço (que implementam regras de negócio) é que ficam com o business.

Quanto à duvida de interfaces, tem um post do ViniGodoy onde ele fala sobre isso. ele usa listas como exemplo, mas a idéia pode ser aplicada a qualquer caso.

http://www.guj.com.br/java/55387-quanto-list-x--new-arraylist-e-melhor-do-que-arraylist-x--new-arraylist

só mais 2 observações, que não consigo não comentar:

1 - você criou 4 pacotes, não 3.
2 - é business, não bussiness.

Acho que vc está bem equivocado.
Model, como o próprio nome sugere, é seu modelo. Onde ficam suas regras de negócio. E em nenhum momento devem ter regras de negócio num DAO.
Esse Business é um nome mais ‘pomposo’ para o model.
E cara, só use interface se isso for realmente necessário. Vale a mesma coisa para patterns. Se vc está procurando lugar para inserí-los, então pq alguma coisa está bem errada.

R

j0nny:
Acho que vc está bem equivocado.
Model, como o próprio nome sugere, é seu modelo. Onde ficam suas regras de negócio. E em nenhum momento devem ter regras de negócio num DAO.
Esse Business é um nome mais ‘pomposo’ para o model.
E cara, só use interface se isso for realmente necessário. Vale a mesma coisa para patterns. Se vc está procurando lugar para inserí-los, então pq alguma coisa está bem errada.

Não sei aonde me equivoquei.

Ao meu ver é assim

Model -> é a parte de dados, simples, onde (em um projeto Java EE) ficam as entidades e os DAOs.
View -> É a camada de visão, interface ao usuário
Controller -> Onde fica toda a “lógica intermediária”, onde é implementada toda a regra de negócio

Ou estou errado?

O que sei que pode acontecer é a confusão entre Controller do modelo MVC, e um nome comum aos ManagedBeans, que é QualquerCoisaController, porém os dois não são a mesma coisa. Sequer estão na mesma “fatia” do modelo MVC.

J

digaoneves:
j0nny:
Acho que vc está bem equivocado.
Model, como o próprio nome sugere, é seu modelo. Onde ficam suas regras de negócio. E em nenhum momento devem ter regras de negócio num DAO.
Esse Business é um nome mais ‘pomposo’ para o model.
E cara, só use interface se isso for realmente necessário. Vale a mesma coisa para patterns. Se vc está procurando lugar para inserí-los, então pq alguma coisa está bem errada.

Não sei aonde me equivoquei.

Ao meu ver é assim

Model -> é a parte de dados, simples, onde (em um projeto Java EE) ficam as entidades e os DAOs.
View -> É a camada de visão, interface ao usuário
Controller -> Onde fica toda a “lógica intermediária”, onde é implementada toda a regra de negócio

Ou estou errado?

O que sei que pode acontecer é a confusão entre Controller do modelo MVC, e um nome comum aos ManagedBeans, que é QualquerCoisaController, porém os dois não são a mesma coisa. Sequer estão na mesma “fatia” do modelo MVC.

DAO’s não cuidam de regras de negócio, portando não são modelos. Se o seu DAO cuida de regras de negócio, então é melhor rever sua implementação.
DAO’s fazem parte de infra, ou seja, apenas uma abstração de como seus dados serão persistidos/recuperados.

Resumindo:
Model: sua entidade, que tem suas regras de negócio tbm. Cuidado com modelos anêmicos, estamos trabalhando com OO, e não estruturação de dados.
Controller: Recebe requisições da view e delega para a camada de domínio. Controller NÃO implementa regra de negócio.
Infra: DAO, Email, etc.
View: HTML, GWT, Swing, etc.
Service/Business/Whaterer: Cuida de regras de negócio quando há mais de uma entidade envolvida.

R

Em momento nenhum eu disse que o DAO implementa regra de negócio, veja:

digaoneves:
eu acho que os DAOs pertencem a camada de model, as suas classes de serviço (que implementam regras de negócio) é que ficam com o business.

Percebeu a vírgula aí?

Agora pega esse monte de divisões que você fez e coloca no MVC, quem fica no M, no V, e no C ?

Na minha opinião você confundiu a classe Controller, com o Controller do modelo MVC, como eu disse acima.

J

Percebeu a vírgula aí?

Agora pega esse monte de divisões que você fez e coloca no MVC, quem fica no M, no V, e no C ?

Na minha opinião você confundiu a classe Controller, com o Controller do modelo MVC, como eu disse acima.

Model pra vc é o que?

M -> Model (entidade, bean, seilá o nome), Service/Business/Whatever. Sua REGRA DE NEGÓCIO.
V -> HTML, Swing, interface do usuário.
C -> Controller, quem recebe as ações da view e repassa pro modelo.

R

Pra mim o Model era a parte que lidava só com dados, sem regra nenhuma de negócio aplicada (Entidades e DAOs, basicamente).
pra mim regras de negócio eram a parte do Control, e o ManagedBean (no caso) estava ligado à View.

G

Eu acho que em um modelo simplista como o MVC suas regras de negócios ficariam no model sim. Em ambiente distribuído eu não utilizo MVC e sim multi-camadas.

J

digaoneves:
Pra mim o Model era a parte que lidava só com dados, sem regra nenhuma de negócio aplicada (Entidades e DAOs, basicamente).
pra mim regras de negócio eram a parte do Control, e o ManagedBean (no caso) estava ligado à View.

Saia um pouco do JSF para entender melhor.

Alguns links para vc ler:
http://www.arquiteturajava.com.br/livro/cuidado-com-o-modelo-anemico.pdf
http://martinfowler.com/bliki/AnemicDomainModel.html
http://pt.wikipedia.org/wiki/MVC

V

Model são as classes de negócio. Quando o MVC foi criado, model referia-se ao “modelo de dados”.

Portanto, não existe uma regra clara para dizer se as classes que dão suporte as classes de negócio são também parte do model. Por isso, não adianta perder tempo discutindo. Há quem argumente que se o model é um “modelo de dados”, então o banco de dados é parte desse modelo, assim como as classes para interfacear com ele.

O fato é que, DAOs certamente não são parte do controller e nem da view. E, se não são parte do model, estão abaixo dele, em algo que não é descrito pelo MVC clássico.

Vale lembrar que persistência é uma das qualidades dos objetos, assim como é a identidade, os atributos e os métodos. O problema é que as linguagens implementam isso de maneira imperfeita, apenas levando em conta a memória volátil. Criamos DAOs apenas porque precisamos de mecanismos de persistência auxiliares para suprir essa deficiência de implementação das linguagens. Não é incomum ver frameworks ORM que criam em objetos métodos como save(), simulando o fato do objeto ter persistência própria.

Isso é parte do model? Eu também prefiro usar a terminologia do J0nny e dizer que não. Dizer que são classes de serviço auxiliares, e que não são descritas pelo MVC puro. Os dados, portanto, só seriam válidos em sua forma de objeto, não na forma de registros no banco. Mas entendo quem possa citar que esse serviço é apenas um submódulo do model.

V

Uma longa discussão sobre isso:

Ah, e sim, regras de negócio estão no modelo, não no controle.

O controle é a parte responsável por comunicar o model com a view. Por isso, em programas desktop, ele é praticamente inexistente.

J

ViniGodoy:
Model são as classes de negócio. Quando o MVC foi criado, model referia-se ao “modelo de dados”.

Portanto, não existe uma regra clara para dizer se as classes que dão suporte as classes de negócio são também parte do model. Por isso, não adianta perder tempo discutindo. Há quem argumente que se o model é um “modelo de dados”, então o banco de dados é parte desse modelo, assim como as classes para interfacear com ele.

O fato é que, DAOs certamente não são parte do controller e nem da view. E, se não são parte do model, estão abaixo dele, em algo que não é descrito pelo MVC clássico.

Vale lembrar que persistência é uma das qualidades dos objetos, assim como é a identidade, os atributos e os métodos. O problema é que as linguagens implementam isso de maneira imperfeita, apenas levando em conta a memória volátil. Criamos DAOs apenas porque precisamos de mecanismos de persistência auxiliares para suprir essa deficiência de implementação das linguagens. Não é incomum ver frameworks ORM que criam em objetos métodos como save(), simulando o fato do objeto ter persistência própria.

Isso é parte do model? Eu também prefiro usar a terminologia do J0nny e dizer que não. Dizer que são classes de serviço auxiliares, e que não são descritas pelo MVC puro. Os dados, portanto, só seriam válidos em sua forma de objeto, não na forma de registros no banco. Mas entendo quem possa citar que esse serviço é apenas um submódulo do model.

Fora que, num modelo MVC, não necessariamente teremos persistência de dados.
No caso do Rails, o método save do próprio objeto apenas informa que seus dados serão persistidos. Portando é de responsabilidade de alguém outro saber como fazer isso.
PS: Acho que no Rails os Adapters fazem esse trabalho de persistência, o método save do modelo apenas ‘delega’ à ele.

H

Model - classes que recuperam e persistem algum tipo de objeto, classes que definem algum tipo de dado com métodos gets e sets. Coloque aqui os beans e os DAOs
View - classes responsáveis pela interface com o usuário
Controller - suas regras de negócio

J

henriquecosta:
Model - classes que recuperam e persistem algum tipo de objeto, classes que definem algum tipo de dado com métodos gets e sets. Coloque aqui os beans e os DAOs
View - classes responsáveis pela interface com o usuário
Controller - suas regras de negócio

Vc realmente leu os links que coloquei anteriormente nessa thread?

V

Uma coisa é fato, o controller não contém as regras de negócio.

Ele pode conter validações, baseadas nessas regras (assim como a view também tem). Em desktop, até isso perde o sentido, pois o mecanismo impede que um usuário burle a view, como ocorre na web. Por isso, frameworks desktop geralmente usam uma versão simplificada do MVC.

Mas a responsabilidade pelas regras, em última instância, é do model.

O model deve representar os objetos sendo desenhados, em sua completude. Deveria ser possível criar uma nova aplicação, com controllers e interface diferentes, apenas baseado no model, sem ferir regras de negócio.

Fora que, num modelo MVC, não necessariamente teremos persistência de dados.
No caso do Rails, o método save do próprio objeto apenas informa que seus dados serão persistidos. Portando é de responsabilidade de alguém outro saber como fazer isso.
PS: Acho que no Rails os Adapters fazem esse trabalho de persistência, o método save do modelo apenas ‘delega’ à ele.

Pois é, aí entra novamente a discussão semântica. Há quem acredite que isso deva estar abaixo do model, e há quem acredite que isso é um sub-módulo do model. Agora, o importante é saber que isso não é nem view, nem controller. E que, o modelo MVC não define se persistência é ou não um atributo do model (portanto, essa é uma zona cinza que sempre gerará discussão).

Eu, particularmente, concordo com você. Até porque, tipicamente, podemos ter mais de um mecanismo de persistência para o mesmo tipo de classe. Fica mais fácil pensar conceitualmente no model como as classes que estão na memória.

H

Acabei de ler, bacana! Nunca gostei mesmo deste padrão getters and setters, realmente na maioria das classes eles não eram nada úteis, obrigado pelos links!

R

é, o henriquecosta mostrou que eu não fui o único que aprendeu errado, rs.

Parte culpa de um ex-gerente meu que ensinou, mas 99% culpa minha por não ter ido atrás e me informar mais.
Realmente links muito bons, provavelmente vou programar diferente daqui em diante, rs.

Realmente eu estava equivocado.

Obrigado pelos eslcarecimentos :slight_smile:

S

Essa discussão cresceu, de fato o que entendi de MVC está todo errado.

no VIEW ao menos acertei, onde estão as minha telas.

Em Control coloquei as classes que recebem as requisições da view, coloquei as regras de negócio
lá tb.

Na Business, que no caso não existe de acordo com vcs no MVC, coloquei os DAOs que fazem a persistência/ busca dos objetos

Na Model coloquei as classes mapeadas das tabelas do banco como classe Pessoa.

Percebo que está tudo errado, de acordo com vcs, como eu deveria organizar isso? Se devo tirar as regras de negócio de Controller, onde deveriam ficar?

Percebo que meu conceito de MVC está todo errado, que m…

J

Shatemui:
Essa discussão cresceu, de fato o que entendi de MVC está todo errado.

no VIEW ao menos acertei, onde estão as minha telas.

Em Control coloquei as classes que recebem as requisições da view, coloquei as regras de negócio
lá tb.

Na Business, que no caso não existe de acordo com vcs no MVC, coloquei os DAOs que fazem a persistência/ busca dos objetos

Na Model coloquei as classes mapeadas das tabelas do banco como classe Pessoa.

Percebo que está tudo errado, de acordo com vcs, como eu deveria organizar isso? Se devo tirar as regras de negócio de Controller, onde deveriam ficar?

Percebo que meu conceito de MVC está todo errado, que m…

Como falei, regras de negócio da entidade, devem ficar na entidade. Evite objetos anêmicos.
Regras de negócio que envolvem mais de uma entidade, vc pode criar classes Service, Business, como preferir. Lembrando que mesmo essas classes ficam na camada do Model (modelo/regras de negócio).

A

Para ajudar a clarear um pouco essas questões, cito abaixo um trecho de um livro de Martin Fowler:

Link para o livro do Martin Fowler:
http://books.google.com.br/books?id=vpHqYZcmeKsC&printsec=frontcover&dq=martin+fowler+padr%C3%A3o+de+arquitetura+de+aplica%C3%A7%C3%B5es+corporativas+mvc&hl=pt-BR&sa=X&ei=EN_DT8CnL4P26AGBoITZCg&ved=0CEEQ6AEwAA#v=onepage&q&f=false

No livro Utilizando UML e Padrões, Craig Larman fala sobre um outro tipo de controlador, que fica na camada de domínio ou modelo. É um controlador que possui conceitos de negócio, e pode coordenar diversas classes de negócio. Esse tipo de controlador pode representar um caso de uso ou o sistema como um todo.
Acho que a confusão se deve um pouco à existência de vários tipos de controladores.

Nesse mesmo livro (pág. 322 da 3a. edição), Craig Larman diz que no Processo Unificado e no método Objectory de Jacobson há três tipos de objetos:

  • objetos de fronteira - abstrações das interfaces (por exemplo, classes Swing).
  • objetos de entidade - objetos de domínio (negócio ou modelo) independentes da aplicação e geralmente persistentes.
  • objetos de controle - são tratadores de caso de uso - são os controladores que ficam na camada de domínio, de que falei.

Link para o livro do Craig Larman:
http://books.google.com.br/books?id=ZHtcynS03DIC&printsec=frontcover&hl=pt-BR&source=gbs_ge_summary_r&cad=0#v=onepage&q&f=false

V

al.barbosa:
No livro Utilizando UML e Padrões, Craig Larman fala sobre um outro tipo de controlador, que fica na camada de domínio ou modelo. É um controlador que possui conceitos de negócio, e pode coordenar diversas classes de negócio. Esse tipo de controlador pode representar um caso de uso ou o sistema como um todo.
Acho que a confusão se deve um pouco à existência de vários tipos de controladores.

Provavemente isso é uma tradução imprecisa para o padrão Mediator. A referência que você usou é em inglês?

A

ViniGodoy:
al.barbosa:
No livro Utilizando UML e Padrões, Craig Larman fala sobre um outro tipo de controlador, que fica na camada de domínio ou modelo. É um controlador que possui conceitos de negócio, e pode coordenar diversas classes de negócio. Esse tipo de controlador pode representar um caso de uso ou o sistema como um todo.
Acho que a confusão se deve um pouco à existência de vários tipos de controladores.

Provavemente isso é uma tradução imprecisa para o padrão Mediator. A referência que você usou é em inglês?

Não, a referência é em Português. Na resposta anterior coloquei o link para a o livro on-line, é o Utilizando UML e Padrões do Craig Larman. Não é o padrão Mediator, da Gangue dos Quatro. O livro apresenta os padrões denominados GRASP (General Responsibility Assignment Software Patterns). São padrões e ao mesmo tempo princípios para atribuir responsabilidades. Alguns deles: Especialista na Informação, Criador, Acoplamento Baixo, Coesão Alta e Controlador. Além deles, o livro ensina alguns padrões da Gangue dos Quatro.

Cito abaixo um trecho do livro que fala sobre os padrões da Gangue dos Quatro:

Utilizando UML e Padrões - pág. 290:
… durante a atividade de desenho (e codificação), aplicamos vários princípios de projeto OO, como GRASP e os padrões de projeto da Gangue dos Quatro (Gang-of-Four - GoF).

Cito abaixo uma explicação do livro sobre o GRASP:

Abaixo a definição do padrão Controlador no livro:

E abaixo a explicação do livro sobre a diferença entre o controlador GRASP e o controlador MVC:

V

Bom, esse trecho já diz tudo. Que o controller do MVC apenas “controla a interação e o fluxo de página da IU”.
É o que eu e o j0nny estavamos falando. E é por isso que ele quase some em desktop (esse controle é trivialmente feito pela linguagem).

Mas talvez daí suja tanta confusão sobre o papel do controller.

PS: Também gosto muito desse livro. Tenho impresso em casa, e já li de ponta-a-ponta.

A

Isso. O Martin Fowler diz que Controlador é usado em vários contextos diferentes. Acho que daí surge uma certa confusão.

A

Gostei muito desde tópico, e me deu a entender que eu estava pensando em MVC de forma errada. Tipo, utilizava o MODEL somente para a comunicação com o banco, e o CONTROLLER usava como a camada de negócios, que acredito que seja a entrada o processamento e saida para view.

Posso estar errado, trabalho com PHP e agora estou estagiando e aprendendo (também) J2EE para web.

Gostaria que alguem me desse um pequeno exemplo de aplicação, ou seja, como funcionaria se eu tivesse por exemplo uma tabela CLIENTES e quisesse mostrar dados do cliente, assim como cadastrar, alterar e excluir.

Posso esta pedindo muito, mas um pequena explicação irá me ajudar a compreender o que eu possa estar ou não fazendo de errado.

A

Atendendo ao pedido, e para ficar mais claro o padrão MVC, resolvi colocar um exemplo simples de CRUD para Web no padrão MVC.

Estou seguindo a abordagem sugerida no livro Core Servlets e Javaserver Pages, de Marty Hall e Larry Brown, capítulo 15: como integrar servlets e JSP: a arquitetura Modelo Visão Controlador (MVC). Abaixo um link para o livro on-line (este link está em Inglês, tem o livro à venda em Português).

[url]http://www.pdf.coreservlets.com/MVC.pdf[/url]

A classe ServletCliente funciona como o controlador MVC.

Os JSP´s funcionam como a view.

Na parte do modelo, utilizo a classe RoteiroCliente. Nessa classe aplico o padrão Roteiro de Transação (Transaction Script) do livro Padrões de Arquitetura de Aplicações Corporativas, de Martin Fowler. Essa é a classe em que coloco as regras de negócio. Neste exemplo as únicas regras de negócio são: o cliente deve ter 18 anos de idade ou mais, e o seu nome não pode ser vazio. Cito abaixo a página 72 do livro do Martin Fowler, que fala sobre a possibilidade de usar Roteiros de Transação como modelo:

Martin Fowler - Padroes de Arquitetura de Aplicações Corporativas:
A primeira e mais importante razão para aplicar o Modelo Vista Controlador é assegurar que os modelos estejam completamente separados da apresentação Web. (...) Colocar o processamento em objetos Roteiro de Transação ou Modelo de Domínio também tornará mais fácil testá-los. (...)

Poderia também utilizar uma classe de domínio como modelo - isso seria o padrão Modelo de Domínio citado acima (e o DDD - Domain-Driven Design). Porém o Martin Fowler recomenda utilizar um Mapeador de Dados (para o mapeamento objeto-relacional) ao utilizar um Modelo de Domínio mais rico, ou um Registro Ativo (padrão em que o modelo e o acesso a dados ficam na mesma classe) para domínios simples. Como eu não quis entrar na complexidade do mapeamento objeto-relacional neste exemplo, e queria separar o acesso a dados das regras de negócio, decidi utilizar o Roteiro de Transação.

A classe ClienteTO funciona como um Transfer Objetc, ou Objeto de Transferência de Dados. Esta classe serve apenas para transportar dados entre as camadas - não é propriamente uma classe de negócios.

E utilizo a classe ClienteDAO.java para interagir com o banco de dados. Ela é um Data Access Object. Para o exemplo funcionar, não coloquei um acesso real a banco de dados. Criei uma List na classe para armazenar os dados. Num caso real eu iria colocar o SQL nesta classe. Pode parecer que a classe ClienteDAO tem métodos muito parecidos com a classe RoteiroCliente. Isso acontece porque trata-se de um CRUD simples. A classe RoteiroCliente encapsula a regra de negócio, enquanto ClienteDAO encapsula o acesso a banco de dados. Num caso muito simples, é possível que sejam apenas uma classe - isso seria o padrão Registro Ativo, do livro Arquitetura de Aplicações Corporativas do Martin Fowler, pág. 165.

Segundo o Martin Fowler o valor do MVC está em duas separações:
1 - separar a apresentação do modelo (conforme trecho citado acima)
2 - separar a vista do controlador.

Cito abaixo um trecho em que ele fala sobre a segunda separação (pág. 317):

Martin Fowler - Padroes de Arquitetura de Aplicações Corporativas:
A separação entre a vista e o controlador é menos importante, de modo que eu só a recomendaria quando fosse realmente útil. Para sistemas com clientes ricos, isso acaba sendo quase nunca, embora seja comum em front ends Web no qual o controle é separado. A maioria dos padrões sobre o projeto Web é baseada nesse princípio.

Por isso eu não acho muito útil o MVC para aplicações Java desktop na maioria dos casos. Porém acho importante a primeira separação: separar a apresentação do modelo - para esse tipo de aplicação.

Abaixo o código do exemplo:

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Aplicativo Exemplo CRUD Clientes</h1>
        <p> Regra de Negócio: um cliente tem que possuir no mínimo 18 anos. </p>
        <a href = "ServletCliente?acao=listar">Entrar</a>
    </body>
</html>
listaClientes.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="to.ClienteTO"%>
<jsp:useBean id="lista" 
             scope="request" 
             class="java.util.List<to.ClienteTO>"/>
<jsp:useBean id="erro" 
             scope="request" 
             class="java.lang.String"/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Lista</title>
    </head>
    <body>
        <h2>Cadastro de Clientes</h2>
        <a href="ServletCliente?acao=iniciarInclusao">
            Novo Cliente
        </a>
        <a href="index.jsp">
            Início
        </a>
        <table border="1" width="70%">
            <tr>
            <b>
                <td>Nome</td>
                <td>Idade</td>
                <td>Opções</td>
            </b>
            </tr>
            <% for(ClienteTO c:lista) { %>
                <tr>
                    <td><%=c.getNome()%></td>
                    <td><%=c.getIdade()%></td>
                    <td>
                        <a href="ServletCliente?acao=iniciarAlteracao&codigo=<%=c.getCodigo()%>">
                            Alterar
                        </a>
                        <a href="ServletCliente?acao=excluir&codigo=<%=c.getCodigo()%>">
                            Excluir
                        </a>
                    </td>
                </tr>
            <% } %>
        </table>
        <font color="#FF0000">
            <% if(erro != null) { %> 
               <%=erro%>
            <% } %> 
        </font>
    </body>
</html>

cliente.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="to.ClienteTO"%>
<jsp:useBean id="dado" 
             scope="request" 
             class="to.ClienteTO"/>
<jsp:useBean id="erro" 
             scope="request" 
             class="java.lang.String"/>
<%!
    String blanknullStr(String s) {
       return (s==null) ? "" : s;
    }
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h2>Cadastro de Clientes</h2>
        <form action="ServletCliente" method="post">
            <input type="hidden" name="acao" 
            value="<%=(dado.getCodigo()==0)?"incluir":"alterar"%>">
            <input type="hidden" name="codigo" 
            value="<%=dado.getCodigo()%>">
            Nome*:
            <input type="text" name="nome" 
            value="<%=blanknullStr(dado.getNome())%>">
            <br>
            Idade*:
            <input type="text" name="idade" 
            value="<%=dado.getIdade()%>">
            <br>
            <input type="submit" value="Enviar">
        </form>
        <font color="#FF0000">
            <% if(erro != null) { %> 
               <%=erro%>
            <% } %> 
        </font>
    </body>
</html>

ServletCliente.java

package servlet;

import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import roteiro.RoteiroCliente;
import to.ClienteTO;

/**
 *
 * @author calazans
 */
@WebServlet(name = "ServletCliente", urlPatterns = {"/ServletCliente"})
public class ServletCliente extends HttpServlet {
    
    RoteiroCliente roteiro = new RoteiroCliente();

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String acao = request.getParameter("acao");
        
        if(acao == null) acao = "listar";
        
        if(acao.equals("listar")){
            listar(request, response);
        } else if(acao.equals("iniciarInclusao")){
            iniciarInclusao(request, response);
        } else if(acao.equals("iniciarAlteracao")){
            iniciarAlteracao(request, response);
        } else if(acao.equals("incluir")){
            incluir(request, response);
        } else if(acao.equals("alterar")){
            alterar(request, response);
        } else if(acao.equals("excluir")){
            excluir(request, response);
        } else {
            listar(request, response);
        }
    }
    
    private void listar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<ClienteTO> lista = roteiro.carregarTodos();
        request.setAttribute("lista", lista);
        despacha(request, response, "listaClientes.jsp");
        
    }
    
    private void iniciarInclusao(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        despacha(request, response, "cliente.jsp");
    }
    
    private void iniciarAlteracao(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int codigo = Integer.parseInt(request.getParameter("codigo"));
        request.setAttribute("dado", roteiro.carregarPorCodigo(codigo));
        despacha(request, response, "cliente.jsp");
    }
    
    private void incluir(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ClienteTO cliente = new ClienteTO();
        try{
            String nome = request.getParameter("nome");
            int idade = parseIdade(request.getParameter("idade"));
            cliente = new ClienteTO(0, nome, idade );
            roteiro.incluir(cliente);
            listar(request,response);
        }catch(Exception e){
            request.setAttribute("dado", cliente);
            request.setAttribute("erro", "Ocorreu o seguinte erro: " + e.getMessage());
            despacha(request, response, "cliente.jsp");
        }
    }
    
    private void alterar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ClienteTO cliente = new ClienteTO();
        try{
            int codigo = Integer.parseInt(request.getParameter("codigo"));
            String nome = request.getParameter("nome");
            int idade = parseIdade(request.getParameter("idade"));
            cliente = new ClienteTO(codigo, nome, idade );
            roteiro.alterar(cliente);
            listar(request,response);
        }catch(Exception e){
            request.setAttribute("dado", cliente);
            request.setAttribute("erro", "Ocorreu o seguinte erro: " + e.getMessage());
            despacha(request, response, "cliente.jsp");
        }
    }
    
    private void excluir(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int codigo = Integer.parseInt(request.getParameter("codigo"));
        try{
            roteiro.excluir(codigo);
            listar(request,response);
        }catch(Exception e){
            request.setAttribute("erro", "Ocorreu o seguinte erro: " + e.getMessage());
            List<ClienteTO> lista = roteiro.carregarTodos();
            request.setAttribute("lista", lista);
            despacha(request, response, "listaClientes.jsp");
        }
    }
    
    private int parseIdade(String idade) throws Exception{
        try{
            return Integer.parseInt(idade);
        }catch(Exception e){
            throw new Exception("Campo idade deve ser um valor numerico");
        }
    }
    
    private void despacha(HttpServletRequest request, HttpServletResponse response, String pagina)
            throws ServletException, IOException {
        RequestDispatcher rd = request.getRequestDispatcher(pagina);
        rd.forward(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Servlet para Manter Clientes";
    }
}

RoteiroCliente.java

package roteiro;

import dao.ClienteDAO;
import java.util.List;
import to.ClienteTO;

/**
 *
 * @author calazans
 * Roteiro de Transação de Cliente
 */
public class RoteiroCliente {
        
    private ClienteDAO clienteDAO = new ClienteDAO();
    
    public void incluir(ClienteTO cliente) throws Exception {
        validar(cliente);
        clienteDAO.incluir(cliente);
    }
    
    public void alterar(ClienteTO cliente) throws Exception{
        validar(cliente);
        clienteDAO.alterar(cliente);
    }
    
    public void excluir(int codigo) throws Exception{
        clienteDAO.excluir(codigo);
    }
    
    public ClienteTO carregarPorCodigo(int codigo){
        return clienteDAO.carregarPorCodigo(codigo);
    }
    
    public List<ClienteTO> carregarTodos(){
        return clienteDAO.carregarTodos();
    }
    
    private void validar(ClienteTO cliente) throws Exception{
        if(cliente.getIdade() < 18){
            throw new Exception("Idade invalida.");
        }
        if(cliente.getNome() == null || cliente.getNome().equals("")){
            throw new Exception("Nome invalido.");
        }
    }
}

ClienteTO.java

package to;

/**
 *
 * @author calazans
 * Transfer Object de Cliente
 */
public class ClienteTO {
    private int codigo;
    private String nome;
    private int idade;
    
    public ClienteTO(){
        codigo = 0;
        nome = "";
        idade = 0;
    }
    
    public ClienteTO(int codigo, String nome, int idade) {
        this.codigo = codigo;
        this.nome = nome;
        this.idade = idade;
    }

    public int getIdade() {
        return idade;
    }

    public String getNome() {
        return nome;
    }

    public int getCodigo() {
        return codigo;
    }

    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }
   
    @Override
    public boolean equals(Object obj) {
        ClienteTO c = (ClienteTO) obj;
        if(c.getCodigo()==this.getCodigo()) return true;
        else return false;
    }   
}

ClienteDAO.java

package dao;

import java.util.ArrayList;
import java.util.List;
import to.ClienteTO;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author calazans
 * Data Access Object de Cliente
 */
public class ClienteDAO {
    private List<ClienteTO> listaClientes = new ArrayList();
    public ClienteDAO(){
        listaClientes.add(new ClienteTO(1, "Francisco Paulo Souza", 31));
        listaClientes.add(new ClienteTO(2, "Maria Joana Souza", 29));
        listaClientes.add(new ClienteTO(1, "Paulo Franco Silva", 32));
    }
    
    public ClienteTO carregarPorCodigo(int codigo){
        for(ClienteTO c:listaClientes){
            if(c.getCodigo()==codigo) return c;
        }
        return null;
    }
    
    public List<ClienteTO> carregarTodos(){
        return listaClientes;
    }
    
    public void incluir(ClienteTO cliente) {
        cliente.setCodigo(novoCodigo());
        listaClientes.add(cliente);
    }
    
    public void alterar(ClienteTO cliente) throws Exception{
        for(int posicao = 0; posicao<listaClientes.size(); posicao++){
            if(listaClientes.get(posicao).equals(cliente)){
                listaClientes.set(posicao,cliente);
                return;
            }
        }
        throw new Exception("Cliente nao localizado.");
    }
    
    public void excluir(int codigo) throws Exception{
        for(ClienteTO c:listaClientes){
            if(c.getCodigo() == codigo){
                listaClientes.remove(c);
                return;
            }
        }
        throw new Exception("Cliente nao localizado.");
    }
    
    private int novoCodigo(){
        int maior = 0;
        for(ClienteTO c:listaClientes){
            maior = c.getCodigo() > maior ? c.getCodigo() : maior;
        }
        return ++maior;
    }
}

Anexei um diagrama ilustrando essa arquitetura. O diagrama é apenas para mostrar a estrutura de camadas, não corresponde exatamente aos pacotes java.

Fiz esse projeto no NetBeans. Anexei o projeto.

Concluo dizendo que esta é uma forma de estruturar a arquitetura do sistema. Há várias outras formas possíveis. A arquitetura do sistema tem que ser sempre pensada de acordo com as características do sistema. No livro do Martin Fowler há várias abordagens de camadas, e explicações sobre quando utilizar uma ou outra abordagem. A quem se interessar, coloco o link:

[url]http://books.google.com.br/books?id=vpHqYZcmeKsC&printsec=frontcover&dq=martin+fowler+padr%C3%B5es+arquitetura&hl=pt-BR&sa=X&ei=NCbvT9bQLKPX6gHJ_NSXBg&ved=0CDYQ6AEwAA#v=onepage&q=martin%20fowler%20padr%C3%B5es%20arquitetura&f=false[/url]

A

Obrigado amigo. Irei dar um olhada para bem entender e não mais fazer errado.

:smiley:

F

Recomendo fortemente tu dar uma estudada sobre DDD (domain driven design) de Eric Evans. Se possível compre o livro pois é muito bom.

Em termos de arquitetura de camadas essa “filosofia” define 4 camadas:

  • UI (interface com usuário)
  • Aplicação (controladores, frameworks, etc…)
  • Domínio (negócio/regras, entidades)
  • Infraestrutura (consumo de serviços de outros sistemas: banco de dados, email, webservices)

o enfoque está na camada de domínio, a qual representa os conceitos do problema, e deve ter o mínimo possível de dependência com outras tecnologias (frameworks, etc) pois no mundo real não existe tecnologia (enviar um email tem o conceito “enviar email” e não “m = new SimpleEmail(); m.set… m.send();”). No livro é descrito várias técnicas para isolamento do negócio, conceitos como VO, Repository, Services, Módulos, Fábricas, Agregadores… (Alguns do GoF com roupa nova :slight_smile: )

Em comparação com o MVC eu vejo o DDD como uma evolução, em termos de conceito. Alguns podem falar que é igual ao MVC com a camada de infra.
Mas se estudar sobre, vai ver que é muito mais profundo, claro, específico e aplicável.

Quanto ao DAO, com uso de ORM (JPA, hibernate, etc…), dependendo da complexidade da aplicação eu vejo desnecessário, mas se for usar, use o conceito de Repository e coloque as implementações na camada de infra, pois o padrão DAO foi criado pra resolver problemas de suporte a multiplos bancos de dados na época que usavamos JDBC.

A vantagem que você verá de imediato é a facilidade de testar sua aplicação, manutenter e evoluir, e irá pensar primeiro no domínio do negócio e depois na solução técnica.

R

Pra mim também sempre foi na camada model , mas aonde eu trabalhava isso era feito na camada de controller em actions.

Agora mexo com EJB e não utilizo mais DAOs , pois entendo que eles são desnecessários.

O que utilizo são classes de serviços , interfaces que fornecem acesso aos EJBs que por sua vez sim fazem o trabalho de isolar realmente a lógica da aplicação das demais camadas.

No meu model só tem entidades que represetam tabelas do banco.

Acho que conceitualmente é muito organizado e faz divisão clara do MVC.

Como disseram não é errado dizer que é no model , porque no momento em que foi criado isso não era descrito.

Só tem três camadas então vai ser em uma delas MVC , sempre achei errado colocar no controller pq sempre tive a visão que essa camada era de gerenciamente e view de apresentação, então sempre pareceu errado colocar regra de negócios nelas.

Sobrando apenas o MODEL

Y

fabioFx:
Recomendo fortemente tu dar uma estudada sobre DDD (domain driven design) de Eric Evans. Se possível compre o livro pois é muito bom.

Em termos de arquitetura de camadas essa “filosofia” define 4 camadas:

  • UI (interface com usuário)
  • Aplicação (controladores, frameworks, etc…)
  • Domínio (negócio/regras, entidades)
  • Infraestrutura (consumo de serviços de outros sistemas: banco de dados, email, webservices)

o enfoque está na camada de domínio, a qual representa os conceitos do problema, e deve ter o mínimo possível de dependência com outras tecnologias (frameworks, etc) pois no mundo real não existe tecnologia (enviar um email tem o conceito “enviar email” e não “m = new SimpleEmail(); m.set… m.send();”). No livro é descrito várias técnicas para isolamento do negócio, conceitos como VO, Repository, Services, Módulos, Fábricas, Agregadores… (Alguns do GoF com roupa nova :slight_smile: )

Em comparação com o MVC eu vejo o DDD como uma evolução, em termos de conceito. Alguns podem falar que é igual ao MVC com a camada de infra.
Mas se estudar sobre, vai ver que é muito mais profundo, claro, específico e aplicável.

Quanto ao DAO, com uso de ORM (JPA, hibernate, etc…), dependendo da complexidade da aplicação eu vejo desnecessário, mas se for usar, use o conceito de Repository e coloque as implementações na camada de infra, pois o padrão DAO foi criado pra resolver problemas de suporte a multiplos bancos de dados na época que usavamos JDBC.

A vantagem que você verá de imediato é a facilidade de testar sua aplicação, manutenter e evoluir, e irá pensar primeiro no domínio do negócio e depois na solução técnica.

Não confunda MVC com camadas, essa eh uma confusao comum. Mas elas nem passam perto de ser a mesma coisa. Por isso o DDD não é uma evolução do MVC, na verdade ele nada tem a ver com MVC, nem o conceito das camadas logicas (interface, negocios, acesso a dados) ou como na definicao do Evans (interface, aplicacao, negocios, infra) não tem nada a ver com o Model-View-Controller.

Model-View-Controller é um pattern criado para separar a interface com o usuario do resto da aplicacao. View é a interface, Controller uma fina camada separadora e Model é todo o resto incluindo as 387 possíveis camadas mais banco de dados sistema de arquivo, acesso a web service e afins.

R

Rodrigo Sasaki:
Pra mim o Model era a parte que lidava só com dados, sem regra nenhuma de negócio aplicada (Entidades e DAOs, basicamente).

Também conhecido como modelo anêmico :smiley:

B

Model -> É composta pelas classes Action, Service e DAO. Cada entidade deve possuir esse trio.
As classes Actions são responsáveis pelo recebimento dos parametros originados na view e pela obtensão da conexao… e as envia à classe Service
As classes Services são as que guardam todas as regras de negócios. Solicitam às classes DAO as listas de dados ou inclusões. exclusões e updates…
As classes DAO fazem somente a parte de persistência, gerando listas de dados ou fazendo inclusões e atualizações…

  • Uma classe Action conversa somente com a classe Service que conversa somente com a classe DAO
    Action <–> Service <–> DAO

obs: Esse formato facilita bastante o uso de transactions, uma vez que a conexão criada na action é enviada por referência a todos os métodos que farão parte da regra de negócios.

View -> É a camada de interface ao usuário
Controller -> Controla as requisições fazendo a comunicação entre a View e a classe Action

A

Estava lendo um artigo sobre o assunto: http://imasters.com.br/gerencia-de-ti/tendencias/a-evolucao-do-mvc-para-rest

Durante a leitura, pensei comigo: “O cara misturou os conceitos, vai ser massacrado nos comentários”

Para minha surpresa (e tristeza?), a maioria adorou o artigo.

Os únicos que apontaram os erros foram taxados de haters e trolls.

Infelizmente, as vezes funciona mais ser simpático do que ter razão.

Criado 20 de junho de 2012
Ultima resposta 31 de out. de 2012
Respostas 33
Participantes 14