Mais um tópico de DDD

Boa tarde!

Antes de mais nada, li e reli os tópicos de DDD do fórum. Aprendi muita coisa mas ainda restam muitas dúvidas. Talvez por eu somente estudar e não aplicar os conceitos no cotidiano. Infelizmente onde eu trabalho nós aplicamos metodologias como POG e XGH (Extreme Go Horse - Quem não conhece google it…rs).

Vou colocar resumidamente o que eu entendi a respeito do DDD e em seguida postar as dúvidas.

DDD é uma forma de pensar, um conceito para resolver um problema de forma Orientada a Objetos. Poderia utlizar todos os padrões recomendados para a pratica de DDD sem ainda estar usando DDD. A ideia basica é isolar o que é negócio de infraestutura e aplicação.

a “Grosso modo” seria um modelo de objetos interconectados, que são capazes de abstrair e resolver um problema, são facilmente desacoplados e testados, e não enxergam nada alem de negocio, nao sabem como seu estado é armazenado e nem como será apresentado.

Para chegar nesse objetivo usamos alguns padrões.

[list]Repository[/list]
[list]Service[/list]
[list]Factories[/list]

etc…

pergunta número um…

aproveitando o exemplo de um outro topico…

Fornecedor fornecedor = ...; List contas = dao.carregaContasPagasDesde1999(fornecedor);
Ou:

Fornecedor fornecedor = ...;
List contas = fornecedor.getContasPagasDesde1999()

a segunda opção me parece muito mais OO, porém para fazer esse metodo teria que seguir algumas premissas: O metodo deveria ser uma ação válida dentro do contexto do negócio para aquela entidade. Certo?

  1. Se eu tivesse que fazer um método que trouxesse dados mais complexos, tendo que resgatar dados de diversas entidades… isso caberia muito melhor a um service? ou até mesmo pesquisas muito complexas?

  2. Em uma operação para salvar um fornecedor

interface FornecedorRepository {

  void add(Fornecedor f);
}
  1. para que o metodo add do repositorio de fornecedor funcione a contento, deveria salvar nao so o fornecedor, mas tbm seus agregattes? como fazer isso?

poderia ser assim:

class FornecedorRepositoryImpl implements FornecedorRepository {

private DocumentoRepository dr;

public void add(Fornecedor f ) {

new FornecedorDAO().salvar(f);
dr.add(fornecedor.getDocumento());
  
}
  1. Se eu precisar de controle transacional, onde coloco? em um service?

  2. é correto fazer isso?


Class Fornecedor {

private FornecedorRepository fr;
private ContaRepository cr;

public List<Conta> getContasPagas(Date since) {
  return cr.getContasPagas(since);
}
  1. Se sim, como injeto os repositórios dentro das entidades…???

tenho muitas outras perguntas, mas vou ficar com essas por enquanto…

Obrigado pela colaboração.

[…]s

Colega não sou expert em DDD, mas assim igual vc, leio bastante e procuro aplicar no meu dia-a-dia. O interessante é ir aprendendo e aplicando, no começo vc vai achar mta coisa estranha, vai estar errado, mas vc vai consertando com o tempo.

Tentando entender sua dúvida , acho que vc está naquele problema de “como aplicar o repositorio”? Ou “devo misturar coisas que deveriam ser de repositorio (ou um service) dentro da minha entidade”? Bom, acho que pode ser esta sua dúvida.

De qualquer forma, eu procuro pensar o seguinte: sua entidade Fornecedor deve ser uma representação, um estado, e não um service, nem uma forma inteligente de buscar dados. Isso deve ser responsabilidade de outro.
Se vc quer tratar de coisas de fornecedor, deve ter um Repositorio de Fornecedores. Esse repositorio define que comportamentos que serão implementados por “algo que não sabemos ainda”…rs

Por exemplo, vc define:

interface FornecedorRepository {
   public List&lt;Fornecedor&gt; getFornecedoresLegais();
}

Se vc precisa das contas pagas, concorda que a conta é uma representação do seu sistema? Logo:

interface ContaRepository {
   public List&lt;Conta&gt; getContasPagasDoFornecedor(Fornecedor fornecedor);

   public List&lt;Conta&gt; getContasQueNaoForamPagasAinda();
}

Dessa forma, um FornecedorRepository define que a implementação deve saber tratar de coisas de fornecedor. E o ContaRepository deve saber tratar de coisas de conta, independende doq seja.
Agora, como fazer isso na pratica? Um factory, que devolve um repositorio, que te traz aquilo que vc quer! Essa factory, tem a ideia de ser uma “fabrica” de repositorios:

DaoFactory factory = new DaoFactory();
// aqui a factory tem metodos que retornam os "caras" que implementam as interfaces de repository. 
Fornecedor fornecedor = factory.getFornecedorRepositorio().getPeloId(5); // Obs: esse metodo getPeloId(id) pode ser herdado por alguma classe da implementação. Tipo algo FornecedorRepositoryImpl extends BaseImpl
List&lt;Conta&gt; contasDoFornecedor = factory.getContaRepositorio().getContasPagasDoFornecedor(fornecedor);

Se vc precisa de transação, seria ideal abri-la no local onde será feita a lógica da transação:

factory.beginTransaction();
factory.getFornecedorRepositorio().atualiza(fornecedor);
factory.commit();

factory.close();

Espero ter ajudado, mas a ideia que eu quis passar é que sua entidade nao deve se preocupar com essas coisas.

amigo infelizmente ainda nao tenho muita experiencia com DDD porem tenho estudado assim como vc… tb li o livro do Eric Evans

nao leve as afirmaçoes abaixo como verdades absolutas, sao apenas pitacos meus rsrs

assim é mais OO:

Fornecedor fornecedor = ...;  
List contas = fornecedor.getContasPagasDesde1999()  

existe um artigo no blog da caelum que cita exatamente este exemplo.

quanto a questao 2, acredito que isso realmente esteja correto, se vc estiver usando um orm tipo o hibernate isso pode ser feito via cascata

questao 4: acho que é valido, tb acho que ficaria até mais legal renomear o metodo para getContasPagasDesde(Date data)

questao 5 otima pergunta para se ver na pratica, ainda mais qdo se utiliza ejb rsrs

abrasssssss

Está na sua mão mudar isso. Se vc aplicar padrões como repositorio mas lhe chamar de business, isso é pog e eles vao aceitar :slight_smile: rsrsrsrsr

Isto é correto.

DDD não é uma forma de pensar OO. DDD é uma metodologia de organização do desenvolvimento que não tem nada que ver com OO ( não diretamente). O que tornar X em DDD é a aplicações de conceitos como Linguagem Ubiqua que é uma prática muito velha que foi renomeada para ter um efeito legal… Esqueça DDD e concentre-se em OO.

Sim.

Na realidade aquele exemplo é ruim. getContasPagasDesde1999 implica numa pesquisa e isso implica no uso de repositorio, o mais certo seria

Fornecedor fornecedor = ...;
List contas = repositoriodeContas.getContasPagasPara(fornecedor, Interval.iniciandoEm(1999));

O fornecedor pode ter métodos get, mas eles são relativos à sua arvore (grafo) de agregados. Por exemplo, fornecedor.getProdutosComercializados() seria um possivel método (fornecedor vende produtos), mas quando vc for pensar melhor, verá que a lista de produtos que o fornecedor vende também muda com o tempo, portanto seria melhor ter um repositorioProdutos.getProdutosVendidosPor(fornecedor, Interval.iniciandoEm(1990)ate(2001))

Sim. Mas cuidado porque nem todas as entidades do gafo do fornecedor pertencem no agregado.

É isso ai ( embora eu não ache que repositorios sejam definidos como interfaces)

Exatamente

Não. Pode parecer que é legal, mas na prática vc terá problemas de sincronismo da informação.
Por exemplo, se vc chamar esse método no inicio e no final de um método, pode acontecer que a segunda chamada não retorna o mesmo que a primeira.
Ai é muito mais complicado inventar um mecanismo que garanta que a chamada retorne o mesmo do que simpesmente não usar esse modelo.
Outro caso é quando vc enviar o objeto fornecedor para outro nodo (via serialização por exemplo), onde não existe suporte ao repositorio.

Vc entendeu o que interessa que são as responsabilidades de cada padrão. Esses padrões são da OO normal e não carece que vc entenda ou saiba DDD para os usar.

A estrutura de repositorios e serviços é otima e eu aconcelho vivamente que a use, mas evite misturar as bolas e achar que isso é DDD. Esqueça o DDD. OO bem feito é tudo o que vc precisa.