Repository pattern em DDD e métodos na prática

Pessoal, seguinte… Estou estudando a implementação do DDD (Domian Driver Design) e o padrão Repository.

Contudo, não entendi muito bem uma coisa e peço a ajuda de quem tenha mais experiencia nisso.

Nos exemplos práticos de implementação de repository que tenho visto, vejo que as pessoas geralmente implementam os métodos:

find()
Load()
save() ou store()…

Porém, dois métodos que considero cruciais em CRUD’s não estão aí… São eles update() e remove().

Se no client, tenho uma chamada para trocar o conteúdo antigo de uma entidade por um novo valor, como fazê-lo se não tenho um método update() ?

E como indicar aos meus DAO’s que quero remover determinada entidade ?

Estive pensando em implementar esses métodos no repositório assim:

public boolean update(Object oldEntity, Object newEntity);
public boolean remove(Object entity);

Alguém vê algum destoamento com o modelo DDD aqui e poderia me ajudar a entender?

Agradeço desde já.

MWAdriano,

Sim utilize DDD, tente colocar o maior número possível de métodos e listas em uma única classe. Uma classe não pode ter menos de 1000 linhas, isso significa que o conceito não foi bem aplicado. Depois disso, tente fazer um relatório com sacolas ou fazer manutenção. Vai ver a gororoba que fica.

Eu estou fazendo uma manutenção em um sistema exatamente assim, um macarrão. To tentando passar um email pro Eric Evans, de repente ele ajuda.

Adriano,

DDD não é uma receita de bolo que devemos segui-lá sem analisar o nosso cenário. No seu cenário, seu repository precisa de um método ADD e outro UPDATE? Se sim, manda bala em implementá-los, não há problema algum.

Uma dica é: entenda bem o Pattern Aggregate. Teoricamente, um Repository deve existir para o agregado raiz, os objetos "internos" dele podem/devem ser persistidos, alterados diretamente pelo raiz. Exemplo:

Supondo que no seu cenário o agregado raiz seja um objeto Cliente. Seu sistema também controla os Pedidos, que no caso pertencem à um cliente, assim sendo, Pedidos fica dentro de Clientes.

Clientes --(faz pedido)—> Pedido

Para persistir o Pedido, você não precisa, e na minha opinião não deve, ter um repositorio para Pedidos, pois você simplesmete faria "clientes.addPedido(pedido)".

Com Hibernate, teriamos um código assim mais ou menos

public void addPedido(Integer idCliente, Pedido pedido) {
  //Recupera o cliente previamente cadastrado
  Cliente cliente = clienteRepository.findById(idCliente); //Aqui o cliente estará gerenciado pelo Hibernate, ou seja, qualquer mudança será refletida em algum momento no BD"
  cliente.addPedido(pedido); //O mesmo de cima. em algum momento seu pedido será inserido na base de dados
}

Note que no exemplo acima existe um repository apenas para o objeto agregato raiz.

Em alguns exemplos mais "radicais", você pode ter, como exemplo, objeto raiz SISTEMA, que tem apenas 1 valor que foi previamente inserido via INSERT direto na base de dados. Nesse caso, o sistema.addCliente, sistema.addProdutos, sistema.findClienteById().addPedido() e por ai vai.

Isso é só uma dica. Espero que tenha ajudado

[quote=Jair Rillo Junior]Adriano,

DDD não é uma receita de bolo que devemos segui-lá sem analisar o nosso cenário[/quote]

Adriano,

extamente, os padrões e as metodologias devem ser bem analisadas e estudadas antes da implementação e utilização, o problema é que isso nunca acontece. Brotou no mercado já era, vira crime se não usar. vira chato se tentar entender como funciona. Apareceu na revista, apareceu no cursinho, virou lei.

Vem aqui fazer manutenção na gororoba que to mexendo, tá com DDD. É de mercado, todo mundo usa.

[quote=rwolosker]MWAdriano,

Sim utilize DDD, tente colocar o maior número possível de métodos e listas em uma única classe. Uma classe não pode ter menos de 1000 linhas, isso significa que o conceito não foi bem aplicado. Depois disso, tente fazer um relatório com sacolas ou fazer manutenção. Vai ver a gororoba que fica.

Eu estou fazendo uma manutenção em um sistema exatamente assim, um macarrão. To tentando passar um email pro Eric Evans, de repente ele ajuda.

[/quote]

Ta dificil entender o que voce esta querendo dizer, mas se o que voce diz eh q viu algo assim e o pretexto era o DDD, a pessoa que diz q isso eh DDD nao sabe o que esta falando. DDD simplifica e nao complica. Agora, se o cara conhece DDD por blogs e artiguinhos na net, ou se ate leu o livro mas nao tem a base da orientacao a objetos, ai sim, vai fazer essas nhacas ai e dizer q eh DDD.

Soh como exemplo de que a culpa nao eh do padrao por estar mal implementado, atualmente eu estou trabalhando num sistema legado que utiliza a arquitetura VO BO, foi feito no tempo em que isso era incentivado. Isso nao eh o ideal e causa alguns problemas de manutencao, mas eu digo sem medo que esse eh um dos sistemas sem testes, mais bem organizado que eu ja trabalhei.

O padrao nao eh la dos melhores, mas a implementacao foi boa e simples.

Quanto ao analisar com cuidado antes de implementar, só cuidado para nao ter cuidado demais e decidir muitas coisas antes de saber se elas funcionam ou nao. Isso normalmente eh muito pior do que “ir fazendo”.

YvGa e Jair Rillo Junior

Novas metodologias e novos conceitos são lançados constantemente pela comunidade JAVA. As vezes em um intervalo tão curto que nem ao menos permitem o domínio e a utilização por parte dos programadores, talvez para alimentar a lucrativa indústria de revistas que publicam estes artigos. Há uma preocupação tão grande em fazer circular estas “novidades” que os novos conceitos acabam por atropelar conceitos não tão novos, até caírem em contradição, isso também acontece, por exemplo, com o DDD, onde a sobrecarga das classes de domínio, como consequência da reorganização das camadas, entram em conflito com a própria definição JavaBeans.

O foco mais notável do DDD é a reorganização dos recursos da aplicação em camadas, como se isso fosse um algo novo ou revolucionário, acontecendo uma separação física mas não lógica das classes, ou seja, o real problema de acoplamento, nem sempre está sendo resolvido como é anunciado. Basicamente, a divisão ocorre com a classificação das classes em domínio, serviço e persistência. O que não é claro nesta especificação e como a bagaça deve ser classificada e redistribuída e até que ponto isso pode representar uma melhora no desenvolvimento e manutenção de uma aplicação, afinal, qualquer tentativa de organização dos recursos também estará contribuindo para um melhor entendimento. No curto prazo, na verdade, o DDD transfere a lógica de negócio presente na camada de serviço para as classes de domínio, pior, sem qualquer estratégia. A arte de transportar a bagaça que vira o código fonte de um lugar para outro, ou quem sabe para debaixo do tapete, não é nenhuma novidade, é uma prática batida e manjada no mundo JAVA. É sempre essa ladainha, o destino só DEUS sabe, mas o importante é vender a ideia de que o resultado da refatoração proporcionou uma camada mais limpa e mais fácil de realizar manutenção e adicionar funcionalidades. Não é difícil perceber este artifício em outras arquiteturas, é o que também acontece, por exemplo, com Java Server Faces (JSF), onde uma 4a camada foi criada entre a visão e o controle do MVC. Para evitar redundância, chamaram esta camada de apresentação, e nela foi colocada a bagaça. Qual o objetivo? Vender a ideia de que agora o controle ficou mais limpo.

A grande maioria destas metodologias só são tidas como boas enquanto a adesão é baixa, pois neste formato, acontece uma divisão entre os “maiorais” da informática e os idiotas programadores, como prêmio, quem está “alinhado” com as “tecnologias de ponta”, não precisa participar ativamente do projeto, cabendo a única coisa que interessa: dar pitaco. No momento que muitas equipes começam a utilizar a metodologia revolucionária, ela tão logo se torna antiga e ultrapassada. JSP, na visão da própria comunidade, revolucionou o desenvolvimento para web, mas só porque outras tecnologias como ASP e PHP já eram amplamente utilizadas. No exato momento que JSP ganhou adesão, reinventaram essa gororoba JSF Java Server Faces que, para quem não sabe, é tão antiga quanto o próprio JSP.

O curioso é que quanto melhor uma metodologia é vendida como perfeita e revolucionárias, pelos nossos atenciosos consultores, menor é o entendimento dos conceitos, maior é o nível de complexidade e menor ainda é a produtividade. Talvez, o grande objetivo esteja diretamente ligado com a produtividade. É uma questão de matemática, se agora levamos o dobro do tempo para fazer uma tela de cadastro, que mal teria colocar um PF no meio do caminho? Numa ordem de grandeza, qual seria a diferença?

Por fim, este tópico foi aberto em 28/07 (quase 4 meses) e ficou todo esse tempo sem receber qualquer ajuda ou resposta. E só voltou a atualidade porque aproveitei o assunto para fazer uma crítica ao DDD, que pouco tem acrescentar e ainda sugere aos programadores o empilhamento da lógica de negócio nas classes de domínio. Nestas condições, eu que pergunto. O que vocês estão querendo dizer se baseando no que foi deixado como resposta? É uma prova de que?

Voce leu Domain Driven Design?

Antes dele voce leu Object Oriented Software Construction? Patterns of Enterprise Application Architeture?

Leu clean code? Refactoring? Leu TDD by example? Design Patterns?

Voce leu Working Effectivelly with legacy code?

Nao da pra listar tudo que alguem deve ler, mas voce entendeu a ideia.

O fato eh q eu ouco sempre essa conversa de DDD isso, TDD aquilo, modinha isso, revistinha aquilo, blablabla, blablabla, blablabla.

E tudo isso com sempre a mesma desculpa. Vou fazer procedural porque procedural sempre funcionou. Sim, sempre funcionou, mas existem coisas que funcionam melhor. DDD nao eh pattern eh conceito, mas antes de alguem querer entender DDD, vai ter que conhecer OO, atribuicao de responsabilidades, alta coesao/baixo acoplamento.

O problema eh que isso nao tem nominho bonito, nao vende revista e todo mundo acha que sabe. NAO, NAO SABE. Mais de 90% dos programadores que eu conheci nao conhecem OO um minimo aceitavel e eu rarissimas vezes encontrei um que achasse que deveria saber mais do que sabia.

Pois bem, aqui tem um, eu leio, estudo e aplico muitos dos conceitos OO, mas continuo tendo que aprender, continuo tendo que melhorar, continuo me surpreendendo com algo que nao estava fazendo direito.

O fato eh que DDD, TDD, GoF patterns e seja la o que for nunca vao ter efeito nenhum no codigo quando quem esta escrevendo o codigo nao tem a menor nocao de como, quando e porque atribuir determinada responsabilidade a uma classe ou outra. Quando mover um metodo daqui pra la, quando e como quebrar um classe em duas. Quando usar polimorfismo ou nao.

E diferente do que voce fala, sim as novidades sempre surgem, mas normalmente elas vem como forma de aprimoramento do que ja se sabia antes, as novidades sao normalmente complementares e nao se contradizem. Agora se o cara nao tem a base pra entender, nao vai conseguir mesmo. Nao vai entender mesmo.

Nenhum desses conceitos voce aprende em revistas e blogs, se voce nao investir seu tempo em livros e praticar aquilo voce nao vai aprender nada.

Em resumo, nenhuma dessas praticas e conceitos “famosos” contradiz a base de tudo, que é o conhecimento basico de orientacao a objetos. Sem esse conhecimento (e acredite: muitos dos que pensam ter nao tem) nao sera possivel entender e muito menos aplicar qualquer desses conceitos.

[quote=Jair Rillo Junior]Adriano,

DDD não é uma receita de bolo que devemos segui-lá sem analisar o nosso cenário. No seu cenário, seu repository precisa de um método ADD e outro UPDATE? Se sim, manda bala em implementá-los, não há problema algum.

Uma dica é: entenda bem o Pattern Aggregate. Teoricamente, um Repository deve existir para o agregado raiz, os objetos "internos" dele podem/devem ser persistidos, alterados diretamente pelo raiz. Exemplo:

Supondo que no seu cenário o agregado raiz seja um objeto Cliente. Seu sistema também controla os Pedidos, que no caso pertencem à um cliente, assim sendo, Pedidos fica dentro de Clientes.

Clientes --(faz pedido)—> Pedido

Para persistir o Pedido, você não precisa, e na minha opinião não deve, ter um repositorio para Pedidos, pois você simplesmete faria "clientes.addPedido(pedido)".

Com Hibernate, teriamos um código assim mais ou menos

public void addPedido(Integer idCliente, Pedido pedido) {
  //Recupera o cliente previamente cadastrado
  Cliente cliente = clienteRepository.findById(idCliente); //Aqui o cliente estará gerenciado pelo Hibernate, ou seja, qualquer mudança será refletida em algum momento no BD"
  cliente.addPedido(pedido); //O mesmo de cima. em algum momento seu pedido será inserido na base de dados
}

Note que no exemplo acima existe um repository apenas para o objeto agregato raiz.

Em alguns exemplos mais "radicais", você pode ter, como exemplo, objeto raiz SISTEMA, que tem apenas 1 valor que foi previamente inserido via INSERT direto na base de dados. Nesse caso, o sistema.addCliente, sistema.addProdutos, sistema.findClienteById().addPedido() e por ai vai.

Isso é só uma dica. Espero que tenha ajudado[/quote]

Jair, seguinte:

Pelo que entendi de DDD e Repository, um repository em sua tradução para o nosso português representa um repositor e não um recipiente (esse seria o banco de dados ou arquivos) como alguns interpretam em alguns casos. Então o referido “repositorio” em OO deve representar um repositor do mundo real, ou seja, um cara (como se fosse uma pessoa, um profissional) responsável por guardar ou buscar um determinado objeto (ou um tipo de objeto) que será ou está guardado em um determinado local ou recipiente (SGBD). Como um funcionário que fica repondo produtos no estoque e retirando do estoque para encaminhá-lo a expedição. Não necessariamente algum funcionário contratado somente para exercer essa função, mas qualquer um que realize essa tarefa estaria exercendo, ao menos naquele momento, o papel de repositor, logo, o referido repository correto?

Sempre ouço que em OO devemos ao máximo representar o mundo real. Em tese, representar objetos do mundo real em objetos de programação pode ser um tanto subjetivo por depender muito do “ponto de vista”. E depende do ponto de vista de cada um e pior, do seu próprio ponto de vista daquele dia (que pode ser diferente do de outro dia)…rs…

Se entendi bem, quando diz sobre o “agregate root” ser o cliente (que se entendi bem você refere-se a “Entidade” Cliente), este deveria guardar um pedido (outra entidade), por ser dele este pedido.

Pois bem, onde quero chegar? Porque um cliente deveria guardar um registro de pedido? Talvez, um cliente possa (ou até tenha que) fazer um pedido. Mas daí a ele ser responsável por guardar um pedido não seria delegar tarefa de um repositor a um cliente?

Grato!