Repository: seu modelo mais Orientado a Objeto
Postado em 09. jun, 2007 por Fabio Kung em Java
Já tem algum tempo que a excelente discussão no GUJ estava me motivando a escrever a respeito.
Para ambientar, a principal discussão é usar:
Fornecedor fornecedor = ...; List contas = dao.carregaContasPagasDesde1999(fornecedor);
Ou:
Fornecedor fornecedor = ...; List contas = fornecedor.getContasPagasDesde1999()
Já que posts na forma de diálogos costumam ser muito interessantes, aproveito um papo que eu e o Paulo Silveira tivemos.
Paulo: credo, achei horroroso isso da classe de domÃnio acessar o repositório
Paulo: mas fica bonitinha a sentença
Fabio: horroroso pq? vc prefere procedural?
Fabio: repositório é domÃnio tb
Fabio: um List, um Map são repositórios
Fabio: vc acha acessar List e Map horroroso?
Paulo: tem certa razão
Paulo: mas entao poderia chamar o DAO diretamente de repositório
Fabio: em muitos casos poderÃamos
Fabio: eu só estava pensando num jeito legal de injetar
Paulo: desde que o cara não receba os objetos de dominio
Fabio: talvez com interceptor de session, ou listener
Fabio: ou então injeta nos métodos load()
Paulo: então. Complicado um Usuario sempre precisar de Repositorio!
Fabio: todo usuário não
Fabio: só Usuário Managed
Fabio: quando vc dá new num Usuário, vc tb não consegue navegar em relacionamentos
Fabio: só faz sentido pegar relacionamento em managed
Paulo: certo
Paulo: mas olha só
Paulo: vai ter Usuario com repositório e outro sem
Paulo: em alguns vc vai poder chamar o método que faz buscas, em outros não
Fabio: mas isso já é assim
Paulo: não com o dao
Fabio: imagina Usuario @OneToMany Categoria
Paulo: certo
Fabio: vc só consegue chamar usuario.getCategorias() no managed, mesma coisa
Fabio: só vai poder chamar usuario.getCategoriasEspeciais() no managed
Fabio: não adianta dar new Usuario().getCategoriasEspecias();
Paulo: hum… entendi! Podia ser um interceptor como fizemos no caelumweb
Paulo: aà ele setava um atributo privado
Fabio: Ou então o próprio load do dao/repository pode fazer isso.
Paulo: mas sei la, baita arquiteturazinha complicada
Fabio: nada! só injetar o repositório
Fabio: o resto é simples
Fabio: em vez de chamar no dao, que é procedural, chama via getter
Paulo: não não, você tem razão. É facÃlimo de implementar
Paulo: mas tipo, é muita coisa
Fabio: muita coisa do jeito que estão falando no tópico do GUJ! 500 camadas…
Fabio: Repository não precisa nem ser interface
Paulo: aquele interceptador que fizemos para gravar no lucene já não gosto muuuuito
Fabio: Repository pode ter referência para Session
Fabio: e não precisa injetar o repositorio na entidade com listener/interceptor
Fabio: poderia ser:
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);
}
}
Fabio: ou seja, na hora que você recupera uma Entidade managed, ela já vem com o repositório embutido…
Paulo: dessa maneira dá um pouco mais de responsabilidade para os beanzinhos entidades né? fica legal
Fabio: isso!
Paulo: proximo projeto vamos tentar essa abordagem?
Fabio: demorou… ![]()
Fabio: hoje em dia, se vc quiser mostrar um objeto e alguma pesquisa personalizada, vc tem que consultar o objeto e a lista nas lógicas
Fabio: separados! E aà ejetar os dois
Fabio: muito feio
Fabio: geralmente faz-se isso (código usando algum controlador ruinzinho):
public class Logica { // extends Action?
public void mostraFornecedorEContasPagas() {
Long id = request.getParameter("id"); // século passado...
Fornecedor f = fornecedorDAO.load(id)
List<Conta> contasPagas = contasDAO.listaContasPagasDoMes(fornecedor);
// ejeta tudo para mostrar na view. No século passado seria:
request.setAttribute("fornecedor", fornecedor);
request.setAttribute("contasPagas", contasPagas);
}
}
Fabio: MUITO procedural!
Paulo: cara se aplicarmos essas idéias, com velocity isso ia ficar ANIMAL
Paulo: Ia dar para chamar os métodos a la DAO direto no beanzinho
Fabio: ISSO!
Paulo: #foreach contas in contas.desde(1994)
Fabio: é meu, legal né?
Fabio: com JSP EL dá tb
Paulo: mais ou menos, teriamos de mexer nos evaluators
Fabio: não, soh usar padrão javabean
Fabio: ahhh vc quer passar parâmetro, aà EL não rola mesmo
Fabio: mas é puro DDD, já fiquei pensando bastante sobre o assunto
Fabio: ultimamente que tenho enxergado um jeito legal de aplicar
Paulo: bacana
Paulo: acho q vale a gente testar
Paulo: parava de ficar enfiando getters para expor as coisas para view.
Paulo: FABIO TODO: blogar sobre isso
Feito!
Fabio Kung
24 Respostas para “Repository: seu modelo mais Orientado a Objeto”
Trackbacks/Pingbacks
-
-
junho 10, 2007
[...] posts em forma de diálogos estão se tornando moda (1 e 2) e como eu não tenho tido muito tempo para escrever decentemente sobre coisas que eu gosto, então [...]
-
-
novembro 12, 2007
[...] about Repositories. I’m from Brazil and we have discussed it many times here (see at GUJ and at my post in the Caelum Blog – unfortunately – in pt-BR; perhaps, translation tools can help). I have a personal and pragmatic [...]
-
-
janeiro 28, 2008
[...] Perceba que esta classe implementa uma interface, está interface implementa o pattern Repository, este padrão já causou muita polêmica em forums Java como o GUJ por exemplo, recomendo a leitura deste post para entender o padrão: http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/ [...]
-
-
janeiro 29, 2008
[...] http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/ [...]
-
-
julho 16, 2008
[...] Perceba que esta classe implementa uma interface, está interface implementa o pattern Repository, este padrão já causou muita polêmica em forums Java como o GUJ por exemplo, recomendo a leitura deste post para entender o padrão: http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/ [...]
-
-
janeiro 13, 2009
[...] Perceba que esta classe implementa uma interface, está interface implementa o pattern Repository, este padrão já causou muita polêmica em forums Java como o GUJ por exemplo, recomendo a leitura deste post para entender o padrão: http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/ [...]
-
-
outubro 2, 2009
[...] é um assunto onde há sempre mais um “ponto” a acrescentar. Motivados pelo excelente post da Caelum e discussão do GUJ (onde ambos não são tão recentes assim), eu e o Eduardo Amuri discutimos [...]
-
-
fevereiro 24, 2010
[...] estava injetada em objetos de modelo na sessao web. Isto é, são sessões usadas pelos nossos Repositories, que faz todo o sentido para o projeto e não é um memory leak, pois a sessão que era [...]
-
-
março 31, 2010
[...] é um assunto onde há sempre mais um “ponto” a acrescentar. Motivados pelo excelente post da Caelum e discussão do GUJ (onde ambos não são tão recentes assim), eu e o Eduardo Amuri discutimos [...]
-
-
março 31, 2010
[...] Eu achei os seguintes links relacionados ao assunto mas ainda não adotei uma solução. Estou pensando nos pontos positivos e negativos de cada uma das opções. Component Aggregates About Repositories Comments to Gavin King about DDD and Repositories Repository Pattern vs. Transparent Persistence Repository: seu modelo mais Orientado a Objeto [...]
-
-
abril 4, 2010
[...] Para saber mais a respeito do conceito por trás desta solução, leia este POST [...]
-
-
fevereiro 13, 2012
[...] um BO para alterar o VO e persistir usando o DAO no MYSQL ou “salvar cliente  no repositório de cadastros“? Compartilhar [...]
ASSINE NOSSO RSS




xebe
13. jun, 2007
Fabio, excelente este post.
Como ficaria sua classe Fornecedor seguindo este seu modelo?
Obrigado.
Daniel Souza
14. jun, 2007
é, gostaria de saber tbm
como ficaria Fornecedor ??
Fabio Kung
15. jun, 2007
Recomendo que vocês leiam o tópico do guj (link no começo deste post) na integra. Tem várias alternativas de como ficaria o Fornecedor. Uma alternativa poderia ser:
getContasDesde(Date date) {
public class Fornecedor {
private final FornecedorRepository repo;
public Fornecedor(FornecedorRepository repo) {
this.repo = repo;
}
public List
return repo.getContas(this, date);
}
}
Eu sei que é simplista demais. Esse é apenas um dos jeitos.
Felipe Regalgo
21. jun, 2007
E se eu quisesse obter uma lista de todos os Fornecedores do sistema??
esse metodo ficaria dentro da classe Fornecedor?? tipo:
public class Fornecedor {
private final FornecedorRepository repo;
public Fornecedor(FornecedorRepository repo) {
this.repo = repo;
}
public List getTodosFornecedores() {
return repo.getTodosFornecedores();
}
}
vc não acha melhor que essa funcionalidade não exista na classe Fornecedor e seja acessada chamando diretamente do repositorio (que faz parte do dominio)? por exemplo:
fornecedorRepository.getTodosFornecedores();
ao inves de
fornecedor.getTodosFornecedores();
a final de contas estamos querendo saber uma informação especifica de todos os fornecedores, e não daquele especifico!!!
VAleu,
e parabéns pelo post
Paulo Silveira
21. jun, 2007
Felipe, ai voce usa o dao mesmo. Esse esquema é para deixar o objeto mais poderoso e com mais responsabilidade, mas nao faz sentido colocar nele um método de instância com cheiro de estático….
Fabio Kung
21. jun, 2007
Boa Felipe,
Essa é a velha discussão sobre ActiveRecord x DataMapper, mas nesse caso (e em Java) eu faria repository.getTodosFornecedores().
Alexandre F. da Silva [afsrj]
21. jul, 2007
Eu gostei e nao gostei.
So vale se for para o mesmo objeto(instância, this!) se for pra trazer coisas do tipo, fornecedor.getContasPagar() trazer de uma outra instância porque voce permitiu no conta a pagar pegar o getId, e liberou o acesso do setId ao inves de ser pelo construtor.
Juro que vomitaria!
Leila
30. jan, 2008
Boa sorte Juliano! vai em frente! vc é um cara de futuro ainda! hehehehe
Emerson Moretto
12. fev, 2008
Eae Fabin!!
parabéns pelo post cara!! Excelente! Ultimamente estive lendo o livro DDD do Eric Evans… e esse seu tópico veio a complementar muita coisa… talvez não tenha resolvido meus problemas, mas provavelmente tenha me trazido mais dúvida rsrsrs! (e isso é muito bom!)
Estou implementando um projeto lá no LSI dessa forma que você sugeriu.. ou pelo menos uma tentativa do repositório injetado automaticamente ao entrar no estado “managed”.
mais uma vez, parabéns!! você ta cada vez mais prodÃgio!! rsrsr
abraços
Dirceu
16. set, 2008
Eu até agora não sei o que é exatamente um Repositório.
Seria uma espécie de ligação entre o DAO na camada de persistência e o domÃnio?? E não tenho a menor idéia de para que ele serve!
Rômulo
21. jul, 2009
E se eu tiver 2 implementações para o DAO (JDBC e Hibernate) mas quiser isolá-las usando o Repository, ficando assim transaparente para o cliente, como faria para que minha aplicação tivesse esse suporte?
Eu consigo fazer uma interface em comum para os dois, mas na hora de injetar como faria para dar suporte as 2 implementações? Porque no meu caso é possÃvel que o cliente prefira usar, em algum momento, o JDBC porém o padrão seria Hibernate.
Rômulo Augusto
08. jul, 2011
Tópico antigo, mas tenho uma pergunta que não vi nos comentários:
O que você acha de também, além do construtor, um método especÃfico receber um repositório como parâmetro?
Por exemplo, para o caso do fornecedor:
forncedor.getConstasDesde(1994, fornecedores);
onde “fornecedores” seria o repositório.
Isso seria legal para o caso em que o Hibernate cria os objetos Fornecedor. Assim não me preocuparia em alguma forma de injetar nessa criação.
O que acham?