DAO's nas classes de negócio

127 respostas
S

galera, como vc fazem quando têm em um objeto de negócio a necessidade de carregar algo do banco? vc’s chamam seus DAO’s dentro dos métodos de negócio?

Ex: tenho uma classe Setor, que tem um método listarUsuários(), sendo que a lista de usuários deste setor está armazenada no banco
como vcs fariam?

public List<Usuario> listarUsuarios() {
     setorDAO.listar();
}

esta é uma abordagem correta? se não, que alternativa vcs usam?

127 Respostas

F

seu método de negócio nao faz nada a nao ser recuperar a lista?

entao talvez nem na camada de negócio ele precise estar…

R

SadNess:
galera, como vc fazem quando têm em um objeto de negócio a necessidade de carregar algo do banco? vc’s chamam seus DAO’s dentro dos métodos de negócio?

Ex: tenho uma classe Setor, que tem um método listarUsuários(), sendo que a lista de usuários deste setor está armazenada no banco
como vcs fariam?

public List<Usuario> listarUsuarios() { setorDAO.listar(); }


Em algum ponto você vai ter que chamar o DAO numa classe de negócio, não é? :wink: Acho que o seu problema é “quando”.

A forma que você colocou pode ser interessante, principalmente se você tiver que executar alguma outra regra de negócio antes de obter os dados do banco, como verificar a permissão de um usuário para ver a lista de todos os usuários cadastrados.

M

essa discussão vai longe…

você tem duas formas de fazer isso.

1ª: exatamente como o RafaelRio disse. Seu objeto de negócio vai precisar conhecer o dao para fazer a consulta.
Parece mais OO.

2ª: a forma mais usada. Você criará uma camada de classes controles e elas serão as responsáveis de fazer este tipo de transação.

S

Não entendi a 2a. opção.

O seu modelo vai ter que chamar o DAO direta ou indiretamente.

Como o DAO por si só já é uma abstração para a camada de persistencia, não vejo problema algum em o seu modelo chamar o DAO. Veja que como eu acabei de falar o DAO deve ser uma interface independente de qualquer coisa relacionada ao mecanismo de persistencia, ou seja, vc tem userDAO e MySQLUserDAO, HibernateUserDAO, FileUserDAO, LDAPUserDAO, OracleUserDAO, e por aí vai… Pode ter também um JdbcUserDAO, que ficaria abaixo de MySQLUserDAO e OracleUserDAO.

Criar mais uma abstração em cima do DAO para acessar a camada de persistencia me parece um grande overkill, mas posso estar enganado…

O que seria bastante equisito é acessar o DAO diretamente da sua action!

S

valeu galera
eu tava com um pé atrás de colocar os DAOs nos objetos de negócio, mas agora estou percebendo que é uma abordagem correta

vlw pela ajuda

Y

Eu uso a segunda forma citada pelo Marcelo.

Quais sao os problemas q eu posso vir a ter com ela.

T

Essa segunda também não entendi!!! Alguém poderia esclarecer ???

S

YvGa:
Eu uso a segunda forma citada pelo Marcelo.

Quais sao os problemas q eu posso vir a ter com ela.

Antes de saber se é bom, ruim, legal, recomendável ou não-recomendável, a gente precisa entender o que é a opção 2.

M

Desculpa pela péssima explicação. Deixa eu tentar explicar melhor a idéia…

A grande maioria dos sistemas que eu conheço trabalha da seguinte forma:

Um objeto que recebe a requisição (action, servlet, etc…).
Esse objeto apenas transforma os dados em um objeto de negócio (Bean) e deixa a tarefa de executar as regras para outra classe, a control. A action apenas conversa com a control.

A control dentre outros papéis (validação, regras de negóciom etc…) será a única que irá conversar com os daos.

Essa é a camada a mais que eu citei… espero ter ficado mais claro agora.

Veja que eu disse que é a maneira mais usada, mas não é tão OO.

Y

Nao sei se eh o mesmo caso q o Marcelo colocou, mas eu faco da seguinte maneira:

A partir da UI o usuario pressiona o botao salvar, q envia a mensagem para um controller (controle.save()). Esse controle tem com um de seus atributos um objeto do dominio, Cliente por exemplo.

É dentro desse metodo save() q ele instancia a classe DAO e passa o objeto do dominio como parametro para ser persistido. O meu objeto Cliente nao conhece nada a respeito de persistencia em tempo algum.

Y

Nesse ponto a minha eh diferente, todas as regras de negocio continuam na classe de dominio, os controles sao responsaveis apenas por direcionar as mensagens recebidas da UI e fazer a ligacao com a camada de persistencia.

A base q eu usei foi a classe q o Craig Larman chama de Registro no “Utilizando UML e Padroes”.

J

Eu acho qeu a opção 2, ele quiz dizer algo como um Command (ao invés de Controller).

Utilizando-se de Command, você não precisa conhecer o DAO, mas sim, este Command o conhecerá, abstraindo assim o acesso ao DAO, mesmo que ele use mais de um DAO para fazer tal “transação”.

Y

jujo:
Eu acho qeu a opção 2, ele quiz dizer algo como um Command (ao invés de Controller).

Utilizando-se de Command, você não precisa conhecer o DAO, mas sim, este Command o conhecerá, abstraindo assim o acesso ao DAO, mesmo que ele use mais de um DAO para fazer tal “transação”.

Na verdade nao. Eu utilizo os Commands tbm, mas apenas para enviar os valores as classes de dominio, desacoplando da UI.

Os meus controllers sao mais ou menos assim:

public class Controller{

private IModel cliente;

private ISaver saver; //strategy para chamadas das classes DAO

public void salvar(){
this.saver.salvar(this.cliente); //o objeto saver instancia o DAO

}

//demais metodos relacionados a persistencia

public void setValor(ICommand c)

{

//aqui ele recebe da UI um command, passa pra ele o IModel

//nesse caso o this.cliente, o command q e o responsavel por

//setar o valor do atributo

}

}
S

marcelo_mococa:
Desculpa pela péssima explicação. Deixa eu tentar explicar melhor a idéia…

A grande maioria dos sistemas que eu conheço trabalha da seguinte forma:

Um objeto que recebe a requisição (action, servlet, etc…).
Esse objeto apenas transforma os dados em um objeto de negócio (Bean) e deixa a tarefa de executar as regras para outra classe, a control. A action apenas conversa com a control.

A control dentre outros papéis (validação, regras de negóciom etc…) será a única que irá conversar com os daos.

Essa é a camada a mais que eu citei… espero ter ficado mais claro agora.

Veja que eu disse que é a maneira mais usada, mas não é tão OO.

o que eu não entendi aqui é:
o objeto de negócios não possui nenhuma regra de negócios então?
toda a regra de negócio está em uma classe de controle?

S

Acho que quando ele disse control, ele quiz dizer modelo de negócios.

Acredito que o certo é:

Requisição Web -&gt Action -&gt Modelo de Negócios -&gt DAO -&gt Implementação de DAO

Não vejo como ser diferente disso.

O que algumas pessoas fazem, o que não é recomendável, é:

Requisição Web -&gt Action -&gt DAO -&gt Implementação de DAO

E tem aqueles que vão fazer assim tb:

Requisição Web -&gt Action -&gt Banco de Dados

F

Com o JPA, qual seria a desvantagem de fazer o CRUD por exemplo numa camada de negocio?

S

Boa pergunta.

Respondo com outra.

E se amanhã vc precisar fazer uma query mais complexa, que exiga por exemplo pegar a connection e fazer um SQL mais sinistro? Vc vai fazer essa query dentro do seu modelo de negócios?

Já tive essa mesma dúvida no passado. A session do Hibernate/JPA pode ser considerada uma espécie de DAO, mas na verdade ela não é isso.

Melhor separar claramente a abstração do seu mecanismo de persistencia num DAO e não atrelar a sua opção de JPA, Hibernate, MentaBean ao seu modelo de negócios…

M

SadNess:

o que eu não entendi aqui é:
o objeto de negócios não possui nenhuma regra de negócios então?
toda a regra de negócio está em uma classe de controle?

exatamente…

F

Concordo que para query complexas ficaria bem confuso(e dificil de fazer) isso no seu modelo de dominio (parece que com Ibatis vc ate consegue fazer umas querys mais complexas, mas nao conheco pra falar, talvez alguem que conheca poderia opiniar), mas se for pensar num modelo bem simples onde apenas há um CRUD, valeria a pena ter no sua classe (Cliente por exemplo) os metodos insert, delete, update, select apenas delegando para uma classe DAO?
Modelos complexo acho que é interessante separar as camadas, mas modelos simples creio que nao, o que acha?

P

Objetos de negócio que sabem o que significam DAOs quebram o princípio da inversão de dependências. DAO é algo concreto, ligado com a infra estrutura e não deve ser relacionado diretametne por um objetod e negócio.

Neste caso, use o padrão Repository. Note que um Repository pdoe ser apenas uma interface implementada por um DAO mas o importante é que um Repository é um conceito de negócios, um DAO não, por isso não liguem seus objetos de negócio aos DAOs.

S

DAO é uma coisa abstrata, não concreta. É uma interface que não é atrelada a nenhuma infra-estrutura.

Se eu tenho uma interface userDAO, ela pode ter qualquer tipo de implementação, inclusive TestUserDAO, DummyUserDAO, etc.

Se vc fala para o modelo de negócios não acessar o DAO, então ele acessaria o que? Acessar esse repositório, só estaríamos passando o problema do DAO para o repositório, não?

Ex do seu modelo de negócios:

private UserDAO userDAO;

public boolean edit(User u) {

    return userDAO.update(u) == 1;

}

Se o meu modelo de negócios não acessar o DAO acima ele vai acessar o que? Me interessei pelo que vc falou, mas estou com medo estarmos criando uma camada extra a troco de nada, o que seria um anti-pattern…

Um DAO não poderia ser considerado como um repositório de objetos e operações relacionadas a camada de persistencia? Vale a pena abstrair o DAO em mais uma camada chamada repositório?

De repente vale, não sei… O repositório é que se encarregaria de saber qual DAO usar e o Modelo usaria sempre o mesmo repositório… Não sei, ainda acho que uma interface userDAO tem exatamente essa função, ou seja, o modelo de negócios utiliza uma interface e essa interface que vai se virar para saber que implementação ela vai usar…

R

Eu acho q o saoj esta correto, imagina o tanto de classe que precisaria ser
criada pra fazer um simples crud…
poxa, jah temos uma interface UserDao, que abstrai o dao, entao criar mais
uma camada acho desnecessario minha opinião é

web -> action > model -> interface dao -> dao concreto -> banco

oque entendi estao querendo abstrair do model para o interface

web -> action > model -> repositorio > interface dao -> dao concreto -> banco

não vi finalidade apenas…

R

É uma questão de conceito. Se você tem uma interface dao para cada entidade do sistema (UserDao, ClienteDao, NotaFiscaDao) que não deixa pistas que tem um banco de dados embaixo dela e seus daos só fazem insert, update, delete e buscas (buscas previstas pela regra de negócio), vc na prática está trabalhando com repositórios. O que não é legal é passar a sessão do hibernate ou um dao genérico pro objeto de negócio.

Se você vai dar o nome de UserDao, UserStore ou UserRepository pra interface é só um detalhe.

[]'s

Rodrigo Auler

R

Exatamente, é ai que entra IoC (Inversion Of Control) para
injetar dentro do modelo o Dao.

ai sim o IoC funciona como um repositorio ± , porque ele que vai dizer qual
implementação de DAO que vc vai utilizar.

C

Antes que essa thread fique parecendo uma cacofonia em hospicio:

DAO: implementacao concreta do Repository. Nao deve ser usada por classes do dominio.

Repository: definicao da interace com o repositorio de dados (nao necessariamente uma interface, mas no maximo uma classe abstrata). Pode ser usada por classes do dominio, preferencialmente via injecao de dependencias.

Espero que fique mais facil se comunicar :slight_smile:

R

cv , agora não entendi mais nada, não consigo enchergar
isso na prática, e a verdadeira finalidade.

R
public interface ClientRepository {

   public ClientVO getClient(long id);

}
public class ClientDAO implements ClientRepository {

   ...

   public ClientVO getClient(long id) { ... }

}
public class ClientBOImpl implements ClientBO {

  public boolean aMethod() {
   ...
   this.clientRepository.getClient(id);
   ...
  }
}

A distribuição de classes seria mais ou menos isso ?

C

Sim, so que sem essa putaria de ClientBO, ClientVO e ClientBOImpl.

Leia: http://en.wikipedia.org/wiki/Test-driven_development

P

saoj:
DAO é uma coisa abstrata, não concreta. É uma interface que não é atrelada a nenhuma infra-estrutura.

Não, Sérgio. DAO é algo que mapeia uma coisa apra outra, é um DataMapper. Ao pedir seus objetos para um DataMapper você está automaticamente sabendo que seus objetos na verdade estão em outro lugar.

Seja este lugar Oracle, hibernate, MySQL, XML ou Lucene isso é algo que não tem a ver com sua Camada de negócios. A Camada de Negócios modela negócios, ponto final, e existem poucos ramos onde o cliente lida com coisas como persistência.

Não, Repositório é um conceito de negócios, é basicamente uma lsita com métodos mais interessantes.

Você não está criando Camada alguma, você já criou (e está no título deste tópico): a camada de negócios. Repositório==negócios, DAO=persistência.

DAO abstrai apenas a lógica de persistência, não o fato de haver uma persistência, que deve ser abstraído da classe de negócios.

cv:
Sim, so que sem essa putaria de ClientBO, ClientVO e ClientBOImpl.

Leia: http://en.wikipedia.org/wiki/Test-driven_development

E

http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs

Não use VO/BO, use objetos

S

Ok, entendi.

Tenho o seguinte DAO que é acessado pelo modelo de negócios:

package org.mybooks.dao;

import java.util.*;

import org.mybooks.bean.*;

public interface UserDAO {
    
    public User loadById(int id) throws Exception;
    public int insert(User user) throws Exception;
    public void update(User user) throws Exception;
    public void delete(User user) throws Exception;
    public User loadByUsername(String username) throws Exception;
    public User loadByEmail(String email) throws Exception;
    public List searchUsersByName(List keywords, boolean and) throws Exception;
    public List searchUsersByName(List keywords, boolean and, int max) throws Exception;
}

Reparem algumas coisas:

:arrow: Ele é uma interface

:arrow: Ele não possui qualquer acoplamento a java.sql.Connection. org.hibernate.session, java.io.File, etc.

:arrow: Posso ter N implementações desse DAO, tais como, JdbcUserDAO, MySQLUserDAO (que extends JdbcUserDAO), HibernateUserDAO, LDAPUserDAO, TestUserDAO, DummyUserDAO, etc.

Algumas perguntas:

  1. Posso considerar essa interface como respositório?

  2. Como ficaria um repositorio então nesse meu caso?

Obrigado e acredito que todos estão tirando proveito desse tópico!

S

pqp
essas 3 páginas de tópico valem + a pena do que muito livro por aí :slight_smile:

T

Acredito que sim… O DAO implementa esse repository, e é utilizado algo para injetar a implementação.

R

É isso aí, saoj!

Daí, a implementação do repository pode ser obtida através de [i]dependency injection /i, service locator ou factories.

Ou seja, obtida por meio de padrões cuja finalidade é desacoplar ao máximo uma classe dependente (cliente) de uma implementação específica.

S

Eu chamei minha interface the UserDAO.

Por isso que eu falei que o modelo de negócios deve acessar o DAO. Na verdade ele vai acessar a INTERFACE UserDAO.

Resta saber se ao invés de chamar essa interface the UserDAO deveríamos chamar ela de UserRepository, ou ainda se isso deveria ser feito de outra maneira…

R

Eu também chamaria a interface de UserDAO e a implementação, de UserDAOBean, por causa das convenções de nomes da especificação EJB.

F

saoj:
public interface UserDAO { public User loadById(int id) throws Exception; public int insert(User user) throws Exception; public void update(User user) throws Exception; public void delete(User user) throws Exception; public User loadByUsername(String username) throws Exception; public User loadByEmail(String email) throws Exception; public List searchUsersByName(List keywords, boolean and) throws Exception; public List searchUsersByName(List keywords, boolean and, int max) throws Exception; }

  1. Posso considerar essa interface como respositório?

  2. Como ficaria um repositorio então nesse meu caso?


Sérgio, eu mudaria um pouco o nome dos métodos para tirar os rastros que de que há um banco (ou algo do tipo). Trocando load/search por get, acho que já ficaria melhor. Trocando insert/delete por add/remove tb melhoraria um pouco.

Fica mais com cara de coleção, entende? Mas isso é só firula.

Fora isso, usaria unchecked exceptions para todos esses métodos e aí sim renomearia para UserRepository.

P

Sim, Sérgio, pode chamar de Repositório. Mas tem 2 coisas importantes aí:

  1. Nomes são muito importantes. Design Patterns são úteis entre outras coisas por definirem um nome comum a alguma técnicas, por isso nomenclatura deve ser usada com muito cuidado.

  2. Um Repositório não é um DAO, um DAO pode ser um repositório. Vou coalr aqui uma resposta minha na lsita de DDD que pode esclarecer:

http://tech.groups.yahoo.com/group/domaindrivendesign/message/5425

R

onde acho documentação da sun falando sobre esses padrões de nomes ?

R

e no caso, isso aqui estaria errado ?? Lá ele utiliza a nomeclatura DAO na interface…

Tá parecendo aquele velho papo que no mundo java existem vários nomes para a mesma coisa…

L

Olá

Nada é imutável no campo da idéias. As coisa evoluem. Desde que os caras da Sun escreveram sobre design patterns, muitos outros autores escreveram também e muitas idéias se aprimoraram.

Siga o exemplo do Phillip, que estuda para caramba para se manter atualizado. Procure ler os livros que ele recomenda e entenderá melhor o porque das mudanças.

[]s
Luca

P

Não há, pelo menos não amplamente divulgada. Estes padrões foram catalogados por Martin Fowler e Eric Evans.

Não está errado porque o autor está falando sobre DAOs e não sobre Repositórios.

Rafaelprp:

Tá parecendo aquele velho papo que no mundo java existem vários nomes para a mesma coisa…

Releia meu último post.

B

Interessante a discussão :slight_smile:

R

Fabio Kung:
saoj:
public interface UserDAO { public User loadById(int id) throws Exception; public int insert(User user) throws Exception; public void update(User user) throws Exception; public void delete(User user) throws Exception; public User loadByUsername(String username) throws Exception; public User loadByEmail(String email) throws Exception; public List searchUsersByName(List keywords, boolean and) throws Exception; public List searchUsersByName(List keywords, boolean and, int max) throws Exception; }

  1. Posso considerar essa interface como respositório?

. . . e aí sim renomearia para UserRepository.

Se eu entendi bem o que foi dito aqui, inclusive nesse e nesse blog, por todos os motivos já citados, a interface UserDAO deve ser renomeada para UserRepository.

Então, o artigo Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? do blog da Caelum deve ser atualizado, certo? interface Dao<T, I> { T search(I id); // ? }
Pois essa interface DAO é utilizada na camada de negócio - pelo menos é o que subtende-se pelo artigo: Dao<Cliente> clienteDao = new GenericHibernateDao<Cliente>(session); clienteDao.persist(cliente); Cliente c5 = clienteDao.search(5);
Afinal, Client é um aggregate, e o repository deverá lidar com Client e suas classes colaboradoras, como Address, etc.

Esse outro artigo sugere o que o pcalcado disse acima:
Repository -&gt RepositoryImpl -&gt DAO -&gt DAOImpl

Ali, o autor diz que nos DAO’s devem haver - digamos assim - métodos de granulação fina, estritamente relacionados às operações com banco de dados: create, find / search, update, delete; nos repositórios, operações mais “interessantes”, relacionadas aos negócios", como procurarTodosClientesInadimplentes.

procurarTodosClientesInadimplentes para mim estaria num domain service e poderia gerar outra discussão: se deveria estar num repositório ou não. Mas creio que ficou claro o que quis dizer.

F

Rafael, você levantou algumas questões muito boas.

Se os objetos do domínio possuírem alguma referência, eu chamaria a interface de Repository, caso contrário chamaria de DAO.

Mas isso também é bem discutível.

K

Uma vez, batendo papo com o Vinícius Siegel (dono da global code) num evento , estávamos falando sobre pattern e ele falou uma coisa muito interessante : "Depois de 2 ou 3 cervejas, eles são praticamente iguais … :slight_smile: ".

Brincadeira à parte, costumo fazer o design dessa camada utilizando uma interface DAO e sua implementação de modo genérico.

Na camada Business, IoC desse com a "ajudinha" do Spring ou um esquema de anotações que voê pode montar tb …

PS: vou postar um artigo sobre isso no meu blog, que não atualizo a quase um ano :slight_smile:

R

Legal Phillip. Realmente usar o nome Repository e usar a nomenclatura de métodos sugerida pelo Fábio Kung fica menos na cara que ta usando um banco de dados por trás, fica mais bonito, etc.

Mas acho que o pessoal ta mais acostumado com o termo DAO e, no fim, DAO e Repository acaba tendo o mesmo efeito.

P

microfilo:

Mas acho que o pessoal ta mais acostumado com o termo DAO e, no fim, DAO e Repository acaba tendo o mesmo efeito.

Ou eu não tô sabendo explicar ou tem algo errado na comunicação…

Imagine a situação: o seu DAO recebe como parâmetro um HttpRequest. Tem o mesmo efeito que passar um objeto de negócios para ele, não?

P

RafaelRio:
por todos os motivos já citados, a interface UserDAO deve ser renomeada para UserRepository.

Então, o artigo Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? do blog da Caelum deve ser atualizado, certo?

Não necessariamente. (1)Ele não precisa estar falando de DDD e (2) ainda que você adote a estratégia simplificada de DAO&lt<implements>&gtRepository nada impede que o DAO tenha sua própria interface para promover alguma abstração.

P

É beeeeeem por aí. Um repository é como objetos de negocio enxergam ‘o lugar onde objetos sao guardados’. Se eles sao guardados num SGBD e mapeados com um DAO nao importa aos objetos de negocio.

F

Boa Phillip, foi exatamente o que eu quis dizer!

No artigo do Paulo lá no blog da Caelum, o DAO não está sendo usado dentro dos objetos do domínio, por isso continua sendo DAO.

A diferença é sutil:
Dao&lt;Usuario&gt; dao = new Dao&lt;Usuario&gt;();
List&lt;Usuario&gt; usuarios = dao.listAll();
public class Usuario {
  private ProdutoRepository repository;

  public Usuario(ProdutoRepository repository) {
    this.repository = repository;
  }

  public List&lt;Produto&gt; getProdutosCompradosDesde(Date dia) {
    return repository.getProdutos(this, dia);
  }
}
getProdutos passando 'this' ficou BEM feio, mas é só para ilustrar a idéia.
R

Entao depois de tanta teoria como ficaria uma estrutura web para acessar um
banco de dados por exemplo?

view -> action -> modelo de negocios -> UserRepository(Interface) -> UserDao(implementação) -> etc etc…

??

S

Se eu entendi direito:

req HTTP -&gt Action -&gt Modelo -&gt UserRepository -&gt Implementação concreta do repositário MySQLUserRepository -&gt Banco de dados.

Mas acho que eu entendi errado, pois acima só trocamos o nome DAO por Repository.

Então talvez seja algo assim:

req HTTP -&gt Action -&gt Modelo -&gt UserRepository -&gt Implementação concreta de UserRepository -&gt User DAO -&gt Implementação concreta de UserDAO -&gt Banco de dados.

Parece correto do ponto de vista teórico, mas com o side-effect prático de termos muitas classes e interfaces.

Minha dúvida agora já é outra. Acredito que devido a simplicidade do meu modelo de negócios ele acabou se comportando como um UserRepository apenas, ou seja, sua única função ficou sendo CRUD de beans.

Acho que esse conceito está difícil de assimilar porque em muitos casos o repositório vai apenas espelhar fielmente o DAO, logo ele parece uma camada a mais apenas com sentido teórico mas nao prático.

Por exemplo, se eu precisar pegar todos os usuários maiores de X anos, com a cueca da cor Y e cadastrados antes de 1990, terei que criar um novo método no repositorio e um outro igualzinho no DAO.

Haverá muita duplicação entre o DAO e o Repository… A dúvida que ficou e se isso tem que ser usado sempre ou não, depende do caso.

O outro extremo seria colocar tudo na action, ou seja, a action -&gt DAO -&gt banco…

F

Todas essas camadas (Repository -&gt RepositoryImpl -&gt DAO -&gt DAOImpl) são a maior abstração possível. Você não precisa (eu eu acho que nem deve) fazer isso sempre. Se for só para ter um monte de interfaces e classes ocas que só delegam tudo, eu não acho que valha a pena abstrair.

Já foi o tempo que achava melhor interfacear e abstrair tudo. Até discutia bastante sobre isso com o Michael Nascimento e com o Paulo Silveira (aqui e aqui).

Hoje em dia eu mudei minha opinião e procuro sempre manter as coisas o mais simples possível, mas isso não significa fazer errado (acabar com a OO, por exemplo). O Repository não precisa ser apenas um envelope para o dao. Nem interfacear o repositório é obrigatório e regra geral.

Se eu percebo a necessidade de abstrair, refatoro e pronto. Acho que não vale a pena complicar muito o modelo com 1332423 abstrações e interfaces de tudo sem nem ter certeza da real necessidade.

O conceito do Repository é esse que o Phillip apresentou (e o trecho de código que eu postei). Já como implementá-lo, no meu ponto de vista, vai depender de cada caso.

F

Vinícius Senger né?

(ou ele tem um sobrenome que ninguém conhece?)

R

saoj:
Então talvez seja algo assim:

req HTTP -&gt Action -&gt Modelo -&gt UserRepository -&gt Implementação concreta de UserRepository -&gt User DAO -&gt Implementação concreta de UserDAO -&gt Banco de dados.

Parece correto do ponto de vista teórico, mas com o side-effect prático de termos muitas classes e interfaces.

[. . .]

Acho que esse conceito está difícil de assimilar porque em muitos casos o repositório vai apenas espelhar fielmente o DAO, logo ele parece uma camada a mais apenas com sentido teórico mas nao prático.


Penso assim também.

saoj, pelo que andei pesquisando, esse é o tipo de operação sob responsabilidade de um repository, que internamente utilizaria um DAO para acessar os dados necessários e então fazer o processamento e devolver o resultado ao cliente.

Os DAO’s seriam escondidos e ficariam com o mais simples e puro CRUD; operações mais relacionadas com o negócio sobem para o repository.

Fabio Kung:
Todas essas camadas (Repository -&gt RepositoryImpl -&gt DAO -&gt DAOImpl) são a maior abstração possível. Você não precisa (eu eu acho que nem deve) fazer isso sempre. Se for só para ter um monte de interfaces e classes ocas que só delegam tudo, eu não acho que valha a pena abstrair.

Já foi o tempo que achava melhor interfacear e abstrair tudo. Até discutia bastante sobre isso com o Michael Nascimento e com o Paulo Silveira (aqui e aqui).


Assino em baixo. E vale a pena ver essa discussão.

Hoje em dia eu mudei minha opinião e procuro sempre manter as coisas o mais simples possível, mas isso não significa fazer errado (acabar com a OO, por exemplo). O Repository não precisa ser apenas um envelope para o dao. Nem interfacear o repositório é obrigatório e regra geral.

Se eu percebo a necessidade de abstrair, refatoro e pronto. Acho que não vale a pena complicar muito o modelo com 1332423 abstrações e interfaces de tudo sem nem ter certeza da real necessidade.


Mesmo porque, dizer o contrário é ir contra um dos princípios do XP, metodologia que parece ser seguida por vários profissionais no GUJ.

Eu achei o conceito de Repository interessante, mas não vi ganhos nem mesmo em grandes projetos. No meu caso, por exemplo, teria que fazer muito mais do que renomear algumas interfaces.

Se um dia eu achar útil… Bem, para isso que serve refactoring.

K

Vinícius Senger né?

(ou ele tem um sobrenome que ninguém conhece?)

Boa … eu realmente me confundi, não sei pq troquei o sobrenome do cara :slight_smile:

Obrigado :slight_smile:

F

Rafael, o ganho seria justamente deixar a coisa mais OO.
Em vez de:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = dao.carregaContasPagasDesde1999(fornecedor);
Você consegue fazer:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = fornecedor.getContasPagasDesde1999()
Se o fornecedor tiver uma referência para o RepositorioDeContas (ContasRepository).

R

Rafael, o ganho seria justamente deixar a coisa mais OO.
Kung, você sabe, para calcular ganhos é preciso conhecer vantagens e desvantagens - me corrigindo, a palavra mais correta seria “valor”, ao invés de “ganhos”.

A questão que eu coloquei é “essa camada a mais vale a pena”? Se o preço para mais uma camada superar os ganhos de tornar “a coisa mais OO”, a resposta é não. Taí uma discussão que vai (ou melhor, poderia ir) longe…

Ultimamente tenho pensado que vale a pena questionar novas teorias que andam ululando por aí, em pró da simplicidade, desde que com fundamentos, ao invés de simplesmente aceitá-las.

Esse repository, por exemplo, vocês podem argumentar que torna as coisas mais claras, elegantes, o genro que toda sogra gostaria de ter, mais OO, etc. Mas tô sentindo que a reação da maioria das pessoas será “isso é lindo na teoria, mas não na prática; deixa quieto, vou continuar com meus DAO’s”. Vão deixar (aproveitando esse exemplo) o Repository para uma “zelite” que irá se formar - “isso é só pros caras”.

E quando argumentos do tipo “torna a coisa mais OO”, “segundo Fowler”, etc, finalmente se desgastarem, essa elite ficará isolada numa torre de marfim - já aconteceu e acontece em diversas áreas. Vão dizer coisas lá de cima na torre, as pessoas vão escutar, ficar encantadas, vai entrar por um ouvido e sair pelo outro.

Isso vai formar um vazio, que será preenchido por palpiteiros inconseqüentes, que pregarão contra a OO, design patterns e o inglês e arrebatarão coraçãozinhos por adotarem uma aura de pragmáticos (levanta a mão quem não sabe do que estou falando).

Não me entendam mal, não estou soando as trombetas do apocalipse e sou fã da fundamentação e da boa literatura. Mas tudo tem limites, cada caso é um caso, teoria ainda é uma teoria, devem ser testadas na prática, por aí vai. (Uauu!! Isso é que bom uso de clichês…)

Aceitam uma sugestão? Em casos assim, penso que o ideal seria escrever artigos técnicos com o contexto e os pormenores, como a série sobre exceções do Luca e o artigo sobre DTO do shoes. Um já é referência no tema, o outro, aposto, vai virar.

A partir daí, as pessoas pensam e decidem com suas cabeças qual o melhor caminho.

Abraços!

S

Rafael, o ganho seria justamente deixar a coisa mais OO.
Em vez de:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = dao.carregaContasPagasDesde1999(fornecedor);
Você consegue fazer:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = fornecedor.getContasPagasDesde1999()
Se o fornecedor tiver uma referência para o RepositorioDeContas (ContasRepository).

É realmente, o segundo é bem melhor que o primeiro, e temo que eu esteja inclinado a fazer o primeiro. Mas isso não tem haver com a questão do repository x DAO. Seja com DAO dentro de forncedores ou com repository dentro de forncedores talvez a coisa deva ser sempre feita assim mesmo como o Fábio falou… É para pensar e brincar…

P

Eu adoro quando as pessoas falam “depois desta teoria toda”. É impressionante como alguém consegue ver toda esta diferença entre teoria e prática em OO, por isso que temos tanto software mal-construído.

Dado que Model = Camada de Aplicação+Camada de Negócios+Camada de Persistência o Repository está dentro da Camada de Negócios enquanto o DAO está dentro da Camada de Persistência.

Acho que você entendeu errado o Model no MVC, por isso esta confusão. Model em MVC é: -&gt UserRepository -&gt Implementação concreta do repositório MySQLUserRepository -&gt Banco de dados. Tudo isso.

Releia sobre MVC, faça seu DAO implementar um Repositorio e pronto, na prática você vai ter o mesmo número de .java.

Novamente: ele não é uma Camada a mais, ele integra duas Camadas. A dificuldade em ver a aplicação pdoe estar ligada com a falta de uma divisão reald e Camadas, já que MVC em si não tem nada a ver com Camadas.

Não.

Primeiro como já falamos aqui milhões de vezes você não precisa ter uma implementação de Repository que nãos eja um DAO se você não precisar ela (por favor, leia o email que colei antes de responder a este post).

Segundo, você não precisaria ter um método para este tipo de coisa, aliás se você tiver muitos métodos assim é sinal que seu design é bem ruim. Você resolve isso com outra dupla: Specification/QueryObject.

É óbvio que tudo, incluindo padrões DDD, só valem a pena quando valem a pena. É não-tão-óbvio que vale a pena na maioria das vezes, as pessoas usam argumentos fúteis apra não usar e acabam criando sistemas…interessantes do pontod e vista homem/hora apra manutenção.

O Repository não rpecisa sequer ser uma interface. leiam o livro do Eric Evans para entender do que se trata (ou o artigo na MundoJava #17).

P

mais uma vez: não é uma nova Camada, é a integração entre duas Camdas que já existem feita de uma maneira disciplinada. Simples assim.

Eu sicneramnete acho que se alguém está lendo uma thread desta ele quer melhorar seus conhecimentos. Pode ser que consiga, pdoe ser que não, mas tomar a atitude sugeria não vai melhorar o nível do emrcado como um todo. Eu já escrevi algumas vezes que acredito num grande cisma tecnológico que irá acotnecer em breve. Através de tecnologias como DSLs os pseudo-profissionais que acham que Repository é “pros caras” vão sair do mercado de tecnologia para se especializar na confecção de aplicações de forma muito simplificada, através de ferramentas de MDD provavelmente.

Enqauntoe ste dia não chega todo mundo aqui é negenheiro e não saber que é Martin Fowler é como um físico que não sabe quem foi Einsten ou Newton (guardadas as devidas proporções de genialidade, claro) e não sabe usar ot rabalho destes mestres no seu dia-a-dia. Ou um engenheiro civil que não sabe edificar um prédio sem usar uns 2 ou 3 modelos pré-concebidos, ele não entende por que faz aquilo e não conseguem mduar nem adaptar os modelos.

Há três anos atrás IoC era coisa “dos caras”. Hoje qualquer framework mais ou menos e boa parte de Java EE 5 usa IoC.

Testadas? Ok, vamos lá, o que você quer como teste exatamente? São conceitos existentes há uma década que já foram implementados e detalhados zilhões de vezes, o que falta neste sentido?

RafaelRio:

Aceitam uma sugestão? Em casos assim, penso que o ideal seria escrever artigos técnicos com o contexto e os pormenores, como a série sobre exceções do Luca e o artigo sobre DTO do shoes. Um já é referência no tema, o outro, aposto, vai virar.

A partir daí, as pessoas pensam e decidem com suas cabeças qual o melhor caminho.
Abraços!

Não entendi, e o que fizemos nesta thread se não apontar para recursos em artigos e livros e discutí-los?

F

Acho que estamos começando a ficar repetitivos demais nesse tópico Phillip! :smiley:

Rafael, muito legal o que você escreveu. Tem o seu valor, mas não concordo com a maioria dos argumentos, achei muito conformista: “não se mexe em time que está ganhando”.

Será que está ganhando mesmo?

S

Acho que o que o Fábio falou sobre OO matou a pau.

Daí se o seu modelo utilizar internamente repositório ou dao ou ambos é problema dele, devendo ser avaliado caso a caso…

R

Não sei se você sabe, mas as teorias de Newton e Einsten são questionadas a toda hora. Aliás, o próprio Einstein quebrou as perninhas do Newton quando a teoria da relatividade foi aceita. O interessante é que mesmo assim as duas podem ser utilizadas, uma melhor que a outra de acordo com o contexto.

Só quis dizer que não é porque uma teoria vem de um lugar que ela simplesmente deve ser aceita, senão estamos aceitando argumentos de autoridade - uma falácia. O que sugeri foi mais demonstrações, além de citações.

Você não entendeu o que eu quis dizer. Se ler com atenção, vai perceber que gostaria que argumentos desse tipo não fossem utilizados, não estou colaborando com eles. Ou seja, não é pra ficar só “com os caras”. Nem é pra existir “os caras” isolados numa Torre de Marfim.

[editado]Você que gosta de conceitos, procure descobrir o que quer dizer Torre de Marfim. Isso vai te ajudar a entender o que escrevi e a minha preocupação.[/editado]

Eu mesmo apontei pra alguns. Que tal mais deles? Você também não prestou atenção num deles, que diz que Repository deve ter uma implementação própria e não apenas ser implementado por um DAO.

Se você ficar bravinho, eu não brinco mais! :twisted: Quero mais acessos a esses testes, eu mesmo quero testar.

[editado]Aqui você me redimiu. Enquanto abusei dos clichês, você fez bom uso de hipérboles" :lol: [/editado]

Fabio Kung:
Rafael, muito legal o que você escreveu. Tem o seu valor, mas não concordo com a maioria dos argumentos, achei muito conformista: “não se mexe em time que está ganhando”.

Será que está ganhando mesmo?


Fábio, a que vc está se referindo? Quem disse “não se mexe em time que está ganhando”?

Na verdade, eu não tomei uma posição contra Repository; nem a favor. Vou parar por aqui, porque vai ficar cíclico mesmo. Pra entender melhor como penso, é só voltar um pouquinho e reler o que escrevi.

L

Olá

Esta discussão está muito boa mas vou dar meu pitaco meio em cima do muro.

Primeiro uma coisa óbvia: Arquitetura do sistema vale mais em termos de negócio do que sob o ponto de vista estritamente OO. Não adianta apenas caprichar no OO.

Quem usa DTO, aprendeu assim e faz bons sistemas usando DTO, que continue assim. Não acredito que vá perder os prazos por escrever umas classezinhas a mais

Quem ainda está aprendendo, procure por alternativas que só usam DTO em casos muitos especiais que é justamente como o Phillip recomenda. Na maioria dos sistemas DTO não é necessário.

É como EBJs antes do 3.0 que também só eram úteis em pouquíssimos casos (*).

Quanto ao DAO ser interface ou não, há muitos autores que fazem assim. Quem quiser fazer, que o faça. Só procure ser coerente com sua equipe.

A verdade é que eu ainda não consegui uma receita de bolo que sirva para todos os sistemas. Neste ponto estou com o Rafael: se alguém tem a receita então vamos publicar.

(*) Na minha opinião, EJBs anteriores ao 3.0 foram a maior besteira já inventada na área de TI. Me desculpe o amigo Kenobi, mas tenho até pena das empresas que ficarão com este legado (bem usado ou não como na maioria dos casos).

[]s
Luca

R

pcalcado:
[
Ou eu não tô sabendo explicar ou tem algo errado na comunicação…

Imagine a situação: o seu DAO recebe como parâmetro um HttpRequest. Tem o mesmo efeito que passar um objeto de negócios para ele, não?

???

Não consigo imaginar essa situação. Enfim, volto a dizer que, no final, o efeito de usar uma interface chamada DAO ou repository é o mesmo.

K

Luca:
Olá

Esta discussão está muito boa mas vou dar meu pitaco meio em cima do muro.

Primeiro uma coisa óbvia: Arquitetura do sistema vale mais em termos de negócio do que sob o ponto de vista estritamente OO. Não adianta apenas caprichar no OO.

Quem usa DTO, aprendeu assim e faz bons sistemas usando DTO, que continue assim. Não acredito que vá perder os prazos por escrever umas classezinhas a mais

Quem ainda está aprendendo, procure por alternativas que só usam DTO em casos muitos especiais que é justamente como o Phillip recomenda. Na maioria dos sistemas DTO não é necessário.

É como EBJs antes do 3.0 que também só eram úteis em pouquíssimos casos (*).

Quanto ao DAO ser interface ou não, há muitos autores que fazem assim. Quem quiser fazer, que o faça. Só procure ser coerente com sua equipe.

A verdade é que eu ainda não consegui uma receita de bolo que sirva para todos os sistemas. Neste ponto estou com o Rafael: se alguém tem a receita então vamos publicar.

(*) Na minha opinião, EJBs anteriores ao 3.0 foram a maior besteira já inventada na área de TI. Me desculpe o amigo Kenobi, mas tenho até pena das empresas que ficarão com este legado (bem usado ou não como na maioria dos casos).

[]s
Luca

Luca, só falando um pouquinho de EJB e suas necessidades, você lembra como era implementar tais requisitos com Corba ?

Já vi projetos para ramos de telefonia levarem anos para serem implementados em Corba e fracassarem a mesma equipe tentando com a infra EJB e em 4 meses entregando ao cliente funcionando.

A verdade é que se você tem necessidades densas, implementar Servant em C ou C++ é muito mais complicado do que se imagina e nem sempre temos tais profissionais disponíveis no mercado.

A especificação anterior à 3.0 possui falhas sim, como ORM - EntityBeans, mas possui muitas coisas legais também como MDBs, SessionBeans, controlole de transações, IIOP - implementar isso na mão é um parto.

Acho que muitos crucificam EJBs pois a espcecificação é bem abrangente e árdua para alguns profissionais,mas ainda sim, mais simples do que fazer tudo na mão.

Lembrando que antigamente não existiam frameworks para controlar transações como o Spring, que veio anos mais tarde, nem soluções como TerraCotta , que na minha opinião ainda precisa ser justificada pelo ROI.

Hoje implementar um sistema tolerante à falhas com a especificação é relativamente simples e com grandes opções sem custos de aquisição de software - GlassFish por exemplo, desde a versão 7.1 do App da Sun, foi incorporado uma tecnologia de cluster da Clustra, empresa que fazia grandes sistemas de cluster para empresas de Telecom.

paper para quem se interessar : http://www.vldb.org/conf/1995/P469.PDF

Acho que além da especificação, vale à pena os profissionais conhecerem também os produtos que a implementam, pois há muitas particularidades, como controle de Sessão, que até um tempo atrás o Websphere fazia por intermédio do DB2 ou pelo servidor, mas com 2GB de informações o mesmo caia e com o SunApp, você podia usar a estratégia de cluster do HADB - High Available Data Base e não onerar a performance com acessos a um DB externo por exemplo.

Finalizando, eu não tenho dó de empresas que usam a especificação EJB e a possuem de legado e sim daquelas que a utilizaram de maneira errônea, possuem um legado mal projetado por profissionais não capazes , conhecedores superficiais da especificação, ambientes e produtos.

L

Olá

Kenobi, eu não disse que não era necessário desenvolver uma solução para os problemas que o EJB &lt 3.0 tentou resolver. E lembre-se que o RMI usado pelos EJBs é mais simples do que CORBA porque é papo de Java com Java.

Eu disse e repito que a solução proposta pelo EJB &lt 3.0 é horrível e foi uma péssima idéia. Acredito que a própria Sun pense assim hoje porque mudou quase tudo nos EJBs a partir da versão 3.0.

O problema existia, o ruim foi ter sido resolvido por gente incompetente. Já vi este filme em muitas empresas, ou seja, ter que refazer tudo porque o sistema era uma droga.

Por este motivo tenho pena dos infelizes que darão suporte ao enorme legado de EJBs &lt 3.0. E ainda com 2 agravantes:

  1. EJBs do tempo em que tudo era remoto
  2. EJBs que foram usados indevidamente, às vezes, só para o desenvolvedor aprender a tecnologia.

Sem falar nos infelizes que usam caros servidores de aplicação obsoletos massageados por consultoras e que agora estão com sistemas engessados. Tem pelo menos um grande banco nesta situação.

[]s
Luca

L

Olá

Galera, desculpa a fuga do assunto do tópico.

Kenobi:

Hoje implementar um sistema tolerante à falhas com a especificação é relativamente simples e com grandes opções sem custos de aquisição de software - GlassFish por exemplo, desde a versão 7.1 do App da Sun, foi incorporado uma tecnologia de cluster da Clustra, empresa que fazia grandes sistemas de cluster para empresas de Telecom.

paper para quem se interessar : http://www.vldb.org/conf/1995/P469.PDF

Acho que além da especificação, vale à pena os profissionais conhecerem também os produtos que a implementam, pois há muitas particularidades, como controle de Sessão, que até um tempo atrás o Websphere fazia por intermédio do DB2 ou pelo servidor, mas com 2GB de informações o mesmo caia e com o SunApp, você podia usar a estratégia de cluster do HADB - High Available Data Base e não onerar a performance com acessos a um DB externo por exemplo.

Cuidado, não bem assim. O HADB é o novo nome do Clustra. Segundo o pessoal técnico do glassfish, se você não precisa de alta disponibilidade com 5 noves, o HADB é overkill. Veja:

http://blogs.sun.com/theaquarium/entry/in-memory_replication_in_glassfish_v2

eduardo pelegri-llopart:

Clustra is a very sophisticated tool. It is a good solution if you need the 5 9’s availability it delivers, but it is an overkill otherwise. We truly believe that most customers will be much better off with the in-memory replication.

[]s
Luca

F

Rubem, em boa parte dos casos vai ser realmente só uma questão de nomenclatura. Mas como o Phillip já disse, nomenclatura é bastante importante.

Se as classes de domínio tem referência, é uma boa chamar de Repository. Caso contrário pode chamar de Dao. Mas claro, isso não é verdade absoluta (não existe verdade absoluta).

K

Luca:
Olá

Galera, desculpa a fuga do assunto do tópico.

Kenobi:

Hoje implementar um sistema tolerante à falhas com a especificação é relativamente simples e com grandes opções sem custos de aquisição de software - GlassFish por exemplo, desde a versão 7.1 do App da Sun, foi incorporado uma tecnologia de cluster da Clustra, empresa que fazia grandes sistemas de cluster para empresas de Telecom.

paper para quem se interessar : http://www.vldb.org/conf/1995/P469.PDF

Acho que além da especificação, vale à pena os profissionais conhecerem também os produtos que a implementam, pois há muitas particularidades, como controle de Sessão, que até um tempo atrás o Websphere fazia por intermédio do DB2 ou pelo servidor, mas com 2GB de informações o mesmo caia e com o SunApp, você podia usar a estratégia de cluster do HADB - High Available Data Base e não onerar a performance com acessos a um DB externo por exemplo.

Cuidado, não bem assim. O HADB é o novo nome do Clustra. Segundo o pessoal técnico do glassfish, se você não precisa de alta disponibilidade com 5 noves, o HADB é overkill. Veja:

http://blogs.sun.com/theaquarium/entry/in-memory_replication_in_glassfish_v2

eduardo pelegri-llopart:

Clustra is a very sophisticated tool. It is a good solution if you need the 5 9’s availability it delivers, but it is an overkill otherwise. We truly believe that most customers will be much better off with the in-memory replication.

[]s
Luca

Luca , vi que deu uma pesquisada sobre o assunto e encontrou uma opinião sobre. Entretanto, eu tenho a experiência prática e sei que em sistemas distribuídos onde há de fato a exigência de tolerância à falhas, essa é uma solução extremamente poderosa, que muitos profissionais ainda não conhecem.

Se alguém tentou fazer replicação de sessão e passou problemas de latência ou performance, sabe do que estou falando.

Para findar, acho que a especificação tem falhas sim, mas tem pontos legais, como afirmei outrora.

Construir serviços de alta disponibilidade, como SessionBeans, MDBs - serviços de mensageria, acesso remoto (corba); exigiria um desvio muito grande do projeto, para focar em questões de INFRA, que o framework te provê.

Há também produtos, que podem fazer toda a diferença, como BEA um dos melhores (senão o melhor) produto com muitas características que podem de fato trazer um incremento à solução.

A especificação 3.0 trouxe uma série de benefícios, como simples configuração, debugger entre outros. Mas com as IDEs de hoje em dia, Debugar ficou mais simples, pode atachar via RMI. Você não tem mais a necessidade de implementar uma porrada de interfaces, nem colocar se é local ou remota, agora está automatico a paradinha …entretanto, um bom desenvolvedor, implementaria um Façade para acesso remoto e para os outros Sessions internos aos módulos, usaria interface local. O lookup dá infinitamente menos trabalho fazendo uso de IoC, mas na especificação anterior você poderia utilizar Patterns para contornar a situação, como ServiceLocator, não é o melhor dos mundos, mas confere um certo grau de organização e produtividade.

Dá mais trabalho, mas o resultado não está tão diferente.

O que mudou mesmo foi a JPA , EntityManager, a forma de configurar tudo aí realmente é outro assunto.

O que não entendo é porque sempre colocam EJB == EntityBeans ? - Entity é só uma parte da especificação, podre por sinal :slight_smile: .

M

Então, em miúdos, minha estrutura ficaria assim:

view > controller > model > repository > dao > sgbd

Sendo que:
Se eu não utilizar minhas classes de dominio como somente VO ou DTO, farei o uso da dependência do repository o qual terá acesso indireto a camada Dao.

Se eu usar DTO’s ou VO’s, chamarei da minha classe que trata negócio, os métodos da interface repository ou Dao.

É isso ?!?

[]'s

P

Pense em Camadas. Repository faz com queobjetos de negócios só pensem em objetos de negócio. Leia Robert C. Martin sobre inversão de dependências.

P

marciobarroso:
Então, em miúdos, minha estrutura ficaria assim:

view > controller > model > repository > dao > sgbd

Não, releia minha mensagem para p saoj.

Por que você suaria VO/DTO em primeiro lugar?

F

Tipica discussao interessante que só tem fim quando alguem desiste de escrever…

Eu concordo com argumentos de vários que escreveram

1 - nomes são importantes pois criam um vocabulário em comum para que todos possam se comunicar mais facilmente. Mesmo que eu nao concorde com um nome, eu procuro saber o que ele significa para outros profissionais… e tento explicar também como eu interpreto esse nome.

2 - Acho importante debater sobre o que Fowler, Evans (e outros) escreveram, assim podemos formar nossas própŕias opiniões… Assim também podemos conhecer algo que é mais difundido do que nossas opiniões. Se alguem concorda com tudo que eles escreveram, pelo menos estão concordando com alguem que já refletiu bastante sobre os assuntos…

3 - Nossa “obrigação” é saber a teoria, mas na hora de por na prática saber decidir o que utilizar dela… por exemplo: todos deveriam conhecer o conceito de Repositorio mesmo que nunca venham a implementar…

Acho que a discussao aqui acontece mais porque não existe uma verdade absoluta, porque cada um tem suas opiniões, interpretações e principalmente EXPERIÊNCIAS…

Talvez uns achem Repositorio algo extremamente importante e talvez outros não tenham sentido necessidade de usar. Não podemos esquecer que aqui temos pessoas de todos os tipos…

D

Concordo plenamente!

(post sem utilidade nenhuma na discussão, mas fiquei muito feliz por alguém ter escrito isso)

R

Antes que eu me esqueça de novo:

Free book: Domain Driven Design Quickly

[]'s

Rodrigo Auler

S

Eu acho teoria importante, mas acho tb que um código/exemplo prático fala melhor do que 10 teorias:

Abaixo tenho o modelo:

Action -&gt Model/Manager/Repositório/??? -&gt DAO -&gt Impl DAO -&gt Banco

public String add() throws Exception {
      
      String method = input.getProperty("method");
      
      boolean isPost = method != null && method.equalsIgnoreCase("post");
      
      if (isPost) {
         
         // post = tentando inserir...
         
         Job job = input.getObject(Job.class);
         
         int id = jobManager.insertJob(job);
         
         if (id &lt= 0) return ERROR;
         
         stageManager.createDefaultStages(id);
         
         return SHOW;
         
      } else {
         
         // get = assume está querendo adicionar um registro...
         
         return SUCCESS;
      }

   }

Será que assim ficaria melhor:

public String add() throws Exception {
      
      String method = input.getProperty("method");
      
      boolean isPost = method != null && method.equalsIgnoreCase("post");
      
      if (isPost) {
         
         // post = tentando inserir...
         
         Job job = input.getObject(Job.class);
         
         int id = job.insert();

         if (id &lt= 0) return ERROR;
         
         job.createDefaultStages();
         
         return SHOW;
         
      } else {
         
         // get = assume está querendo adicionar um registro...
         
         return SUCCESS;
      }

   }
  • Será que a action deveria acessar o DAO diretamente?

  • Será que minha action virou o modelo?

  • Será que a action deveria virar modelo?

  • Será que o modelo deveria ser separado da action, mas poderia virar uma action não acoplada ao framework? (POJO ACTION)

  • Estou começando a achar que a maneira mais bonita, de forma que sua aplicação ficaria o mais independente possível do framework em questão é:

framework mvc -&gt Modelo/Pojo Action -&gt DAO / Repository -&gt Implementação de DAO -&gt Banco de dados…

Assim vc teria uma action, que não seria na verdade uma action, mas sim uma espécie de model… O preço a pagar me parece claro tb: burocratização do processo… Seria como programar sem uma interface DAO e tentando deixar sua aplicação independente de banco de dados… (Model não é como DAO, não dá para fazer uma interface UserAction, ou seja, para abstrair o modelo de negócios…)

A dúvida que ainda tenho e se realmente vale a pena jogar o DAO pra dentro das entidades e deixá-las o mais esperto possível (segundo código postado) ou trabalhar com Entidades que apenas são envelopes de dados a a manipulação dessas entidades acontece por fora delas via DAO (primeiro código postado)…

R

pcalcado:

Pense em Camadas. Repository faz com queobjetos de negócios só pensem em objetos de negócio. Leia Robert C. Martin sobre inversão de dependências.

Eu entendi. Só não enxergo nenhuma situação em que usar Repository num objeto de negócio em vez de DAO seja efetivamente vantajoso, na pratica. No fim, da na mesma. :slight_smile:

F

Vamos considerar a busca do melhor “design possivel”(se é que isso é possivel)

Não

Não

Não

Não

Minha visão…
O Action, deve pegar os dados da fonte(web, swing) e repassar pra alguem… Se usarmos DDD, o action poderia conversar com uma fachada que manipularia os objetos de negocio (é claro que com as regras desses objetos dentro deles mesmos)

Actions deveriam ser “burros” e apenas fazer validações de dados(não de negócios) conversões e formatações

Existe um livro muito legal que da uma passada em algumas “opções” de design chamado POJOs in Action

É um livro teorico/pratico e tem vários exemplos de código… recomendo (Mas ele é um pouco superficial)

É claro que dependendo da situação, fazer um action acessar um DAO não é nenhuma heresia… não vou dizer que nunca fiz isso…

S

Eu tb tenho feito a coisa assim… Meu erro foi ter chamado essa classe que recebe os dados da action de JobManager, o que passa a idéia errada da coisa. Melhor seria JobLogic, JobSession, JobWork, etc. (alguém teria um nome melhor?)

Me restou a seguinte dúvida:

A action deve passar os dados para um JobWork desses da vida ou deve passar direto para um objeto Job de forma que o job saiba se virar para carregar tudo que ele precisa e fazer as operações no banco.

se virar = possuir dentro dele uma instância de JobRepository ou JobDAO de forma que ele possa se auto-carregar, e carregar outras dependencias que ele venha a ter.

O impasse aqui é que usando um JobWork, meu objetos podem ter uma tendencia de ser apenas envelope de dados… mas acho que uma coisa não tem nada haver com a outra, ou seja, usar um JobWork da vida não significa que meus objetos serão anêmicos…

F

saoj:

O Action, deve pegar os dados da fonte(web, swing) e repassar pra alguem… Se usarmos DDD, o action poderia conversar com uma fachada que manipularia os objetos de negocio (é claro que com as regras desses objetos dentro deles mesmos)

Eu tb tenho feito a coisa assim… Meu erro foi ter chamado essa classe de JobManager, o que passa a idéia errada da coisa. Melhor seria JobLogic, JobSession, JobWork, etc. (alguém teria um nome melhor?)

*Service talvez

Ai que ta…
Fachadas ou não?
Eu usaria as fachadas… não acho legal os actions conhecerem os objetos de negocio. Pra mim actions devem fazer somente o que eu falei anteriormente…

Eu faria como no uml que estou postando em anexo

P

Problema com seu exemplo: Action não tem nada a ver com Repository. Action é MVC e MVC é Camada de Apresentação, estamos falando da integração entre negócios e Persistência.

saoj:
Eu acho teoria importante, mas acho tb que um código/exemplo prático fala melhor do que 10 teorias:

Ponto interessante.

  1. Já foram citados neste artigo diversas documentações que possuem vários exemplos, alguém se deu ao trabalho de ler pelo menos alguma?

  2. Um exemplo, vinte exemplos,t rinta exemplos não conseguem explicar todos os casos, então não, ele não vale mais que 10 descrições de uma teoria (ou exemplo e teoria são antagônicos?)

Na boa, Sérgio, leia a documentação, depois poste aqui. Fica muito repetitivo ter a mesma pergunta feita de 30 maneiras diferentes e por mais que tentemos provavelmente não seremos tão claros quanto as pessoas que criaram ou catalogaram estas práticas. Fica difícil debater as idéias do Domain-Driven Design sem saber o que é Domain-Driven Design.

Segundo este pensamento dá na mesma fazer Action chamar DAO, ou nem ter DAO, afinal dá tudo na mesma. Ou melhoir: pra que interfaces? Use logo as implementações, dá na mesma.

Não, não dá. Se vale a pena usar no caso X ou não é outro assunto, mas pela enésima vez: DAO pode ser a implementação de repositório, repositório não precisa ser implementado por um DAO.

S

Sinceramente não entendo esse tipo de colocação, Phillip. Todos aqui estão trocando idéias e debatendo com educação, e acredito que eu e todo mundo aprendemos bastante com o tópico. Vc tb estava contribuindo bastante e de repente vêm com essa de “Na boa, Sérgio, leia a documentação para o tópico não ficar repetitivo”, como se o foco negativo desse post estivesse em mim. É lamentável esse tipo de postura… É um comportamento no mínimo indelicado, para economizar nos adjetivos…

Pode dar a entender que vc está mais preocupado comigo do que com o tópico em si.

Bom, agradeço a todos que contribuiram e debateram, principalmente ao Fábio Kung e ao FelipeC… Aprendi bastante e agora mesmo estou refatorando meu sistema para melhor aplicar esses conceitos.

Ok, vou estudar mais. Me desculpe por vc ter perdido o seu precioso tempo discutindo com pessoas que não sabem o que é DDD.

R

felipec:
Fachadas ou não?
Eu usaria as fachadas… não acho legal os actions conhecerem os objetos de negocio. Pra mim actions devem fazer somente o que eu falei anteriormente…

Eu não vejo problema que as actions conheça os objetos de negócio. As minhas actions conhecem minhas classes de repositório e minhas classes de serviço.

Uma dúvida, no seu diagrama o que você chama de fachada? O TransferService?

[]'s

Rodrigo Auler

K

pcalcado:
Problema com seu exemplo: Action não tem nada a ver com Repository. Action é MVC e MVC é Camada de Apresentação, estamos falando da integração entre negócios e Persistência.

saoj:
Eu acho teoria importante, mas acho tb que um código/exemplo prático fala melhor do que 10 teorias:

Ponto interessante.

  1. Já foram citados neste artigo diversas documentações que possuem vários exemplos, alguém se deu ao trabalho de ler pelo menos alguma?

  2. Um exemplo, vinte exemplos,t rinta exemplos não conseguem explicar todos os casos, então não, ele não vale mais que 10 descrições de uma teoria (ou exemplo e teoria são antagônicos?)

Na boa, Sérgio, leia a documentação, depois poste aqui. Fica muito repetitivo ter a mesma pergunta feita de 30 maneiras diferentes e por mais que tentemos provavelmente não seremos tão claros quanto as pessoas que criaram ou catalogaram estas práticas. Fica difícil debater as idéias do Domain-Driven Design sem saber o que é Domain-Driven Design.

Segundo este pensamento dá na mesma fazer Action chamar DAO, ou nem ter DAO, afinal dá tudo na mesma. Ou melhoir: pra que interfaces? Use logo as implementações, dá na mesma.

Não, não dá. Se vale a pena usar no caso X ou não é outro assunto, mas pela enésima vez: DAO pode ser a implementação de repositório, repositório não precisa ser implementado por um DAO.

Philip, às vezes para abstrair alguns conceitos, precisamos no mínimo de alguns exemplos tangíveis, para ver sua aplicação.

Acho válida a argumentação do Sérgio.

Fica complicado apenas citar Patterns e dar link para os mesmos , pois alguns conseguem abstrair outros não e tais exemplos, ajudariam reforçar o entendimento e até mesmo corrígi-los, pois alguns podem entender algo que na prática é diferente.

Já vi vários tópicos seus, com grande auxílio, mas falta o tal do exemplo tangível e acredito que para muitos, a referência acaba ficando confusa e seu empenho foi em vão.

S

Parece que ficou no ar alguma duvida sobre DAO X Repository e que Repository pode ser / implementar um DAO (Data Access Object)
Repository (Repository) é onde as entidades estão. Não onde os “dados brutos” estão , mas os objectos de negocio. A entidade Cliente tem quantas instâncias ? Onde elas estão ? no repository. Como uma entidade encontra as entidades que lhe cabem ? Por exemplo , como um pedido encontra seus itens ? Pelo repositório. Claro que os itens são injetados no pedido, mas como ?

Pedido p  = Repository.get ( Pedido.class, 14 ); // 14 é a chave

O Repositório internamente identifica que Pedido tem um associação com PedidoItem e automaticamente faz (internamente)

Pedido p  =  new Pedido(14);

p.setItens (Repository.get ( PedidoItem.class, p));

Ou poderia injetar uma implementação de Collection, que fizesse lazy loading

Pedido p  =  new Pedido(14);

p.setItens ( new LazyList( this,  PedidoItem.class, p));

Que depois faria o codigo de cima quando alguém consultasse a lista.

Por outro lado, o repositório está associado ao dominio. Um DAO está associado aos dados brutos e à tecnologia paras os acessar (Data Access Object)
Mas como o repositório preenche os dados das instâncias ?
Ele tem que usar um DAO. Porque? Porque os dados não estão em objetos na memória. Mesmo que estejam, provavelmente não estão na mesma forma em que o domínio os quer. O comum é estarem no banco de dados, mas poderiam estar no mecanismo prevalente, ou numa simples List ( por exemplo em ambiente de teste)
O repository isola a instancia do dominio do local onde as outras instancias estão , o DAO isola o repositorio de saber onde os dados estão.
Veêm a diferença ? Um trabalha com instancias do dominio, o outro com dados brutos.

O DAO isola também o mecanismo de procura. Para bancos ele usa SQL, mas para list provávelmente usa um filtro. O repository apenas passa ao DAO “o quê ele quer” e não o “como encontrar”. O mesmo para os objectos de negocio que pedem o que querem e não dizem ao repository como encontrar.

Mas isto é a camada de negocios. Como seria na camada de visualização.
Se eu quiser listar todos os pedidos num table num html tenho que passar pelo repository ? Não. Basta usar o DAO. Não ha logica de negocios aqui. Apenas transferência de dados brutos.

O repositório é a forma como as instancias das entidades de negocio se comunicam e se encontram (repositório : onde todo o mundo está)
O dao é a forma como um repositório especifico executa esse trabalho.
Poderíamos ter repositório sem dao. Um exemplo classico é que o repositório seja um grafo gigante em que a raiz é um objeto anônimo que contém todas as coleções de todas as entidades de negocio que cotêm todas as referencias aos objetos que necessitam. Isso seria OO puro, mas isso não é tecnologicamente viável. Somos obrigados a guardar os dados de forma mastigada , e para isso que serve o DAO.

A interface de um DAO e de um Repository são muito semelhantes, mas elas não significam a mesma coisa. Não se pode pedir a um repository que encontre um objeto com base numa frase SQL, a um DatabaseDao, pode.
Mas a um InMemoryListDao não pode. Ou seja, a comunicação da intensão tb tem que ser abstraida de forma que o programador/objecto de negocio diga “o que quer” e "não como quer"
Claro que isto pode ser muito complicado, e, no caso geral serei obrigado a escrever o SQL na mão. Isto viola o encapsulamento que estou construindo com os DAO e os Repository. Isso nunca é bom. Claro, podem dizer que 99,99% dos casos usam banco de dados e que portanto usar SQL é tranquilo (quem diz SQL , diz EQL, HQL ,etc…) Mas , na verdade , é uma violação sim.
Quando no futuro , a tecnologia de persistência for outra, e o SQL não for mais a forma de procurar pela informação danou. Vai ter que haver outro software. Não se fizermos as coisas como deve ser. A lógica de negocio não depende do banco. Ela sempre será a mesma. Então se a tecnologia muda para outra coisa - digamos XQuery como exemplo - so teria que escrever um XQueryDAO. Mas e para as SQL que tive que escrever na mao ?

Para essas é criado um DAO especial que contém as SQL sofisticadas e retorna os dados. Ou seja, eu não passo o SQL , ele já está lá dentro. O repositório traduz isso para a camada de negocio. A camada de negocio não sabe que existem dois DAO no repositório. Mas ele sabe que DAO chamar dependendo da pergunta que lhe foi feita pelas classes de negocio. Se a tecnologia mudar eu crio um DAO com as consultas XQuery dentro dele e o repositório nunca saberá a diferença.

São duas responsabilidades diferentes. Ser o ponto de encontro das instancias das entidades - Repository, ou ser o cara que garimpa os dados avulsos que constituem essas entidades - DAO.


Alguem falou que um DAO generico seria algo como

Dao<T , I>{

T find (I id)
}

Na realidade o DAO mais genérico é

Dao {
<T> T find (Class<T> entity , Object id);
}

Que é o que o EntityManager do EJB 3 usa , embora ele seja um Repository e não um DAO.

R

pcalcado:

Segundo este pensamento dá na mesma fazer Action chamar DAO, ou nem ter DAO, afinal dá tudo na mesma. Ou melhoir: pra que interfaces? Use logo as implementações, dá na mesma.

Não, não dá. Se vale a pena usar no caso X ou não é outro assunto, mas pela enésima vez: DAO pode ser a implementação de repositório, repositório não precisa ser implementado por um DAO.

Peraí cara.

Eu digo que dá na mesma pois você mesmo disse que a unica diferença entre uma interface UserDAO e UserRepository é o nome! Por isso da na mesma, das duas maneiras eu abstraio o código de persistência da minha lógica de negócios. Só o nome da interface vai ser diferente.

Não tem nada haver com a ACtion chamar o DAO ou nem mesmo ter o DAO, pois nisso há o grave problema de uma clara violação de camadas.

D

Pessoal,

Muito boa a discussão. Tenho uma pequena dúvida. Imagine uma classe do dominio do problema. Esta classe (um POJO com atributos e métodos de negócio) não é uma classe “gerenciada” por um container IOC correto (ex: Spring)? Então imagine que necessito de fazer algo do tipo:

DomainObject domainObject = new DomainObject();
domainObject.setAttribute1("A");
domainObject.setAttribute2("A");
//... N atributos
domainObject.businessMethod();

E que meu metodo businessMethod precise de uma referência do repositorio para realizar a logica usando tb os atributos preenchidos anteriormente. A pergunta é: como o objeto que implementa o repositório pode ser injetado/atribuido visto que a classe DomainObject não é uma classe gerenciada.
Já pensei em três maneiras:

  • AOP: no new eu faria essas injeções. Não sei me parece um overkill… Acho que alguém me disse que o Rod Johnson faz assim… BTW, não gosto muito pois o código não fica muito evidente… mas é uma alternativa
  • usar uma Factory ao invés de fazer o new, onde terei oportunidade de injetar os repositórios. Muito manual, um objeto “artificial” à mais, eu sei… Mas é a alternativa que mais me atrai…
  • recuperar o repositorio antes e atribui-lo como mais um atributo da minha classe (ARGH!).

Existem mais maneiras? Qual é a mais recomendada? Como vocês estão fazendo isso hoje?

Desde já agradeço a atenção!

R

duardor:
E que meu metodo businessMethod precise de uma referência do repositorio para realizar a logica usando tb os atributos preenchidos anteriormente. A pergunta é: como o objeto que implementa o repositório pode ser injetado/atribuido visto que a classe DomainObject não é uma classe gerenciada.
Já pensei em três maneiras:

  • AOP: no new eu faria essas injeções. Não sei me parece um overkill… Acho que alguém me disse que o Rod Johnson faz assim… BTW, não gosto muito pois o código não fica muito evidente… mas é uma alternativa
  • usar uma Factory ao invés de fazer o new, onde terei oportunidade de injetar os repositórios. Muito manual, um objeto “artificial” à mais, eu sei… Mas é a alternativa que mais me atrai…
  • recuperar o repositorio antes e atribui-lo como mais um atributo da minha classe (ARGH!).

Nos meus repositórios eu tenho um método create que já recebe os dados mínimos que o objeto precisa pra ter um estado válido e já injeta as dependências, ou seja, é proibido dar new nos objetos do domain, como uma factory mesmo. E pros objetos vindo do banco pelo hibernate eu uso um interceptor do hibernate que usa o Spring pra injetar as dependências byName.

[]'s

Rodrigo Auler

F

Ótima questão! Estava pensando comigo mesmo se mais ninguém se perguntava sobre isso…

Eu ia responder aqui, mas achei melhor blogar a respeito: http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/.

(tá, tá… eu também sou contra ficar linkando para blog no fórum. Mas nesse caso não teve como!)

P

Ok, eu me exedi e peço desculpas.

Frequentemente trabalhamos exemplos com pessoas aqui quando elas estão com dificuldades em aplicar conceitos, mas quando eles estão com dificuldades em entender conceitos geralmente é melhor ler sobre o tal conceito antes de perguntar. Como falei antes um exemplo não vai mostrar o que o conceito representa, do contrário não haveriam livros com seus capítulos cheios de exemplos e textos.

Tudo que foi pedido consta na bibliografia -e boa parte disponível online gratuitamente- mas a impressão que tenho é que se acha que é eficaz inferir informação baseado em meia dúzia de postagens num fórum sem conhecer a base da discussão e sem nem querer conhecer.

Existe uma tendência em todas as áreas de se esconder atrás de ‘pragmatismo’ para não ler e pesquisar mas ainda assim dar opiniões sobre as coisas que não conhecem.

P

Eu disse isso? Onde?

microfilo:

Por isso da na mesma, das duas maneiras eu abstraio o código de persistência da minha lógica de negócios. Só o nome da interface vai ser diferente.

Não tem nada haver com a ACtion chamar o DAO ou nem mesmo ter o DAO, pois nisso há o grave problema de uma clara violação de camadas.

Não, o que eu venho falando aqui há alguns posts é que objetos de negócio lidam com Repository, não com DAO. O DAO pdoe ser a real implementação do Repository -ou não- mas apra o objeto de negócios é um Repository, não um DAO que ele nem sabe do que se trata.

Da mesma maneira, se um método receber java.util.List Para ele é uma lista. Se for na verdade um trabolho mega-complexo que guarda os elementos em bases de dados distribuídas não improta, é uma lista. Um Repository não rpecisa ser uma interface, o ponto aqui é a abstração entre List–&gtListamegaDistribuida e Repository-&gtDAO.

P

Acho que conseguimos simplificar este problema apra: como fazer quando um objeto requer outro para funcionar, não?

Bom, temos 2 questões aí. Primeiro, a relação entre os objetos (Usuario–>RepositoryDao) pode ser parte da invariante do objeto Usuario. Neste caso quando o objeto for criado ele deve ser populado. Factory é normalmente a melhor alternativa para criar objetos complexos, Factories genéricas como o Spring podem ajudar (mas eu abstrairia seu uso).

Na segunda possibilidade temos a relação como pré-condição para a invocação do método. Ou seja: a relação não rpecisa existir, exceto ao se invocar o método que faz uso desta. Neste caso você poderia fazer um itnerceptor para popular a relação on-demand.

Tenho a impressão que esta última abordagem é overkill para a maioria dos problemas. Se você tem objetos com relações delicadas crie-o através de Factories.

Se ter uma Factory é um estorvo muito grande use um FactoryMethod. Poderia ser um método estático na classe, Ruby-like, mas cuidado para não criar elefantes brancos.

F

Se tivesse um ranking com as melhores discussões do GUJ, eu votaria nesta!

D

Primeiro, obrigado pelas respostas, este topico realmente têm me ajudado muito e me tendencionado a adotar DDD…
Fabio, muito instrutivo o seu post no teu blog.

pcalcado:

Se ter uma Factory é um estorvo muito grande use um FactoryMethod. Poderia ser um método estático na classe, Ruby-like, mas cuidado para não criar elefantes brancos.

Gostei da idéia mais do que da própria Factory. Algo como Domain.create() ou Domain.getNew()
Mas pcalcado, um método estático tiraria o repository de onde? Falando um pouco mais de implementação, por ex. usando Spring… O repository sendo um objeto “gerenciado” pelo Spring… Dá até pra fazer uns pequenos “arranjos” (entenda coisas não muito bonitas e não convencionais) para guardar em um atributo estático uma referência ao ApplicationContext e assim ter acesso aos objetos gerenciados pelo Spring… Deste modo o método estático teria acesso a esta referência e conseguiria “injetar” o repository em seu objeto… Mas como já disse não ia ficar muito bonito não… Incluiria fazer as classes do dominio implementar aquela ApplicationContextAware (ARGH!) do Spring…
Como você está implementando isso hoje em seus sistemas? Recomenda algo?

PS: Como o aviso por email tá fazendo falta!!!

R

Do post do Fabio Kung:

public class Repository {
  private final Session session;
  public Repository(Session session) {
    this.session = session;
  }
  
  public void get(Long id) {
    // poderia delegar para um dao, se fosse necessário
    Usuario u =  session.load(id);
    u.setRepository(this);
  }
}

O problema de injetar as dependências assim é quando se faz buscas. Se você faz uma busca que retorna 50 objetos como injetar essas dependências? Por isso que uso interceptor do Hibernate.

Não gosto de métodos estáticos. São ruins de testar. Faço os repositórios gerenciados pelo Spring e o create fica no repositório. Tenho tudo a mão pra criar meus objetos.

[]'s

Rodrigo Auler

T

Segundo alguns textos que li sobre DDD, os factories servem tanto para CRIAR objetos complexos quanto para RECONSTITUIR objetos (por exemplo, objetos carregados do repositório).

Então, seu repositório faz a query utilizando seja lá o que for (jpa, hibernate etc). Seu repositório também terá uma referência a um factory (relativo ao aggregate em questão) e o utilizará para recompor esses objetos antes de repassá-los para a aplicação.

P

Não não, o estático foi ilustrativo. Use métodos de instãncia com objetos gerenciados pelo Spring mesmo. Eu costumo fazer exatamente assim. Dificilmente existe um Entity (falando no jargão DDD) que seja criado manualmente, geralmente ele é criado por um Factory Method em um Service (outra vez DDD) que já cuida destas coisas.


Um Factory lida com lógica de inicialização complexa. O papel de uma Factory numa paltaforma como Java é agrantir que a invariante do objeto seja cumprida.

Como fatalmente o Repository (ou mesmo um Context Mapper ou algo do tipo) precisa criar novos objetos válidos e apra isso precisa verificar e garantir a invariante. Como esta lógia é da Factory é normal que o Repository utilize a Factory (não o contrário). Um Rpoeisotyr pode também abstrair funções do tipo “procure X, caso não encotnre crie um novo”.

D

Opa pessoal, tudo bom?

Eu tenho uma dúvida quanto ao reuso dos métodos de “CRUD” no caso, por exemplo, qual seriam as formas mais elegantes de eu nao ter que implementar métodos como Person.get() , ou Person.list() em todos o meus objetos de négocio?

F

Acho que fica melhor (em Java) deixar esses métodos no repositório / dao.

T

Olá,

esta discussão está ótima!

TriTonE:
Segundo alguns textos que li sobre DDD, os factories servem tanto para CRIAR objetos complexos quanto para RECONSTITUIR objetos (por exemplo, objetos carregados do repositório).

Eu entendi diferente. As factories apenas criam objetos novos enquanto é responsabilidade do repository carregar objetos existentes.

Não sou fã da idéia de reaproveitar as factories dentro do repositório também. Eu preferiria deixar a responsabilidade da contrução do objeto existente no framework ORM. Li este artigo ontem e parece que tornaria isto possível.
Migrating to Spring 2: Part 3 - injecting dependencies into entities

Quero reforçar esta dúvida. Eu prefiro colocar métodos como get(), list() e find() como sendo estáticos, ou seja, prefiro “Aluno.getAll()” ao invés de “new Aluno().getAll()”. Já que estamos falando em OO fica estranho uma instância de aluno conhecer e listar outros alunos que não são ele. Enfim… como vocês tem lidado com isso?

Shoes:
Segundo, você não precisaria ter um método para este tipo de coisa, aliás se você tiver muitos métodos assim é sinal que seu design é bem ruim. Você resolve isso com outra dupla: Specification/QueryObject.

Não querendo ser folgado… :mrgreen: Mas você possui alguma referência para nos indicar para estudar sobre os padrões Specification e QueryObject? Desde os fundamentos e um exemplo mostrando o caminho das pedras para implementá-los?
Obs: Ainda não pesquisei muito no google mas vou pesquisar com certeza.

M

Acabei de ler o tópico desde o início (ótimo, por sinal), mas algumas afirmações me dixaram com dúvida,

pcalcado:
… I used to have:

Domain Object --&lt&lt;depends&gt;&gt--&gt Repository &lt--&lt&lt;implements&gt;&gt-- DAO

And changed to:

Domain Object --&lt&lt;depends&gt;&gt--&gt Repository

Repository &lt--&lt&lt;implements&gt;&gt-- RepositoryImpl --&lt&lt;depends&gt;&gt--&gt DatabaseDao--&lt&lt;depends&gt;&gt--&gtSearchEngineDao


Segundo o trecho acima, o padrão Repository pode ocasionar em uma camada a mais no design do sistema, dependendo do caso, tudo bem. Mas o que me deixou em dúvida foi a dependência de RepositoryImpl com DatabaseDao… me parece que os 2 ficam com uma dependência forte, ficando o RepositoryImpl sabendo como os dados são armazenados. Neste caso ele ficaria fora da camada de negócio? De repente este exemplo ficou bem abstraído e eu não entendi direito.

Quanto ao MVC:

pcalcado:
Acho que você entendeu errado o Model no MVC, por isso esta confusão. Model em MVC é: -&gt UserRepository -&gt Implementação concreta do repositório MySQLUserRepository -&gt Banco de dados. Tudo isso.

pcalcado:
Problema com seu exemplo: Action não tem nada a ver com Repository. Action é MVC e MVC é Camada de Apresentação, estamos falando da integração entre negócios e Persistência.

Também sempre considerei MVC como apresentação, conforme a segunda afirmação, mas a primeira parece dizer o contrário… talvez não tenha ficado claro o que o Philip quiz dizer com a primeira afirmação e se puder esclarecer um pouco… :slight_smile:

T

Thiago Senna:
Olá,

esta discussão está ótima!

TriTonE:
Segundo alguns textos que li sobre DDD, os factories servem tanto para CRIAR objetos complexos quanto para RECONSTITUIR objetos (por exemplo, objetos carregados do repositório).

Eu entendi diferente. As factories apenas criam objetos novos enquanto é responsabilidade do repository carregar objetos existentes.

Sim, você vai utilizar o repository para carregar um objeto. Quando salvamos objetos no repositório, é comum termos atributos “transientes” (referências para services, repositories etc). Então você acaba tendo que satisfazer as dependências dos objetos carregados dentro do repositório mesmo, como você disse. No entanto, quando criamos novos objetos, TAMBÉM temos que fornecer as dependências.

No caso, faz mais sentido “estender” um pouquinho a responsabilidade dos factories de modo a criar e “remontar” objetos. Dessa forma, seu repositório terá uma referência ao factory que, por sua vez, será utilizado para preencher as dependências necessárias antes de retornar o objeto.

Fazendo desse jeito, teremos a lógica a montagem de objetos (criação e reconstituição) em um único local, o que, ao meu ver, facilita a manutenção.

P

Thiago Senna:
Não querendo ser folgado… :mrgreen: Mas você possui alguma referência para nos indicar para estudar sobre os padrões Specification e QueryObject? Desde os fundamentos e um exemplo mostrando o caminho das pedras para implementá-los?
Obs: Ainda não pesquisei muito no google mas vou pesquisar com certeza.

Tem uma referncia ótima aqui.

P

O Repositório sabe como os objetos são persistidos, em quais lugares, etc. Ele é um objeto na frotneira entre Negócios e Persistência.

mutano:

Também sempre considerei MVC como apresentação, conforme a segunda afirmação, mas a primeira parece dizer o contrário… talvez não tenha ficado claro o que o Philip quiz dizer com a primeira afirmação e se puder esclarecer um pouco… :slight_smile:

Neste diagrama:

O Model é composto por tudo menos o cercado em vermelho.

Fonte: http://fragmental.com.br/wiki/index.php?title=MVC_e_Camadas

B

Cara, eu preciso estudar muuuuuito

R

Tudo entendido sobre Repositorios e DAOs…
Mas eu ainda estou com uma duvida em um sistema que estamos iniciando agora (e que essa thread me ajudou bastante) que é o seguinte:
Nesse sistema, tem horas que eu “vou” num Oracle via JPA, outras em WebServices, outras na plataforma alta via MQSeries e outras em um XMLDB. Pois bem, o Repositorio e o DAO funcional perfeitamente nesses casos. Mas que objeto (nome e tipo) eu devo retornar nesses vários caminhos…
Hoje eu tenho um monte de DTOs… nesse caso, qual o conselho de vcs? E no caso do Entity do JPA? Eu não acho legal retornar um objeto todo anotado… o que fazer?!?

P

rodrigoallemand:
Mas que objeto (nome e tipo) eu devo retornar nesses vários caminhos…
Hoje eu tenho um monte de DTOs… nesse caso, qual o conselho de vcs? E no caso do Entity do JPA? Eu não acho legal retornar um objeto todo anotado… o que fazer?!?

Seu problema não tem tanto a ver com Repositórios ou DAOs e sim com objetos de negócio. Você deve retornar Entities e seus Aggregates segundo Domain Driven Design, que não necessariamente são Entities JPA mas que pdoem ser sem problemas. Anotações foram criadas exatamente para abstrair dos objetos infra-estrutura como persistência ou transações.

R

Não conheço DDD a fundo… mas como essa camada de negocio ficará exposta para outros serviços (via JAR ou via transação remota) como seriam os objetos?!? Digo como seriam, assim, POJOs, destacados dos objetos utilizados no caminho até o repositorio real, etc…

pcalcado:

Anotações foram criadas exatamente para abstrair dos objetos infra-estrutura como persistência ou transações.

Idem acima. Em alguns casos, esses objetos de negocio devem ser expostos para outro sistema. Não ficaria “feio” mandarmos um objeto com configurações de mapeamento anotadas?!? Em contra partida, duplicar objetos somente para tirar as anotações seria um tiro no pé, já que atualizações deverão ser em dois lugares agora…

O problema é: eu preciso expor objetos (POJOs). Vcs acham que ficaria “feio” expor objetos anotados?

A

Sem entrar no mérito das anotações, quando o assunto é integração, ficaria “feio” expor os próprios Pojos. Se assim o fizer estará acoplando suas aplicações cliente ao seu modelo, e isso é ruim. Imagine, se elas forem forçadas a recompilar suas aplicações toda hora que vc adiciona/atualiza/exclui um atributo em qualquer Pojo do seu modelo, .

XSDs podem ser opções mais elegantes quando o problema é definir “padrões” de dados que devem trafegar entre aplicações.

B

pcalcado:
Dificilmente existe um Entity (falando no jargão DDD) que seja criado manualmente, geralmente ele é criado por um Factory Method em um Service (outra vez DDD) que já cuida destas coisas.

Não sei se estou misturando as bolas mas,

Este factory method também faz e registro do objeto como limpo em uma unidade de trabalho?

B

pcalcado:
Thiago Senna:
Não querendo ser folgado… :mrgreen: Mas você possui alguma referência para nos indicar para estudar sobre os padrões Specification e QueryObject? Desde os fundamentos e um exemplo mostrando o caminho das pedras para implementá-los?
Obs: Ainda não pesquisei muito no google mas vou pesquisar com certeza.

Tem uma referncia ótima aqui.

Será que resumo da infoq chega a falar sobre isso? Vou dar uma olhada…

B

Taz:

Sem entrar no mérito das anotações, quando o assunto é integração, ficaria “feio” expor os próprios Pojos. Se assim o fizer estará acoplando suas aplicações cliente ao seu modelo, e isso é ruim. Imagine, se elas forem forçadas a recompilar suas aplicações toda hora que vc adiciona/atualiza/exclui um atributo em qualquer Pojo do seu modelo.

Desculpa se estou sendo muito burro!

Você só precisa recompilar uma classe quando a interface de uma classe que ela depende muda! (Ou to viajando?)

Eu penso que se as interfaces dos seus pojos são estaveis vc pode acoplar qualquer coisa a eles. A implementação pode mudar a qualquer hora sem que vc tenha que recompilar seu cliente!

Falo de interface como sendo os métodos que a classe fornece!

"Teve uma época que li programe somente para “interfaces”! Sai criando interface para tudo! sem nem ter necessidade! hauhahauhauha o mula!

G

Tópico Hellraiser…heheheheh…

Da pra fazer isso nesse caso:

@MappedSuperclass
public abstract class Pessoa{
      //Varias annotations de mapeamento...
}

Dai tu expõe apenas a:

@Entity
public class PessoaEntity extends Pessoa {
}

Melhoraria um pouco o problema. Não o excluiria por completo. Outra solução para não expor configuração seria voltar ao XML.

T

Aproveito que o tópico foi ressucitado para recomendar a leitura do mesmo. :smiley: É um dos tópicos clássicos do GUJ.

C

Boa madrugada gente!!! :slight_smile:

Estou estudando sobre DDD e este post best seller ajudou totalmente.

No final das contas me restou uma dúvida:

Nos no meu “UserRepository” eu tenho algo mais relacionado ao negócio, suponhamos que eu precise de encontrar “Todos usuários com salário > 5.000, que tenham Casa própria quitada, que não tenha filhos, seja solteiro etc etc”(considere que seja uma consulta bem complexa) e lá na interface repository eu terei este método "findUsersBemDeVida();

Até ai ok, pois representa algo bem espefíco, mas agora se eu estiver usando este modelo:

UsuarioRepository > UsuarioDecorator(implements UsuarioRepository) > UsuarioDao

Onde ficará meu SQL(HQL seja o que for) dessa consulta?

Considerando que nesse UsuarioDecorator eu já tenha um UsuarioDao para outras consultas gerais, o que seria o correto e/ou melhor pra ser feito?

1- Colocaria dentro do UsuarioDecorator uma instância de uma EntityManager e faria essa consulta diretamente ali sem ir ao UsuarioDao;

2- Delegaria essa consulta para o UsuarioDao(afinal já tenho uma instância dele no UsuarioDecorator) e lá no Dao faria a consulta.

3- Faria todo o SQL dentro do método no UsuarioDecorator, e passaria essa String SQL para um método genérico no UsuarioDao que simplesmente executa a consulta, evitando assim ter que possuir uma instância de EntityManager.

Bem fiquei confusa quanto a isso, a opção 1 me parece estranha ter um EntityManager e um UsuarioDao no Decorator. A opção 2 eu acho sem sentido, se é uma consulta específica do domínio não teria porque ir parar no Dao. A opção 3 eu particularmente acho feio ficar mandando String SQL, tirando isso achei a melhor opção das 3.

Bem posso estar bem errada nos meus pensamentos, mas se alguém puder me ajudar a compreender essa dúvida que ainda me restou.
Alguém pode vir e dizer simplesmente pra esquecer o UsuarioDao e usar apenas o UsuarioDecorator que implementa a interface UsuarioRepository e lá fazer tudo, mas considerando essa minha dúvida, como ficaria de fato essa questão nesse modelo ?

UsuarioRepository > UsuarioRepositoryImpl(meu caso UsuarioDecorator) > Dao > UsuarioDaoImpl

Agradecida a todos pela atenção.

P

Não entendi, por que você está usando essa hierarquia toda? Que tal uma interface RepositorioUsuarios que é implementada por um UsuárioDAO, uma coisa simples que funciona?

Na implementação do Repositório, o DAO na minha proposta acima.

J

pcalcado:
carol_programadora:

Nos no meu “UserRepository” eu tenho algo mais relacionado ao negócio, suponhamos que eu precise de encontrar “Todos usuários com salário > 5.000, que tenham Casa própria quitada, que não tenha filhos, seja solteiro etc etc”(considere que seja uma consulta bem complexa) e lá na interface repository eu terei este método "findUsersBemDeVida();

Até ai ok, pois representa algo bem espefíco, mas agora se eu estiver usando este modelo:

UsuarioRepository > UsuarioDecorator(implements UsuarioRepository) > UsuarioDao

Não entendi, por que você está usando essa hierarquia toda? Que tal uma interface RepositorioUsuarios que é implementada por um UsuárioDAO, uma coisa simples que funciona?

Na implementação do Repositório, o DAO na minha proposta acima.

Corrija se eu estiver errado, mas no projeto exemplo do site oficial (dddsample) , existe um exemplo dessa situaçao, onde a interface do repositorio fica na camada de domínio, e a implementação, no caso em Hibernate, fica na camada de infra-estrutura/persistencia.

C

pcalcado:
carol_programadora:

Nos no meu “UserRepository” eu tenho algo mais relacionado ao negócio, suponhamos que eu precise de encontrar “Todos usuários com salário > 5.000, que tenham Casa própria quitada, que não tenha filhos, seja solteiro etc etc”(considere que seja uma consulta bem complexa) e lá na interface repository eu terei este método "findUsersBemDeVida();

Até ai ok, pois representa algo bem espefíco, mas agora se eu estiver usando este modelo:

UsuarioRepository > UsuarioDecorator(implements UsuarioRepository) > UsuarioDao

Não entendi, por que você está usando essa hierarquia toda? Que tal uma interface RepositorioUsuarios que é implementada por um UsuárioDAO, uma coisa simples que funciona?

Na implementação do Repositório, o DAO na minha proposta acima.

Entendi, sua proposta é tirar essa hierarquia. OK.
Mas pensei nessa estrutura apenas pelo detalhe abaixo:

Se nas minhas classes de controller, quando eu preciso de alguma consulta direta, sem ter negócio envolvido, inclua aqui dados brutos para popular comboBox, DataTable… etc eu tinha pensando em injetar uma dependência “UsuarioDao” no meu “UsuarioController” e não um UsuarioRepository… achei que fosse errado colocar uma dependência do repository no controller, achei que elas deveriam ser usada APENAS por classes do domínio, por domínio quero dizer as entities e os services, então eu pensei que o controller não deveria ter esse contato.
Então creio que estou errada, utilizando sua sugestão Shoes, minha única opção pra inserir dentro do “UsuarioController” seria minha "UsuarioRepository.

Shoes, explorando-te um pouco mais :roll: , vendo o projeto ddd-sample, eu vi algo que me deixou confusa:
La está divido assim:
Application
Domain
Interface
Infrastructure

Dentro de Application e Domain, tem pacote “service”, pelo que li e entendi até agora(a não ser que fiz bagunça) minhas regras de negócio devem ficar no Domain > Service, certo?!

Fiquei confusa com essa camada “Application”, não tinha visto sobre ela no DDD, e na verdade pouco conheço ainda dela no geral(é tanta coisa pra estudar :? falta tempo…), mas pesquisando achei essa definição , que menciona na camada de aplicação serviços EJB, JMS… Agora confundi tudo sobre essa application, JMS e EJB não é infra? O certo não seria ela estar na camada de infrastructure, assim o Dao que acessa o banco, eu teria esses serviços de infra? Ou não? Totalmente confusa agora.

Se puder esclarecer o que vai exatamente nessa camada “Application”.

Obrigada pela ajuda.

A.L:

Corrija se eu estiver errado, mas no projeto exemplo do site oficial (dddsample) , existe um exemplo dessa situaçao, onde a interface do repositorio fica na camada de domínio, e a implementação, no caso em Hibernate, fica na camada de infra-estrutura/persistencia.

Pois é, olhando esse projeto me veio algumas dúvidas a mais. :roll:

J

Carol,

de uma olhada nesse esquema

http://dddsample.sourceforge.net/architecture.html

e no livro diz que

’ It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down’

ou seja, a camada de aplicação apenas coordena e delega tarefas dos objetos do domínio.

Ignore essa definição da arquitetura JEE, nesse contexto são assuntos diferentes.

P

Oi,

Uhm… será que você não está pensando em dados quando devia estar pensando em objetos?

Uma combobox ou algo do tipo não exibe dados isolados, ela exibe propriedades de um objeto. Quando você precisa, digamos, listar todos os estados de um país você não deveria fazer algo como:

String[] estados = //algo que faz um "SELECT * FROM ESTADOS WHERE PAIS_ID=123"
for(String estado: estados){
print(estado);
}

Desta forma você está quebrando o encapsulamento do objeto país e quebrando oencapsulamento da sua infra-estrutura de persistência.

Eu recomendo fazer assim:

Pais pais = paises.porId(123);
for(Estado estado : pais.getEstados()){
print(estado);
}

Sim.

Como o Alexa falou, no Capítulo 4 do Domain-Driven Design existe a definição das Camadas propostas pelo Eric Evans:

Os slides do meu workshop de DDD podem ajudar: http://www.slideshare.net/pcalcado/domaindriven-design

S
Olá Philip, esse tópico teria que virar reliquia em algum museu, poxa! rsrsrs, nunca vi um nivel de discussão ser tão profundo, Entretanto queria aproveitar e erguer novamente o tópico. 
Trabalhei com dotnet uns três anos, e algumas práticas de desenvolvimento me inspirei na comunidade java, agora pois tenho quase dois anos que estou trabalhando com a plataforma JAVA, bom chega de conversa e vamos ao assunto. Estive conversanto com meu professor acerca da arquitetura de um projeto que estamos trabalhando um sistema de estoques, segue abaixo as ferramentas tecnologicas, abordagens, padrões..e etc:

PLATAFORMA:
JAVA

LINGUAGEM
JAVA

PARADIGMAS
O.O
MVC

IDE
ECLIPSE

PLUGIN FOR ECLIPSE
JBOSS TOOLS

SGBD:
MYSQL in DEVELOPMENT, POSTGRES in PRODUCTION.

framework’s de base e de extensão
JSF SPECIFICATION SUN (RI) - MORRAJA PROJECT,
RICHFACES EXTENSION
PRMEFACES EXTENSION

METODOLOGIA DE DESENVOLVIMENTO EM EQUIPES
XP+SCRUM

SEGUE ABAIXO A ARQUITETURA:

VIEW-> paginas jsp (não to usando facelets)
CONTROLLER -> classes de controle responsaveis pelo roteamento (muitos codifica regras de negocios nessa camada!)
MODEL-> classes de modelo de dados (os famosos JAVABEAN)
BUSINESS -> classes e interfaces de negocios.
DAO -> classes e interfaces de acesso ao SGBD
DAO.CONNECTION -> classes e interfaces responsaveis em entregar uma conexao funcional para o DAO, nessa camada temos um pool implementado manual, embora os servidores de APP façam isso.

Com base nisso, eu como já tinha estudado bastante sobre padrões, conceitos, abordagens, percebi que essa arquitetura parece uam receita de bolo, bastante difundida em "distributed Applications" com uso das ENTERPRISE JAVA BEANS. Poxa, então vem a pergunta, eu SEBASTIAO FIDENCIO, desenvolvedor, dependendo da situação e do cenario vou usar o PARADIGMA O.O, porque me da possibilidade reuso, relacionar melhor o problema com a solução por meio de abstração, logo é mais fácil abstrair algo que denota o mundo real à artefatos que não fazem menor sentido no segmento de negocio e sim com principio tecnologicos, para construir sistemas aproveitando tudo que é de bom na orientação a objetos, e o que nosssos inlustres…professores ensinam, é modelar sistemas onde minhas classes de dominio é composta por atributos e metodos, e como na prática aplico a arquitetura mencionada anteriormente? Como a maioria dos desenvolvedores tendenciaram a tal prática?

muitos dizem: !ahh mais o framework JSF funciona dessa forma, portanto o meu modelo de classes tem que se adequar ao framework, onde crio minhas classes de modelo com getters e setters, um construtor vazio…e atributos, para preservar o encapsulamento, poxa mais cadê meus métodos de negocio? está separado? O.O não veio para abstrair a complexidade que tinha de modelar sistemas de forma estruturada, onde a mesma em todas fases e ciclos detona o domino do problema? Ou teriamos um corpo sem vida?

O que vejo é que criou se uma nova abordagem chamada DDD. Domain Driven Design, Desenvolvimento dirigido ao ao dominio, é complexo entender isso? eu acho que não. Tudo se resume na prostituição que os padrões J2EE causaram.,. TO’s, V’os… tudo isso pra atender uma especificação. e na verdade o uso dessas classes de dados separadas das classes de negocio eram aplicadas em aplicações N-TIER, porque tendenciou em usar isso até em aplicações N-Layer?

Acho que DDD é uma forma que o Evans encontrou de Mostrar para os desenvolvedores que Orientação Objetos não foi inspirada em padrões J2EE, e que as EJB’s que tentaram se inspirar em O.O e acabou fazendo com que novos analistas e desenvolvedores que surgem a cada dia, aprendem já de forma errada o conceito de O.O. acho que um new(); ou usar um pattern Delegate não denota O.O, mas sim como os objetos usando a inteligencia que está encapsulada em cada um deles interage para realizar os casos de uso.

Se eu seguir a mesma arquitetura que estou seguindo para um projeto em Ruby on Rails ? E eu duvido se não já tem gente por ai,.levando esses costumes mal aprendidos para outras plataformas, eu vim do .NET e conheço N-sistemas que são desenvolvidos dessa forma.

Essa arquitetura acima está ou não totalmente O.O?

Seria correto eu elimiar essa camada de negocio…que pra mim invalida todo conceito de O.O e colocar minhas regras de negocio junto com meus atributos numa mesma classes? ou seja, eu teria a classe Produto.java, ‘nada de BO, VO, e tal’. e dentro dela ficasse todas regras de negocio, dai sim apartir dela eu chamaria meus DAO’s, se fosse o caso, mas poderiamos ser mais coerente colocando um repositorio como fronteira para a camada de persistencia, e uma facade/service como fronteira em direcao aos meus controles e portanto minhas VIEW’???. funcionaria? seria correto eu setar meus componentes GUI…input direto em cada atributo do modelo, a saber que eu iria chamar um metodo gravar e tal metodo estaria na mesma classe onde setei o atributo do input. Então posso fazer isso? ou irei ferir os principios basicos de um JAVABEAN?

O Modelo fica igual bola de basquete…pra cima e pra baixo…um hora ta na VIEW outra hora está persistido!. Mais parece com uma Entidade do banco de dados que À um objeto que deveria prover serviços para quem o chama.

Imagine o objeto carro sem seus seus comportamentos? Eu não consigo nem imaginar ou abstrair a existencia de um carro com comportamento separado de suas caracteristicas, seria um fantasma? Pelo que sei cada objeto possui identidade unica,e nem precisa o Evans dizer isso. porque é notorio e vem desde o principio.

Dai alguem me disse: Bom faz assim "conforme citado acima a arquitetura" que fica mais organizado, facil manutenção, dai eu disse: Poxa mais e o que o Martim Flower disse acerca do Anemic Domain Model,

então ele disse: !ahhh as ideias do Flower meio confusa, não dá pra confiar.

Att
fidencio

D

SEBASTIÃO, eis a minha opinião:

Nossas classes são a “receita” para se construir objetos de um determinado tipo. Objetos que materializam a mesma classe tem o mesmo conjunto de propriedades e métodos. As classes definem propriedades e métodos justamente porque nossos objetos deveriam refletir “indivíduos” do mundo real e consequentemente possuir estado e comportamento.

Agora um exercício de abstração:

Com aquela arquitetura-padrão-j2ee-n-layer pretendia-se antender a uma necessidade de sistemas distribuidos… Compartilhar o estado dos objetos entre máquinas diferentes.

Forçando bastante esse exercício de abstração, pode-se dizer que a união de várias classes-java em camadas diferentes formava uma classe-de-negócio. Por exemplo (simplificado): o conceito Cliente podia ser reproduzido pelo conjunto ClienteBO-ClienteDTO. Eu particularmente nunca gostei disso, mas nem considero uma heresia muito grande, desde que você tenha isso bem claro em mente durante a modelagem.

Essa forma de desenhar sistemas foi absurdamente vulgarizada. É como se houvesse uma solução de caixinha assim: ColoqueONomeDoCasoDeUsoAquiDAO, ColoqueONomeDoCasoDeUsoAquiBO, ColoqueONomeDoCasoDeUsoAquiFacade… Onde você só precisava substituir ColoqueONomeDoCasoDeUsoAqui por Cliente, ou Usuário, ou Projeto, ou qualquer substantivo nascido dos seus requisitos. Desde que você fizesse uma classe de cada camada para cada substantivo, você seria um cara de vanguarda, desenvolvendo soluções OO, portáveis, J2EE, absurdamente escaláveis. Seria convidado para dar palestrar em Nova York e Oslo, e por aí vai.

O grande mérito do DDD, na minha opinião, foi provocar uma “guinada filosófica”, do tipo: “Eu fui contratado para usar J2EE, ou para resolver um problema da melhor forma que eu conseguir?”. Modificou-se o paradigma. Ao invés de se pensar em como resolver o problema que você ainda nem conhece, agora entende-se e modela-se todo o ambiente que envolve o problema antes de se preocupar com questões meramente computacionais.

Quando vocês se desvinvula daquele “Padrão J2EE” você percebe que existem alternativas simples e naturais para resolver as questões computacionais. Por exemplo… As pessoas simplesmente existem no mundo, o mundo não serializa elas em um banco de dados enquanto elas dormem (pelo menos eu acho que não, fiquei bolado agora…). A necessidade de se persistir de alguma forma as pessoas não é natural, mas é bem clara em um modelo computacional. Definiu-se o padrão Repositório, que ajuda a abstrair esse pequeno entrave, fazendo com que lidar com pessoas seja o mais natural possível. A pessoa simplesmente está lá, não interessa ao cerne do problema como elas estão, desde que estejam.

Acho que você não deve, mas até pode usar a modelagem “Padrão J2EE”, desde que seja um ninja da capacidade de abstração.

Se você for um cara normal que nem eu, compre o livro de DDD Evans, o de padrões do Fowler… Estude para caramba. Se você for mesmo normal como eu, a cada vez que você olhar o código, vai identificar uma coisinha que deveria fazer diferente… Por isso você deveria comprar logo o livro de Refactory do Fowler. A partir de um determinando momento o desenvolvimento será natural.

Não acho que seja fundamental seguir o Evans. Acho que o importantíssimo é entender que somos desenvolvedores de software, entendemos de computador e temos que nos esforçar para entender ao máximo o ambiente no qual o nosso produto está inserido. Feito isso devemos nos dar ao direito de refletir, discutir, inventar… que é a parte mais legal do nosso trabalho. Não se preocupe com o que é certo ou errado, tente conhecer todos os pontos de vista, e alinhe-se àquilo que te parece mais simples e natural (no meu caso o que pareceu ser mais simples e natural está descrito no livro do Evans).

Com certeza seria correto, mas várias outras coisas seriam corretas… Estude todas elas para embasar sua opinião, desde que depois você junte estado e comportamento dos elementos do seu domínio naa suas classes de domínio. Use repositórios e não deixe vazar absolutamente nadinha da sua infra de persistência para a camada de domínio, nada significa nada mesmo (nem querys, nem exceptions, nem nada). Agregue suas classes de domínio, e respeite essas agregações, por mais que doa às vezes, há uma razão de ser… e use sempre protetor solar!

Abraço

M

Pessoal, dando uma renascida no tópico novamente!

Gostei muito do modelo proposto pelo Fabio Kung e vim parar nesse tópico:

Fornecedor fornecedor = ;

List contas = dao.carregaContasPagasDesde1999(fornecedor);

Ou:

Fornecedor fornecedor = ;

List contas = fornecedor.getContasPagasDesde1999();

Porém estou enfrentando diversas dificuldades para entender esse cara:

1 - Se eu passar o repositorio no construtor, sempre que instanciar esse cara vou precisar passar esse repositorio? É certo isso mesmo?

Fornecer(FornecedorRepositorio repositorio) {
}

2 - Esse meu objeto fornecedor vai navegar pelo sistema inteiro, certo? Não é estranho minha view poder executar esse método?

Numa outra abordagem, eu li que por exemplo os método store(Fornecedor fornecedor), getAll(), find(Integer id) ficariam no próprio repositório e seriam executadas diretamente pelo controller ou outro objeto de domínio meu.

3 - Não é estranho instanciar esse repositório em outro local e poder chamar o método repositorio.carregaContasPagasDesde1999(fornecedor);

Eu li a respeito de criar esse Fornecedor nao setando sempre o repositorio, porque, nem sempre eu precisarei executar esses metodos, as vezes soh quero exibir os dados na view. Porém, se executar o método sem o repositório daria um null pointer, e não me parece legal utilizar um objeto “incompleto”.

Eu vi o projeto dddsample, porém as entidades dele instanciam os objetos repositorios.

Enfim, alguém utiliza esses caras na prática? DDD + Hibernate e tenha um exemplo pra me ajudar a entender esses caras?

J

Boa noite,

Eu sugiro para você, caso ainda não conheça, estudar o padrão de projeto Facade.

A estrutura ficaria assim:

  • Sua tela, ou talvez seu serviço (Sevlet, WebService, etc.) conhece a camada Facade;
  • A camada Facade conhece as classes de negócio;
  • A camada de negócio conhece a camada DAO.

Tutorial - Padrão Facade:
http://www.devmedia.com.br/o-padrao-facade-aplicado/12683

M

jean.zunino:
Boa noite,

Eu sugiro para você, caso ainda não conheça, estudar o padrão de projeto Facade.

A estrutura ficaria assim:

  • Sua tela, ou talvez seu serviço (Sevlet, WebService, etc.) conhece a camada Facade;
  • A camada Facade conhece as classes de negócio;
  • A camada de negócio conhece a camada DAO.

Tutorial - Padrão Facade:
http://www.devmedia.com.br/o-padrao-facade-aplicado/12683

Mas onde ficam seus java bean? Ele são objetos burros com apenas get e setters? Você chama algum DAO de dentro deles?

Esse é meu maior problema entender como chamar um DAO de dentro de um java bean, e podeis como instanciar esse DAO e etc, como perguntei acima.

Criado 29 de maio de 2007
Ultima resposta 25 de jul. de 2013
Respostas 127
Participantes 41