Factory para persistir classe adequadas ou existe outra partner para isso

Sérgio:

um metodo lista() de um DAO retorna o q? Object[]?

[quote=fabiocsi]Sérgio:

um metodo lista() de um DAO retorna o q? Object[]?

[/quote]

Vc que sabe, vc que define a API do DAO. Object será meio chato.
A API do DAO tem que ser tal que sua interface possa ser implementada com várias API sujacentes, já que o DAO,
na realidade é um Adapter ( ele transforma a interface uma API na interface de outrao API) só que ele mesmo define a API final.

A minha sugestão seria devolver algo como RecordSet ou RecordList , sendo estes coleções de Record que contém um conjunto de campos e valores.

Entao eu realmente estou implementando o DAO de forma errada, pq ele conhece os objetos de dominio e eu nao conseguiria usar os mesmos DAOs em aplicacoes tao diferentes qto as q vc citou.

Eu tenho uma interfaceDAO q retorna, por exemplo, um objeto Venda. Eu posso mudar de banco de dados qtas vezes eu quiser apenas acrescentandos novas implementacoes a essa interface. Mas eu nao consigo reutiliza-las com outras regras de negocio, num outro dominio, vou precisar de outros DAOs.

Se vc puder me dar algum exemplo do q vc diz pq eu nao consegui ainda visualisar bem (a nao ser fazendo typecasts pra todo lado, mas ai vale a pena?).

Na pagina da Sun em q descreve o Pattern DAO eu encontrei la pelas tantas:

public interface CustomerDAO{

public int insertCustomer(…);
public boolean deleteCustomer(…);
public Customer findCustomer(…);

}

Repare como na propria documentacao do Pattern a interface retorna um objeto do dominio.

Velhas discussões em novos tópicos.

Que tal estudar os exemplos do Hibernate/JBoss (se é que estão usando uma boa ferramenta ORM)!? :roll:

Veja, não ha nada de errado com os objetos que vc usa. Apenas eles não são implementações do padrão DAO e sim do Repository.
Não significa que vc tem que mudar seu sistema. Apenas os nomes das classes :lol:

Pois, so que esse objecto é na realidade um DTO. Ou , no minimo, não segue DDD E ai que a coisa se complica.
Objetos de domino todos são. Afinas suas regras, interfaces e estados dependem do dominio. Ninguem saria Pedido e ItemPedido
num sistema de banco. Sejam eles DTO, Entity , Aggregation ou qq outro padrão. No fim, não importa.

O dilema aprece se queremos misturar os conceitod de DDD com as práticas e tecnologias actuais da Sun.
Não ha no mercado - até onde sei - uma implementação genecia do DAO. Aliás se houvesse isso
seria quase um contrasenso.
O que temos sõa frameworks que usar objetos dos dominio como se fossem DTO e vendem a ideia de
que porque esses objetos têm metodos que atuam sobre o estado do objeto, então esses objetos são objetos de dominio completos e sem
nenhum problema. Ora isso não é verdade. Muito já se falou do problema do JPA/Hibernate não funcionar “out-of-the-box” em ambiente distribuido
Os famosos detached (ou melhor un-managed) são objetos verdadeiramente de dominio , independentes da persistencia, que esses framewrks tem problemas em tratar.

Não ha problema em usar essas tecnologias se é isso que realmente se precisa e quer, mas é importante saber o que elas são e que trade-offs fazem.
Acho que ninguem espera um JPA para XML … em tese poderia existir, mas não é isso que está na cabeça da pessoa ao pensar em JPA. Pensa-se me SQL e banco de dados. A prova é que vc define queries em quase-SQL , não em quase-XPath

Também é verdade que sistemas persistidos em outra coisa que não em banco não são muito levados a serio e portanto o esforço de criar uma api hipergenerica de DAO não é compensador. Mas falávamos de padrões e nao de tecnologias.
Agora qe vc entendeu o padrão e as diferenças subtis entre eles ao menos não vai achar que DAO genérico é algo que usa hibernate.

Ainda sobe outro ponto de vista tem o problema do DDD. NA superficie DDD é muito legal. Mas DDD acaba por ser uma filosofia , uma forma de vc encarar seus objetos e suas responsabilidades, mas não é um padrão tecnologico.
Ele não ele diz como implementar os objetos. Mas ele diz como os construir.

É aqui que mora o problema. Se a construção depende das relações de agregação, composição e associação entre as entidades e logo, entre as classes, e isso é modelado de alguma forma no dominio. Como?
Quando DDD nasceu annotations ainda não eram comuns. Portanto a responsabilidade de donhecer os metadaos tinha que estar em algum objeto : o repositorio.

Essa informação é o que o sistema de persistencia precisa para o seu trabalho. E na forma de metadados embutidos , que são as anotações eles funcionam. Mesmo com os metados em xml ou noutro formato. O ponto é que o ORM precisa de metadados, o Repositorio não.

O repositorio com várias estratégias como no modelo do Fowler pode ser uma utopia em sistemas do dia-a-dia, e o repositorio eu-faço-tudo poderá ser um opção mais válida. Sobretudo usando hibernate. O ponto, que espero que seja claro é que não dá para ter as duas coisas, e é necessário fazer escolhas.

YvGa se o seu sistema está rodando com DAO dessa forma otimo. Apenas declare que está seguindo o padrão da Sun , que parece usar objetos de dominio e que não está usando DDD. É só uma questão de por as coisas em contexto. Algum vai dizer que DAO é do passado ,mas vc saberá no fundo que aquilo é um repostório que usa o nome trocado… e que nunca funcionará para outra persistencia que não Banco de Dados. Precisaria ? :wink:

Em qual referência “DDD” esta descrito que DAO não pode retornar objetos de negócio Sergio?
DAO na maioria de vezes é um gerenciador de entidades persistentes que utiliza DataMapper, portanto pode sim retornar objetos de negócio (eu disse na maioria das vezes).

O Repository é uma abstração disso, podendo utilizar DAOs para atender uma determinada ação de negócio.

Um Client de um DAO deve ser um Repository …

[quote=Lezinho]Em qual referência “DDD” esta descrito que DAO não pode retornar objetos de negócio Sergio?
[/quote]

Em qual referencia de DDD está escrito que se deve usar DAO ? Onde o padrão DAO é mensionado ?

E se o DAO pode retornar objetos do dominio porque ele não é um objeto do dominio? E se ele é um objeto de dominio que retorna objetos de dominio qual o papel do Repository (que é mencionado explicitamente várias vezes) ?

Pra mim, o padrão é implícito toda vez que a junção dos padrões Query Object e DataMapper é utilizado, mas se não quiser cunhar como DAO pode chamar de DataMapper + QueryObject. Contudo, a essência destes padrões é encapsular o acesso ao dados (por isso cunho como DAO), e não realizar lógica de negócio.

Ele não é um objeto de domínio pq é apenas um Helper de acesso a dados, não executa lógica alguma e não tem valor ao modelo. Portanto ele não é um objeto de domínio, e por isso existe o Repository.

Repository pode executar instruções relacionadas ao negócio, pq faz parte dele. Provavelmente, para que esta consulta ocorra, ele deve solicitar a um ou vários DAOs (DataMappers + Query Objects) a tradução do serviço.

Mas eu entendo o que você vem dizendo Sergio de uma implementação onde a interface de um repository seja implementado diretamente por um JPA ou Hibernate da vida, entendo porém não apoio. Acredito ser mais interessante a implementação de um repository ter por composição um ou mais DAOs injetados e o Repository fazer uso deles, sem saber se esta trabalhando com EntityManager, Session ou qualquer coisa do gênero.

… IMHO.

[quote=Lezinho]Pra mim, o padrão é implícito toda vez que a junção dos padrões Query Object e DataMapper é utilizado, mas se não quiser cunhar como DAO pode chamar de DataMapper + QueryObject. Contudo, a essência destes padrões é emcapsular o acesso ao dados (por isso cunho como DAO), e não realizar lógica de négócio.
[/quote]

Humm… Repository tb é um DataMapper (Afinal criar um aggregado é um mapeamento) e tb pode usar QueryObject , contudo não é um DAO.

Eu não estou defendendo que se use o Repository como uma casca para o JPA/Hibernate.
O que eu estou dizendo é que em vez de usar um DAO (que encapsula o acesso a dados) vc pode não encapsular e acessar a API de dados diretamente no Repository. Ou seja, se fosse o JDBC vc pode escolher usar
Repository -> JDBC ou Repository -> DAO -> JDBC.

O Eric o Fowler usam o termo (Repository)Strategy para se referirem às várias formas de acessar os dados

Mas isso é apenas um adjetivo para DAO. Como falei. O termo "DAO" nunca é usado no texto.
Ele diz ainda o seguinte:

O que significa que o Repository é além de objeto de dominio, objeto de estrutura.
É o que acontece se usar JPA ou Hibernate directamente nele. Mas usando o DAO/Strategy isola a dependência da estrutura, o que eu acho mais limpo.

[size=9]Corrigidos os creditos da citações[/size]

É exatamente o que faço quando opto por utilizar composição na implementação de meu Repository (injetando o DAO como atributo). A Strategy é a interface DAO injetada como atributo do meu repository, o encapsulamento de acesso fica neste DAO, assim como vc lembrou na citação.

[quote=sergiotaborda]

O que significa que o Repository é além de objeto de dominio, objeto de estrutura.[/quote]

Não, o que a citação diz é que o Repository [B]PODE[/B] conter os detalhes da infraestrutura, não que DEVE conter. Como eu disse anteriormente, eu acho que a primeira citação mencionada, usando uma Strategy, mais adequada.

Se eu tenho como Strategy uma interface de DAO, logo ele pode sim retornar uma entidade que representa um objeto de domínio para meu repository, como disse em meu primeiro posto neste tópico.

PS: Quem escreveu Domain-Driven Design Quickly não foi Eric Vans, mas sim Avram e Marinescu.

Só é um DataMapper se ele possuir os códigos de infraestrutura da ponte Objeto / Relacional, se não ele apenas faz uso de um DataMapper. Ele não realiza mapeamento de camadas, alguém realiza pra ele.

É exatamente o que faço quando opto por utilizar composição na implementação de meu Repository (injetando o DAO como atributo). A Strategy é a interface DAO injetada como atributo do meu repository, o encapsulamento de acesso fica neste DAO, assim como vc lembrou na citação.
[/quote]

Estamos todos de acordo então.

[quote]

Estamos de acordo tb. Me expressei mal. Eu queria dizer : “O que significa que o Repositorio que conem informações de de infraestrututra é alem de objeto de dominio, objeto de estrutura”

Bom, é ai que discordamos. Se olhar bem a definição da responsabilidade do repositorio é encontrar e criar os agregados. Ele é como um cache que cria o objeto apartir da persistencia quando não o acha “em memoria”.
Essa criação é ajudada por Factories. Mas a logica é contida no Repositorio. Ou seja, o Repositorio é o cara que sabe montas os legos que são os objetos das entidades e seus respectivos value-objects.
Um exemplo simples: A conta tem um saldo. Esse saldo é calculado fazendo um sum() dos movimentos. No banco isso é a soma de uma coluna numerica. O repositorio traz isso facilmente do banco usando um select sum() etc… Mas o meu modelo não usa numeros sem unidades e todas as quantidades monetárias são inseridas num value object Money. O repositorio é o cara que sabe esta regra e sabe como contruir esse objeto. Money não é persistente e é um Value Object do dominio


// no repositorio de conta

public Conta find(AccountNumber number){

     BigDecimal saldo = // operação com dao que retorna um numero

     Conta conta = ContaFactory.createNew();

     conta.saldo = new Money ( saldo , "BRL");

}

Isto é um exemplo tosco para é só para mostrar que o DAO não tem como saber a moeda em que o saldo é ditado, nem que o saldo é na realidade um Money. Outros Value Objects mais complexos encontrados dos livro deixam mais clara o papel do repositorio. O Strategy/DAO só tras dados brutos, é o Repositorio que os intrepreta.
(a moeda poderia ser ainda lida de uma tabela setup ou de uma outra entidade)

Se o DAO souber tudo isto, ele contém logica de dominio. E isso, acho que concordamos, é uma violação do padrão DAO.

O q particularmente eu acho muito mais intuitivo, tirando do repositorio a responsabilidade de fazer o mapeamento. Dessa maneira ele soh delega e continuara delegando seja qual for a infraestrutura q eu venha a adotar.

Em um dos posts o Sergio disse q eu deveria usar diretamente o Hibernate com o repositorios “pulando” o DAO. Eu discordo, ou prefiro nao fazer assim, pq um dia eu posso mudar minha ferramenta de persistencia e entao terei q mudar toda a implementacao dos repositorios (fechado para modificacoes, aberto para extensoes).

Vc vai dizer tbm q nao se deve lidar hj com o q pode vir um dia. Mas nao ha nada mais propenso a mudancas do q uma ferramenta de terceiros, q pode ser superada por outra (em custo, implementacao, qualidade etc…) a qualquer momento.

[quote=sergiotaborda]
Se o DAO souber tudo isto, ele contém logica de dominio. E isso, acho que concordamos, é uma violação do padrão DAO.[/quote]

Qual a necessidade de ter DAO entao? No meu modo de ver sao eles podem ser os responsaveis pela construcao dos objetos e entrega-los aos repositorios ja em estado valido. (Nao q os repositorios nao possam eles mesmos fazer isso), mas como ja disse antes - particularmente prefiro q os DAOs facam.

Tbm discordo Sergio qdo vc diz q os DAOs nao devem conhecer os objetos de dominio, eles fazem parte da camada de persistencia q pode perfeitamente conhecer a camada de dominio - o contrario eh q nao eh aconselhavel. O q nao pode realmente e a persistencia conter logica de dominio, mas transformar algumas linhas de tabelas num banco de dados num objeto na memorio em estado valido nao eh regra de dominio, mas funcao propria da camada de persistencia.

Ok Sérgio, porém você há de concordar comigo que nem tudo é Aggregate. Muitas vezes uma entidade é genuinamente completa.

Bom, acho que nos entendemos.

YvGa, os DAOs podem devolver objetos de domínio (mas tendo como cliente o repositório), desde que estes não sofram transformações como no caso de Aggregates.

A) Repository como um Mapper

Faltou esclarecer este ponto. No codigo de exemplo que dei, o Repositorio está mapeando dados brutos do DAO para objetos Entity. É por isso que ele é um mapper. Quando for dado um store(Conta) o repositorio tem que obter os dados brutos a partir do entity e passar ao DAO.

B) Dever usar Hibernate no Repositorio

Eu nunca disse que devia fazer isso. Eu disse que podia. Aliás todo o meu argumento é que vc deve ter um DAO totalmente separado das reponsabildiades do repositorio. Mas isso não é uma condição sin qua non para usar DDD.
Pode , pode , usar a api de persistencia directamente no repositorio. Acho que concordados que isso é ruim, embora possivel e viável em sistemas que não precisa usar outra coisa que nao DB.
Eu defendo exatamente o total desacoplamento do DAO do dominio e o uso do Repositorio de DAO como estratégias para acesar aos dados (padrão Strategy).

C) Qual a necessidade de ter DAO entao?

Poder mudar a persistência a gosto. Sem mudar uma virgula ( um ponto-e-virgula) do codigo do dominio. Aliás, mudando apenas um properties qq.

D)Os DAOs nao devem conhecer os objetos de dominio

Se os DAOs conhecem os objetos eles não podem ser usados noutro domínio contrariando o objetivo descrito em C. Um DAO cuja assinatura seja Cliente find(id) não é universal. Obrigaria a definir uma interface DAO para cada Entity o que é absurdo. Bastaria T find(Class entityclass, Object key). Que à primeira vista não viola nada.
Eu posso até viver com isso. O problema não é esse. São os metadados.

A camada de cima pode conhecer a de baixo, mas não ao contrario. A persistencia não pode conhecer o dominio.
O Hibernate não conhece o dominio já que usa reflection. Mas um dao do tipo Cliente find(id) depende do dominio. Contudo o hibernate precisa ser informado do meta-modelo do dominio (as relações)

E) nem tudo é Aggregate

Certo. Para esses casos vc usa um Repositorio padrão com operações padrão do tipo “pega dados ,cria objeto, insere dados no objeto, retorna objeto”. Se o DAO já faz isso, ok, mas se uma implementação do DAO faz isso , TODAS as outras terão que fazer tb. Cria-se um contrato implicito no DAO que não é a sua responsabilidade.
Se é um agregate, sobreescrevam-se os metodos corretos do repositorio generico e pronto.

O que não faz sentido:
Ter um repositorio que é delegador para o DAO porque o DAO faz-tudo.
Ter um repositorio que faz tudo e um o DAO que não faz nada sem ser delegar para outra API.

DataMapper é uma extensão de Mapper. O respositório pode até assumir um papel de Mapper ao modelar um Aggregate, mas de um DataMapper seria bizarrise.

No mais é isso mesmo Sérgio, concordo com os pontos colocados. Não é errado ter uma interface DAO para cada entidade de ORM, mas também não acho que isso tenha um cheiro bom. Em minhas implementações, utilizo BaseDao, fornecendo implementações dos gerenciadores das entidades deixando isso transparente ao repositório.

color=oliveembora, contudo, porém, pra ser sincero,(…) o DataMapper pode resolver na maioria dos casos Aggregates, pelo menos nos casos onde trabalhei.[/color]” :twisted: