Como alguns aqui já sabem (ou ao menos me viram no fórum nos últimos dias) estou tentando melhorar minha visão sobre OO para depois começar a me aprofundar mais em designer patters, porque senão vira uma sopa.
Então, por isto, li bastante ontem aqui no fórum e alguns blogs e sites - com destaque pro Fragmental do Phillip, o blog da Caelum e o Search do fórum.
Depois de muito ler, criei um modelo de aplicativo que simplesmente seta uns dados e “persiste-os” num possível database.
Tentei implementar: Repository, evitar os get/set burros, Dao (que não sei se seria bem esse o nome) além da Entidade. Abaixo o código:
Programa de teste
[code]public class TestePessoa {
public static void main(String[] args) {
Pessoa maluco = new Pessoa(“Fulano”,12);
maluco.adiciona(); //persistindo
if(maluco.isMaior()) {
System.out.println(maluco.getNome() + " eh maior de idade");
}else{
System.out.println(maluco.getNome() + " ainda eh menor de idade, coitado =~ ");
}
}
}[/code]
Nele eu usei o construtor da Entidade Pessoa para popular meu objeto com o nome e idade. Depois tento persisti-lo no banco de dados (que não existe) e entao pergunto ao objeto Pessoa se “ele” é maior de idade, ao invés do if(maluco.getIdade() >= 18 ) diretamente no programa teste.
A Interface
public interface PessoaRepository {
public int salva(Pessoa maluco);
}
A Dao que a implementa…
[code]public class PessoaDao implements PessoaRepository {
public int salva(Pessoa maluco) {
System.out.println(maluco.getNome() + " foi persistido no database");
return 1; // seria o id do novo maluco, talvez =)
}
}[/code]
e a entidade…
[code]public class Pessoa {
private String nome;
private int idade;
private PessoaRepository repositorio = null;
public Pessoa() { }
public Pessoa(String nome, int idade) {
this.nome = nome;
this.idade = idade;
}
public void adiciona() {
this.setRepositorio(new PessoaDao()); // veja que eu to passando a PessoaDao como se fosse PessoaRepository
this.repositorio.salva(this); // persiste…
}
public String getNome() {
return this.nome;
}
}[/code]
Agora, gostaria de tirar algumas dúvidas, se for possível…
A partir do momento que a “DAO” implementa o “Repository” e eu na entidade Pessoa.setRepositorio exijo que o parametro seja a Interface, eu estou “codificando para uma interface ao invés de para uma implementação” como muitos dizem ser o mais correto ?
no Pessoa.adiciona, eu passo para o Pessoa.setRepositorio a DAO, uma vez que não posso passar a Interface, pois ela não é algo “concreto”. Essa implementação estaria correta ?
Quanto aos get/setters: eu usei apenas o getNome() pois no programa eu precisaria exibir o nome dele, porém não criei o getIdade. Só que ao “persistir” lá na DAO eu precisaria ter todos os getters para passar ao Statement do DB para ele poder gravar, além de usar boa parte deles para a View. Isso não seria um pecado, ou seria ?
Acho que são “apenas” estes fantasmas que rondam minha cabeça por hora. Se alguém puder comentar algo também, será de grande valia!
Sim. Você está trabalhando com o conceito e não com a implementação, o que geralmente é algo bom.
(dica: por que você precisaria do Repositório dentro da Pessoa?)
Seu objeto pessoa trabalha com o conceito Repositório e não com a implementação DAO. Isso é uma coisa boa mas instanciar a implementação dentro do objeto destrói este desacoplamento. A maneira comum de fazer isto em Java é ter uma terceira entidade que ou é perguntada quando você precisa de uma implementação ou injeta a implementação na sua classe. Nos dois modos sua classe lida apenas com a interface e nunca com a implementação.
Para saber mais procure sobre o padrão Registry e sobre Dependency Injection.
Se você estiver utilizando JDBC ou algum framework mais antigo (ou com uma abordagem diferente) você vai precisar de tais getters. A solução neste caso pode ser tanto ter os getters na classe (dependendo do caso não faz sentido complicar) ou fazer Pessoa ser uma interface que Não expõe o getIdade() mas que é implementada por uma classe que o faz. A solução ideal depende do caso.
Mas a melhor solução seria, certamente, utilizar uma abordagem moderna com Hibernate que não vai te obrigar a fazer estas coisas.
Dica: esqueça Domain-Driven Design por algum tempo e concentre-se em design Orientado a Objetos.
truck1n,
Sua recomendação esclareceu bem a idéia ! DAO não é o fim, é um meio ao que pude entender. Com isso, após a DAO que é uma interface vem sua real implementação seja ela em JDBC, TXT, XML, enfim, a persistência “real”.
pcalcado,
[quote=pcalcado]Sim. Você está trabalhando com o conceito e não com a implementação, o que geralmente é algo bom.
(dica: por que você precisaria do Repositório dentro da Pessoa?)[/quote]
Legal. Menos um fantasma. Mas diga-me, essa “dica” significa que não haveria motivos “reais” para uma Pessoa implementar um Repositório ? Pelo que li à fora, Repository é útil quando você tem uma entidade, no caso Pessoa, persistindo informações em diferentes DAO’s uma vez que cada DAO tem a reponsabilidade de “cuidar” de um meio - database, xml, txt… - e no caso mais especifico de db, cada DAO cuidaria de “uma tabela”, correto ? Ou eu viajei demais nas leituras ? :lol:
Eu li, na verdade passei a manhã toda lendo sobre isto e pensando em possíveis implementações. A Dependency Injection (como abrevia isto ?) pode ser implementada de várias formas: construtor, interface ou injetando via setter. Hum ! Poderia eu também implementar esse “RepositoryImpl” usando uma fábrica, não ?
Só uma coisa não bateu ainda: esse “RepositoryImpl” seria para cada entidade da aplicação, logo, eu teria que ter outra interface para ele. Resumindo: ainda é uma “sopa” para mim. Busquei alguns exemplos, porém, tá complicado digerir essa ponte entre a camada de negócio e a camada de persistência… sequer consegui implementar alguma coisinha no meu “programinha exemplo” que postei lá no começo… alguma sugestão por onde começar ?
Sim. Estou tentando focar em partes para realmente entender as implementações e saber aplicar caso-a-caso, acho que com isso estou fugindo de aplicar padrões as cegas programas à fora, penso eu.
ah sim! Sobre os getters então não há pecado algum. Desde que eles não sejam inúteis, não haverá problema. (y)
Bom… depois de procurar mais infos, montei a seguinte idéia:
Objeto Pessoa tem injetado via setter um RepositorioImpl
RepositorioImpl Repositorio para que tal obedeça o contrato
O repositorioImpl contém as chamadas às Daos Necessárias para fazer a persistência do objeto, ou seja, se para persistir o Objeto Pessoa eu precisar de 2 tabelas distintas + umas configs no XML, eu chamaria 2 ou até 3 implementações de DAO’s para que cada uma delas execute sua tarefa própria que seria mapear o objeto para um sistema relacional (database) e uma outra DAO para persistir dados no XML.
Pelo que entendi de repositório seria isto. Ele abstrai diferentes DAO’s para que a entidade não saiba o que tem por trás daquele repositório.
Por isso que eu disse: esqueça Domain-Driven Design por enquanto e se concetre em design orientado a objetos. Um repositório é algo bem diferente do que você mencionou mas acho que só é possível entender quando se entende a Camada de Negócios.
De qualquer modo, sobre seu exemplo em específico, não há necessidade da pessoa conhecer seu repositório, essa relação não faz parte do domínio e foi criada apenas para facilitar a vida do programador.
[quote=hlegius]Eu li, na verdade passei a manhã toda lendo sobre isto e pensando em possíveis implementações. A Dependency Injection (como abrevia isto ?) pode ser implementada de várias formas: construtor, interface ou injetando via setter. Hum ! Poderia eu também implementar esse “RepositoryImpl” usando uma fábrica, não ?
[/quote]
Um container de dependências é como uma fábrica genérica de objetos.
Vai ser complicado mesmo no início. Você precisa entender melhor como Camadas são organizadas e como objetos são injetados. Como falei, acho que agora é melhor você esquecer Repositórios e começar pelo básico.
[quote=hlegius]Bom… depois de procurar mais infos, montei a seguinte idéia:
Objeto Pessoa tem injetado via setter um RepositorioImpl
RepositorioImpl Repositorio para que tal obedeça o contrato
O repositorioImpl contém as chamadas às Daos Necessárias para fazer a persistência do objeto, ou seja, se para persistir o Objeto Pessoa eu precisar de 2 tabelas distintas + umas configs no XML, eu chamaria 2 ou até 3 implementações de DAO’s para que cada uma delas execute sua tarefa própria que seria mapear o objeto para um sistema relacional (database) e uma outra DAO para persistir dados no XML.
Pelo que entendi de repositório seria isto. Ele abstrai diferentes DAO’s para que a entidade não saiba o que tem por trás daquele repositório.
[/quote]
Não. Um repositório é apenas onde você guarda os objetos, ele não necessariamente abstrai nada. Apesar de mais uma vez recomendar que você esqueça repositórios, um Repositório vai estar ligado com um Aggregate Root e dependendo de como você armazena seus entities e value objects ele pode ou não abstrair seus DAOs.
Para começar, crie aplicações que possuem apenas uma Camada de Serviço usando DAOs para persistir objetos de negócio. Entender Domain-Driven Design sem experiência nisso é difícil porque quase toda a literatura foi criada para pessoas experientes.
Okay! o “design orientado a objetos” que você diz é como a camada de negócios funciona ? Não entendi bem essa definição…
Sim. Depois que vi outros posts aqui no Guj onde você fala sobre a camada de negócios e sua relação com a persistência. Você falava que para a camada de negócios, uma vez em memória para sempre em memória, pois ela não “espera” que vá ser descarregada.
Então você recomenda que eu foque mais na camada de negocios e seu funcionamento, e por hora persista os dados diretamente na camada de negócios ?
Porque a interface é PessoaRepository e a implementação PessoaDAO ?
Se o DAO é o mesmo que um Repositorio use apenas uma das palavras.
public class PessoaDaoImpl implements PessoaDAO
ou
public class PessoaRepositoryImpl implements PessoaRepository
Por outro lado, qual é a responsabilidade de um DAO ?
E qual é a responsabilidade de um Reposiotorio ?
Posso ter um XMLDAO ? E um XMLRepository ?
PessoaDAO e PessoaRepository são o mesmo objeto ? Têm a mesma responsabilidade ? São baseados nos mesmos padrões ?
Pense nisso…
O DAO é um serviço de preservação de dados. Ele media a interação do sistema java com depósitos de dados através do uso de uma ou mais API especificas para esse tipo de deposito. O nome da implementação do DAO está ligado À tencologia que ele usa e/ou ao tipo de deposito que usa. Nomes como XMLDAO (arquivos XML), JDBCDAO (uso de JDBC) , LDAPDAO (usa LDAP) ou DataBaseDAO são válidos.
Vc teria um PessoaDAO e um JDBCPessoaDAO que é a implementação de PessoaDAO que usa JDBC para comunicar com o banco.
Vc pode ter ainda extenções de JDBCPessoaDAO para cada banco de dados. assim teriamos por exemplo OracleJDBCPessoaDAO
e SQLServer2005JDBCPessoaDAO.
O Repositório é um objeto permite aos objetos das entidades encontrarem outros objetos de entidade. Ele são modelados como se fossem coleções de dados com métodos especiais para procurar esses dados. Eles não são desenhados para serem um fachada para a preservação dos dados, mas na prática é util que sejam. Os repositórios funciona para uma certa entidade e são independentes da forma de preservação utilizada. Vc terá um PessoaRepository, mas nunca um XMLRepository porque isso significaria que o seu sistema tem uma entidade chamada XML (poderia, mas é incomum).
Não exatamente. Não apenas como esta camada funciona mas como objetos, em qualquer camada ou mesmo sem camadas, devem ser projetados. Talvez isso ajude a entender:
Sim mas isso não faz com que o objeto precise ter uma instância de seu repositório/DAO dentro dele. Procure ler sobre Service Layer e Façade.
Mais ou menos. Minha recomendação neste caso é que não procure entende Domain-Driven Design sem entender como criar uma aplicação Orientada a Objetos “normal” (i.e. que não usa diretamente os conceitos de DDD)
[quote=sergiotaborda]Por outro lado, qual é a responsabilidade de um DAO ?
E qual é a responsabilidade de um Reposiotorio ? [/quote]
No que pude entender por nas leituras por aí, DAO seria a implementação da persistência, ou seja, o cara que salva em disco nosso objeto - ou como o Shoes disse num post: coloca-os para dormir X)
O repositório ao que entendi é uma interface dessas DAO’s. Ele é único para a entidade (no exemplo Pessoa) e é ele que faz a comunicação com as DAO’s existentes MySQLPessoaDAO, XMLPessoaDAO, etc.
Só que por exemplo: supondo que o objeto Pessoa ao ser persistido, necessite que: seja persistido o objeto no Database e que salve num XML, por exemplo, a hora em que ele foi persistido. São 2 rotinas: database e XML (exemplo beeem irreal, mas só pra constar mesmo). Neste caso surreal, o Repository iria servir “apenas” como uma façade para o XMLPessoaDao e JDBCPessoaDao ? Ou ele executa outra tarefa ? Veja, explico em código rapidinho:
[code]class Pessoa { …
//…
public void salva() {
try {
this.id = RepositoryPessoaImpl.salva(this); // repositório com comportamento estático, acho que é uma saída...
}catch(....
}
//…
[/code]
class RepositoryPessoaImpl implements RepositoryPessoa {
//...
public static int salva(Pessoa maluco) {
// delegaria a JDBCPessoaDao para gravar no banco
// delegaria a XMLPessoaDao a tarefa de gravar o log no XML...
}
Estaria essa idéia sobre o Repository correta, ou não tem nada a vê ? Realmente parece uma pattern simples mas digeri-la não está sendo fácil como as demais que tenho lido =~
Nesta sua explicação você diz que o Repositório permite uma entidade encontrar outra a qual tenha relação. Isso seria algo como: a entidade “Inventario” usa o RepositorioProdutos para localizar Produtos com certas especificações e retornar a coleção desses Produtos para ela ? OU ela usaria o RepositorioInventario e este conectaria-se às interfaces das DAO’s dos Produtos para retornar um Produto[*] ?
Se for isto, a coleção seria “criada” no Repositório e devolvida já montada (num vetor, ou algo do tipo) pronto para o “Inventario”, certo ? Assim eu teria que alterar somente o RepositorioProduto em caso de atualização na entidade Produto, penso.
pcalcado,
É verdade. Eu ainda estou engatinhando nisto. Programar, programo faz um tempinho, mas aprofundar da forma correta em OO estou começando agora, por isso essa dificuldade em pegar as manhas.
Certo. Li a pattern façade e me pareceu bem simples. É uma interface que manipula outras interfaces com o objetivo de simplificar uma rotina. A grosso modo seria algo como eu ter 3 tarefas a seguir em passos, só que ao invés de chamá-las separado, posso “juntá-las” numa façade e rodar apenas um comportamento.
Assim, sendo a pattern repository aplicada como uma façade, eu teria apenas que chamá-la dentro da minha entidade usando o comportamento estático da minha Repository e ela que iria fazer o serviço sujo, apenas me retornando - ou não - algo no fim.
Tranquilo. Estou seguindo em partes como criar uma aplicação “OO pura” para ver e entender ela primeiro para depois entrar nas patterns mais complexas. Step by step X)
Não. Minha sugestão é que você esqueça isso de colocar DAO (tentando sair dos nomes de DDD já que não estamos usando DDD) dentro do objeto e faça algo como isso:
class GerenciadorUsuarios{
pubic void adicionaUsuario(String login, String senha, String nomeGrupo){
Usuario u = new Usuario(login, senha);
Grupo g = daoGrupos.buscaPorNome(nomeGrupo);
g.adiciona(u);
daoUsuario.salva(u);
daoGrupo.salva(g);
}
}
E este código é seu Façade, que é um Service Layer neste caso.
Note que com técnicas e tecnologias mais avançadas que JDBC básico você conseue eliminar algumas partes do exemplo acima.
Caracas ! Ou esse pattern é muito simples e eu tô complicando ou talvez tenha que reconsiderar ir vender dog na esquina =/
aaah! Pera lá. Então esse Domain-Driven Design nada mais é do que essa sopa de nomes para patterns, principios e conceitos relacionados à OO ?
Entendi. Nesse caso seria o básico do básico. Um objeto que comunica com JDBC para persistir e que retorna um ArrayList com os valores pesquisados e lança umas Exceptions em caso de problemas.
Como eu posso diferenciar uma façade que também exerce função de Service Layer de uma façade que é apenas uma façade ?
Aproveitando que você citou a classe GerenciadorUsuarios: é sempre preferível eu ter um objeto que manipula as entidades à que elas mesmas “se auto-manipularem”, correto ? Ou seja, antes eu ter um GerenciadorUsuarios para CRUD à ter os comportamentos de persistência dentro da minha classe Usuario, por exemplo, certo ?
Uma Facade pode ser como voce implementa uma service layer. Outra forma, por exemplo, eh atraves de Commands.
A classe ehe chamada GerenciadorXyz no exemplo porque eu nao conheco seu dominio. O importante no exemplo eh que o ’ gerenciador’ nao executa nenhuma regra de negocio, ele apenas executa o fluxo tira-objecto-do-banco->chama-metodo-de-negocio-no-objeto->coloca-no-banco-o-resultado-da-computacao.
Na verdade estou tentando entender a solução que o Repository podem vim a ajudar a resolver. Talvez por não conhecê-la direito eu esteja direcionando de forma errada minhas perguntas/afirmações sobre. Acho que é esse o problema =/ Talvez até não tenha sentido nenhum usar Repository para um objeto Pessoa (como coloquei no exemplo lá no começo), mas realmente estou tentando entender o básico dela: o que é, para que serve como posso aplicá-la.
Verdade, eu cheguei a ler mas por cima. Li agora com mais calma e pude entender mais sobre o DDD.
Talvez seja esse o motivo que esteja recomendando a mim que esqueça os DDD por hora, não ?
[quote=hlegius]Entendi. Nesse caso seria o básico do básico. Um objeto que comunica com JDBC para persistir e que retorna um ArrayList com os valores pesquisados e lança umas Exceptions em caso de problemas.
Então, estava tentando dizer que o exemplo que você passou seria algo bem simples e sem preocupações com Repository, camada de persistência bem abstraída e etc.; Apenas um “corredor” entre as entidades e a camada de persistência.
[quote=pcalcado]Não. Minha sugestão é que você esqueça isso de colocar DAO (tentando sair dos nomes de DDD já que não estamos usando DDD) dentro do objeto e faça algo como isso:
class GerenciadorUsuarios{
pubic void adicionaUsuario(String login, String senha, String nomeGrupo){
Usuario u = new Usuario(login, senha);
Grupo g = daoGrupos.buscaPorNome(nomeGrupo);
g.adiciona(u);
daoUsuario.salva(u);
daoGrupo.salva(g);
}
}
E este código é seu Façade, que é um Service Layer neste caso.[/quote]
Phillip, tenho três dúvidas a respeito da sua sugestão:
O método adicionaUsuario() recebe apenas dois parâmetros. Qual seria a forma ideal de proceder quando há 15, 20 parâmetros ou mais? Um usuário do GUJ me perguntou isso um tempo desses, e eu sugeri a ele duas coisas: utilizar um Map<String, String> com os nomes dos parâmetros e seus conteúdos, ou projetar uma DSL interna.
Voltando a DDD só um pouquinho ( e sem querer focar exclusivamente nos padrões mas já focando :XD: ), ao invés de chamar o DAO eu poderia, por exemplo, injetar o repositório direto nesse Façade aí né? Ou o uso do repositório é exclusivo da camada de negócios?
O Façade acima compõe a camada de aplicação certo? Seria ele, conceitualmente falando, o mesmo Service de que Eric Evans trata no livro dele?
Sobre estes exemplos espec’ificos leia o Patterns of Enterprise Applications Architecture, de Martin Fowler.
Por ai. Usando a terminologia do artigo, DDD eh uma decisao de 3o nivel mas voce ainda esta com dificuldade no segundo nivel, portanto eh melhor se concentrar nele.
Isso.
o restante deste post nao deveria estar em java basico
Dado que quem chama este facade eh a camada de apresentacao nao teria problema (falando de regra geral, depende do dominio) se esta criasse o objeto usuario e passase este para o Service layer. Acho que no seu exemplo voce teria que criar objetos baseados nos parametros (talvez usando uma Factory que pertence a Camada de Negocios) e passar estes objetos para os servicos.
Este exemplo eh completamente (e propositalmente) nao DDD. Num exemplo DDD voce nao pode ter um conceito de infra-estrutura como DAO sendo usado diretamente por uma classe de negocios. Neste caso -considerando que seu Repositorio seja uma implementado por um DAO JDBC- voce usaria Dependency inversion principle e sim, faria algo injetar o Repositorio.
Exato. lembre-se, entretanto, que Camada de Aplicacao geralmente eh diluida entre Apresentacao e Negocios.
Nao. Os Services do Evans possuem granularidade menor, o Service Layer do exemplo acima cuida de todo o fluxo de uma dada operacao.
Eh muito dificil dar um exemplo de Service sem ter um dominio em mente mas vamos pensar no seguinta: suponha que eu estaj num estacionamento de shopping. Quando o cliente entra de carro neste ele inforam em qual loja ir’a. O sistema guia ele para a vaga disponivel mais proxima daquela loja.
Em pseudo-Java:
class Estacionamento{
public Vaga indicarVaga(Carro carro, Loja loja){
VagaMaisProximaSpecification especificacao = new VagaMaisProximaSpecification(loja);
Vaga vaga = localizadorDevaga.locaziarDeAcordoCom(especificacao);
vaga.reservarPara(carro);
return vaga;
}
}
Note a diferenca entre Estacionamento#indicarvaga() e LocalizadorDeVagas#locaziarDeAcordoCom(). O primeiro 'e um Service Layer , ele executa o fluxo da aplicacao, nao regra de negocio em si. O segundo eh um Service Domain-Driven Design, ele executa regra de negocio.
Opa, pode deixar ! Assim que eu finalizar os Head-first que tenho aqui irei providenciar uma cópia deste do Fowler (o qual é bem falando pelo fórum ao que pude perceber)
Exato. Repare como a herança não está de acordo com o que vc mesmo disse.
O repositorio é único para cada entidade. Se existem várias implementações possiveis, então não é único. Logo, o repositorio não pode ser uma interface. Tem que ser um objeto concreto ( não abstrato, não interface, não estático)
O repositorio comunica com um ou mais DAO. Primeiro, herança não é comunicar. Comunicar significa uma relação de cooperação (de composição). Segundo, se o DAO for a implementação de repositorio então não tem como chamar mais do que um DAO.
Acho que isto já basta para mostrar que o Repositorio é um objeto distinto do DAO. Quando digo distintio quero dizer que um não RepositoryPessoaherda ou implementa o outro. A relação é Reposiotorio—>(1…*) DAO e não Repositorio—|> DAO nem DAO—|>Repositorio
Ele atua realmente como um façade para o DAO. Mais geralmente atual como façade para a camada inferior de preservação ( se existir). Repare que o repositorio gravar em dois daos já é uma coisa que justifica o façade (Que é o padrão para agrupar várias chamadas em uma so). Mas ele executa outas tarefas sim.
A tarefa principal de um repositorio é possibilitar que as instancias das entidades se encontrem e que os serviços encontrem as instâncias das entidades. Ou seja, ele é principalmente um “procurador” (locator). Por isso o respositorio tem um monte de métodos find. O ponto é que os métodos recebem os parametros da pesquisa e não a pesquisa em si.
O Repositório tem que criar um pesquisa no formato que o DAO entende (SQL para bancos, XPath para XML etc… )
No seu exemplo, o repositorio encontra as instancias onde ? no XML ou no banco ? ( ja que ele grava nos dois)
Essa decisão é algo que o Repositorio faz. Ele decide isso , cria a pesquisa, envia ao DAO no formato que ele tende e trabalha os dados de retorno. Um DAO tipicamente retorna algo semelhante a um resultSet ou a um Map. O Repositorio tem que instanciar a classe, preencher com os dados, verificar estados, etc… pode injetar objetos “filhos” etc…
Hoje em dia, um DomainStore é preferivel ao DAO extamente porque ele faz esse serviço chato de instanciação, preenchimento, etc… Ou seja, ele assume o papel e o Repositorio simplesmente delega. Mas o Repositorio ainda tem que criar as pesquisas.
Na real, se usar o Hibernate que é uma implementação de um DomainStore, o Repositorio é onde vc cria os Criteria (ou HQL se quiser…) e envia ao Hibernate.
É isso ai mas sem o static. O Repositorio é um objeto concreto. Mas tome atenção que o codigo salva() em pessoa não é necessário para o Repositorio.
Esse codigo em pessoa é o uso de um outro padrão (ActiveRecord). Vc pode salavar a pessoa simplesmente fazendo
RepositoryPessoaImpl rep = new RepositoryPessoaImpl ();
rep.salva(pessoa);
Como a ideia é que o Repositorio funciona como uma coleção (ou seja, tem estado) vc não vai criar o respositorio cada vez que precisa dele. A sau solução foi usar static, mas isso viola o primeiro objetivo que é ter um objeto concreto e segundo, cria um “objeto global” que é sempre ruim. A solução é usar outro padrão o Registry. Este sim é um objeto com métodos só estáticos que funciona como um Map global com assinaturas especiais. Por exemplo:
Vc pode argumentar que pode incluir este codigo em pessoa e inverter as coisas (pessoa.salva()). É verdade.
Mas eu não recomendo isso. É que com active record qualquer objeto pode mandar salvar a pessoa, mesmo quando não deveria.
O salvar é uma ação protegida por validações e outros processos do sistema que não cabem dentro do objeto pessoa ou do método salvar. Como conceito é legal, mas na prática é ruim se vc quer um sistema com fácil manutenção.( se vc não quiser, ignore o que eu disse…)
Exatamente isso.
Definitivamente não.
Poderiamos ligar o RepositorioInventario ao RepositorioProdutos mas nunca ligar o RepositorioInventario ao DAOProdutos.
O repositorio se liga ao seu proprio DAO. Apenas a ele. Se precisar de entidades diferentes ele se liga ao Repositorio da outra entidade , não ao DAO dela. O DAO é visivel apenas pelo seu proprio Repositorio.
Veja que vc pode ter um mecanismo agnostico como o hibernate que tem a mesma invocação qualquer que seja a entidade, e desse ponto de vista o RepositorioInventário vè a mesma interface do Hibernate que o RepositorioProdutos. Mas isso não significa que deve haver quebre de encapsulamento. Isto porque se , por exemplo, o RepositorioCidade usa o RepositorioEstado que usa um EstadoDAOXML se o RepositorioCidade chamar directamente o EstadoDAOXML terei duas chamadas em lugares diferentes. Ao mudar para EstadoDAOJDBC terei que mudar em dois lugares. Mas se o RepositorioCidade chamar sempre o RepositorioEstado e apenas ele chamar o DAO, não terei problemas em mudar em um lugar apenas. Isto é válido mesmo quando o DAO é agnóstico (é o mesmo para qualquer entidade) ou quando se usa um DomainStore (como o Hibernate) que é agnóstico por construção.
Repito : o repositorio tem a responsabilidade de preservar os dados como e onde quiser. Ninguem pode atropelar esta responsabildiade. Outros objetos do sistema apenas podem invocar o repositorio e nunca os objetos que o repositorio usa. Isso seria uma violação grave do encapsulamento tornando o repositório de fato inutil.
Exatamente
Você entendeu. Agora faça o seu código corresponder às suas palavras. (porque não está… )
[quote=hlegius]Bom… depois de procurar mais infos, montei a seguinte idéia:
Objeto Pessoa tem injetado via setter um RepositorioImpl
RepositorioImpl Repositorio para que tal obedeça o contrato
O repositorioImpl contém as chamadas às Daos Necessárias para fazer a persistência do objeto, ou seja, se para persistir o Objeto Pessoa eu precisar de 2 tabelas distintas + umas configs no XML, eu chamaria 2 ou até 3 implementações de DAO’s para que cada uma delas execute sua tarefa própria que seria mapear o objeto para um sistema relacional (database) e uma outra DAO para persistir dados no XML.
Pelo que entendi de repositório seria isto. Ele abstrai diferentes DAO’s para que a entidade não saiba o que tem por trás daquele repositório.
[/quote]
Sim. É isso mesmo.
O seu problema é que está pensando que “Cada entidade tem o seu repositorio” significa “Cada instancia da entidade tem uma instancia de um repositorio para a classe propria para a entidade”. É isso que é falso.
Imagine um Repositorio assim
[code]public class AbstractRepository {
public abstract List findAll();
}[/code]
Este cara funciona para qualquer entidade E.
Agora pense numa implementação com Hibernate
public class HibernateRepository <E> extends AbstractRepository <E> {
public HibernateRepository (Class<E> type){
this.type = type;
}
public List<E> findAll() {
// cria criterio, executa no hibernate e retorna.
}
}
Esta implementação funciona para qualquer entidade E.
Agora tome atenção no Registro de reposiotorios.
[code]public class RepositoryRegistry {
private RepositoryRegistry (){}
private static final Map<String, Repository> repositories;
public static <E> Repositoy<E> repositorioDe(Class<E> type){
Repositoy<E> rep = repositories.get(type.getName());
if ( rep ==null ){
// cria um repositorio agnostico . poderia invocar um Factory
rep = new HibernateRepository (type);
repositories.put(type.getName(),rep);
}
return rep;
}
}[/code]
Agora vc pode fazer findALL para qualquer entidade do seu sistema e só teve que criar 3 classes.
Se vc entendeu o padrão Repositorio vc irá perguntar: mas e se a minha entidade tem métodos especiais no repositorio?
O registro é um registro porque coisas podem ser registradas nele ( ). Ou seja, no inicio do sistema vc pode
simplesmente registrar um repositorio especifico para um classe de entidade
public <E, R extends AbstractRepository<E> > void addRegistry(Classe<E> type, R repository){
epositories.put(type.getName(),repository);
}
Depois pega da mesma forma e faz um cast para usar os métodos especiais ou simplesmente cria um método no registro que faça o cast por si.
Vc vai ter muito poucas classes e por isso um sistema mais conciso com manutenção mais fácil. Nada de 300 DAO