DDD - Como vocês injetam seus repositórios nas entidades de negocio?

Usam instanciacao normal?
Usam algum container de DI ? Qual? Poderia ilustrar um exemplo de configuração dessa injeção?
Usam aspectos? Poderiam me passar um exemplo?

Estou com dúvidas nisso! Obrigado!

Normalmente uso uma interface na camada de domínio.

E na camada de persistência uma classe que implementa essa interface.

E, pra que o domínio saiba qual classe que implementa aquela interface, uso DI.

[quote=Rodrigo Vieira Pinto]Normalmente uso uma interface na camada de domínio.

E na camada de persistência uma classe que implementa essa interface.

E, pra que o domínio saiba qual classe que implementa aquela interface, uso DI.[/quote]

Você quer dizer que usa DI, assim:

class Person { private PersonRepository repository; // <---- AQUI VOCÊ USA DI? }

[quote=MrDataFlex]Usam instanciacao normal?
Usam algum container de DI ? Qual? Poderia ilustrar um exemplo de configuração dessa injeção?
Usam aspectos? Poderiam me passar um exemplo?
[/quote]

Em tese todos esses métodos são iguais.
Vc precisa definir o repositorio no construtor da classe.
Se vc o passa manualmente ou com injeção é irrelevante para a construção da classe.

  class Person {  
          private final PersonRepository repository; 

          public Person (PersonRepository repository){
                    this.repository = repository;
          }

  }  

O que vc não deve fazer é

  class Person {  
          private PersonRepository repository; 
  }  

e esperar milagres.
Esse código espera que exista um DI e isso fazer suposição. Supor é sempre ruim.

[quote=sergiotaborda][quote=MrDataFlex]Usam instanciacao normal?
Usam algum container de DI ? Qual? Poderia ilustrar um exemplo de configuração dessa injeção?
Usam aspectos? Poderiam me passar um exemplo?
[/quote]

Em tese todos esses métodos são iguais.
Vc precisa definir o repositorio no construtor da classe.
Se vc o passa manualmente ou com injeção é irrelevante para a construção da classe.

  class Person {  
          private final PersonRepository repository; 

          public Person (PersonRepository repository){
                    this.repository = repository;
          }

  }  

O que vc não deve fazer é

  class Person {  
          private PersonRepository repository; 
  }  

e esperar milagres.
Esse código espera que exista um DI e isso fazer suposição. Supor é sempre ruim.
[/quote]

Isso significa que há outra camada de uso acima da Person, demosntrada neste exemplo?
Como ficaria a sua utilização ?

Edit: Em outras palavras, de uma maneira de boa prática: quem estaria criando o repositório e passando a Person ?

[quote=MrDataFlex]
Isso significa que há outra camada de uso acima da Person, demosntrada neste exemplo?
Como ficaria a sua utilização ?

Edit: Em outras palavras, de uma maneira de boa prática: quem estaria criando o repositório e passando a Person ?[/quote]

Não existe essa outra camada.

Agora, onde vc precisa inicializar Person ? Vc faria isso no repository/dao usando create() algo como


PersonRepository  rep = new PersonRepository ();
Person p = rep.create();

// dentro de create

public Person create(){

   return new Person(this);
}

Assim é fácil. O Repositorio auto injeta-se no person.

Na prática vc nunca pode dar um new em Person directamente. Vc precisa de um outro objeto
para fazer isso. Seja o repositorio/dao , seja um objeto especifico para isso , ou seja via DI

Se vc usar DI então o container irá prover a implementação de PersonRepository para Person quando criar o objeto person. Para isso vc precisa inicializar Person sempre através do container. Algo como (com Guice)


Person p = Guice.getInjector().getInstance(Person.class);

Claro que, assim, não precisa do método create() no repositorio/dao

[quote=sergiotaborda][quote=MrDataFlex]
Isso significa que há outra camada de uso acima da Person, demosntrada neste exemplo?
Como ficaria a sua utilização ?

Edit: Em outras palavras, de uma maneira de boa prática: quem estaria criando o repositório e passando a Person ?[/quote]

Não existe essa outra camada.

Agora, onde vc precisa inicializar Person ? Vc faria isso no repository/dao usando create() algo como


PersonRepository  rep = new PersonRepository ();
Person p = rep.create();

// dentro de create

public Person create(){

   return new Person(this);
}

Assim é fácil. O Repositorio auto injeta-se no person.

Na prática vc nunca pode dar um new em Person directamente. Vc precisa de um outro objeto
para fazer isso. Seja o repositorio/dao , seja um objeto especifico para isso , ou seja via DI

Se vc usar DI então o container irá prover a implementação de PersonRepository para Person quando criar o objeto person. Para isso vc precisa inicializar Person sempre através do container. Algo como (com Guice)


Person p = Guice.getInjector().getInstance(Person.class);

Claro que, assim, não precisa do método create() no repositorio/dao[/quote]

Valeu amigão, só para finalizar, poderias validar minha arquitetura baseada em DDD, e dizer se está correta ou não?

[code]class arch.domain.business.entity.Person {
private PersonRepository rep;
public Person(PersonRepository rep) { this.rep = rep; }

//gets / sets

//comportamentos

public void store() {
rep.save(this);
}

}[/code]

[code]class arch.domain.business.repository.PersonRepositoryImpl implements PersonRepository {
private PersonDAO personDAO;

public void save(Person p) {
    personDAO.save(p);
}

}[/code]

Pelo codigo que vc mosrtrou não tem nada errado. Você está usando ActiveRecord com Repositorio mutável e DAO. Eu não usaria active record, mas isso sou eu.

[quote=sergiotaborda][quote=MrDataFlex]
Valeu amigão, só para finalizar, poderias validar minha arquitetura baseada em DDD, e dizer se está correta ou não?
[/quote]

Pelo codigo que vc mosrtrou não tem nada errado. Você está usando ActiveRecord com Repositorio mutável e DAO. Eu não usaria active record, mas isso sou eu.

[/quote]

Obrigado pelo esclarecimento, amigo!

Poderia me dizer o que faria você optar por utilizar gerenciadores ao invés de AR ?

Concordo com o Sergio: pelo construtor fica direto e sem magia negra.

[quote=MrDataFlex]
Poderia me dizer o que faria você optar por utilizar gerenciadores ao invés de AR ?[/quote]

A pergunta seria “O que me faria usar AR”. A resposta : nada.
AR não é sério para sistema grandes. Essa é a minha opinião.
Quando vc está gerenciando transações com objetos (padrão WorkUnit) o fato do objeto poder passar por cima disso tudo é muiito ruim. O objeto simplesmente não deve ter essa responsabilidade. Atrapalha.

Se o objeto está vindo do Contexto Persistente (EntityManager, Hibernate Session) quem injeta?

Só injeto coisas na entidade quando elas são necessárias para as responsabilidades da entidade. Salvar-se não é uma responsabilidade da entidade.

Não faz sentido algum uma entidade precisar se salvar.

Uma sugestão bem legal em minha opinião está aqui:

New Improvements in Domain Object Dependency Injection Feature

Não sou fã do @Configurable, mas as outras opções de usar uma interface marcadora ou uma annotation própria para DI me pareceu interessante.

Alguém sabe se é possível fazer algo parecido com o Guice?

Se o objeto está vindo do Contexto Persistente (EntityManager, Hibernate Session) quem injeta?[/quote]

Neste caso, imagino que o ideal seria passar o repositório por parâmetro do método da entidade.

turma.getAlunosReprovados(alunoRepository);

Na opinião de vocês é também uma opção válida?

Se o objeto está vindo do Contexto Persistente (EntityManager, Hibernate Session) quem injeta?
[/quote]

No Hibernate e JPA+Hibernate, que injeta é um interceptor configurado no hibernate.cfg.xml ou programaticamente. Fica bem legal.

(atualmente ou injeto na mão ou faço magia negra com AOP)

Se o objeto está vindo do Contexto Persistente (EntityManager, Hibernate Session) quem injeta?[/quote]

Neste caso, imagino que o ideal seria passar o repositório por parâmetro do método da entidade.

turma.getAlunosReprovados(alunoRepository);

Na opinião de vocês é também uma opção válida?[/quote]

Válida sim, util, dificilmente. Isso obriga a ter uma referencia ao repositorio e não ha como injetar pq
é um método que vc vai usar em alguns casos. Por outro lado, se vc tem a referencia ao repositorio
vc simplesmente faz rep.getAlunosReprovados(turma) que é muito mais claro.
Ou seja, em principio vc não passa objetos de infra como parametros dos seus métodos de negocio. É estranho.

Quanto ao Guice. Guice é muito mais simples que Spring. Ele já parte do conceito de que é possivel injetar qualquer coisa em qualquer lugar. Vc coloca um @Inject onde quer que ele assuma a configuração.
E não ha xml envolvido. É um conceito melhor: configuração via codigo.
Além disso o Guice é extensivel. Vc pode configurar um escopo especial para os seus objetos de entidade , por exemplo, e injetar coisas neles sempre que eles são criados. Isso é muito baba com Guice.

Ou seja, assim como no spring, seu eu fizer

o guice conseguirá fazer a injeção de dependência nesta nova instância de aluno?

Se é isso mesmo que entendi Sérgio, que maravilha. Eu já estava mesmo querendo uma opção ao Spring, mas as vezes que procurei recurso como este para o Guice não encontrei.

Se o objeto está vindo do Contexto Persistente (EntityManager, Hibernate Session) quem injeta?

Só injeto coisas na entidade quando elas são necessárias para as responsabilidades da entidade. Salvar-se não é uma responsabilidade da entidade.

Não faz sentido algum uma entidade precisar se salvar.[/quote]

Mas e o ActiveRecord ? Faz isso muito bem, não acha ?

Nao confundir Active Record (o padrao, que tb eh diferente de ActiveRecord, a implementacao do Rails) com DDD, please. Uma briga de cada vez :slight_smile:

IMHO, HashMaps convertidos do HttpServletRequest, sanitizados e enfiados no PreparedStatement sao um bom comeco. O que vem dali eh organizacao latente e a putaria toda tem que ser ditada pela sua linguagem ubiqua. Se o cliente disse que o usuario salva o documento no servidor, o melhor eh chegar o mais perto possivel de um

…em algum lugar do seu sistema.