Dúvidas - Transações/DDD

Pessoal, tenho algumas dúvidas com relação à alguns assuntos…

Se os mais experientes puderem me ajudar(respondendo as questões, ou indicando
fontes pra que eu possa buscar as respostas), eu agradeço. :smiley:

TRANSAÇÕES

1 - O que é uma transação?

2 - Usando JPA, qual a diferença entre utilizar RESOURCE_LOCAL ou JTA? em quais ocasiões a
utilização de cada uma é recomendada?

3 - Qual a finalidade da anotação “@Transaction” do Spring?

DDD

1 - Um repositório é uma interface que o dao implementa, ou é uma classe concreta?

2 - Por que os entities devem ter referências aos seus repositórios? Eles devem referenciá-los
apenas quando eu utilizar active record ou sempre? Essa dúvida surgiu porque em alguns posts eu vi
um repositório genérico sendo utilizado (neste caso, aonde ficariam as consultas específicas
de cada entidade?), e em outros posts eu vi repositórios específicos para cada entidade sendo utilizado.

Acabei ficando confuso nesse aspecto.

Desculpem pelo grande número de dúvidas. :oops:

Aqui tem uma excelente definição sobre transação http://en.wikipedia.org/wiki/Database_transaction, mas a grosso modo falando, usamos transação quando queremos que várias operações sejam executadas, se uma falha, todas as outras operações devem voltar para o seu estado inicial. O exemplo clássico é transferencia bancaria. Voc6e tem que tirar dado de uma certa conta e passar dado para a outra conta, se algum dessas operações falharem, tudo deve voltar para o estado inicial.

JTA é quando o controle transactional será utilizado através da API JTA (do J2EE). Geralmente utilizado quando você tem uma aplicação rodando sobre um container
RESOURCE_LOCAL não usa a API JTA, o usuário se encarrega de fazer o controle transactional. Em JPA por exemplo, você usa o UserTransaction para fazer esse controle.

Não!!! São conceitos diferentes. Repositório pertence ao dominio, a camada de negócios, enquanto o DAO pertecente a camada de persistencia. Em alguns casos, pode até ser que o repositório seja uma interface/classe abstrata e o DAO sua implementação, mas isso não é regra.
A um tempo atrás, houve um excelente tópico no GUJ sobre isso, leia aqui http://www.guj.com.br/posts/list/60916.java

Não existe a fórmula certa para se fazer tudo. Isso depende de casa para caso.
Mas o ideal é sim, os repositórios serem injetados dentro das Entidades (para evitar acoplamento). Um jeito recomendado para fazer isso, é criar a entidade através de um Factory e nessa hora injetar o repositório no seu construtor.

Espero que fique clara as dúvidas

[quote=ManchesteR][quote=Erick Jeronimo]
1 - O que é uma transação?
[/quote]
Aqui tem uma excelente definição sobre transação http://en.wikipedia.org/wiki/Database_transaction, mas a grosso modo falando, usamos transação quando queremos que várias operações sejam executadas, se uma falha, todas as outras operações devem voltar para o seu estado inicial. O exemplo clássico é transferencia bancaria. Voc6e tem que tirar dado de uma certa conta e passar dado para a outra conta, se algum dessas operações falharem, tudo deve voltar para o estado inicial.

JTA é quando o controle transactional será utilizado através da API JTA (do J2EE). Geralmente utilizado quando você tem uma aplicação rodando sobre um container
RESOURCE_LOCAL não usa a API JTA, o usuário se encarrega de fazer o controle transactional. Em JPA por exemplo, você usa o UserTransaction para fazer esse controle.

Não!!! São conceitos diferentes. Repositório pertence ao dominio, a camada de negócios, enquanto o DAO pertecente a camada de persistencia. Em alguns casos, pode até ser que o repositório seja uma interface/classe abstrata e o DAO sua implementação, mas isso não é regra.
A um tempo atrás, houve um excelente tópico no GUJ sobre isso, leia aqui http://www.guj.com.br/posts/list/60916.java

Não existe a fórmula certa para se fazer tudo. Isso depende de casa para caso.
Mas o ideal é sim, os repositórios serem injetados dentro das Entidades (para evitar acoplamento). Um jeito recomendado para fazer isso, é criar a entidade através de um Factory e nessa hora injetar o repositório no seu construtor.

Espero que fique clara as dúvidas[/quote]

Já clareou bastante a minha mente, cara. Obrigado! :smiley:

1 - Tú recomenda alguma leitura pra que eu possa aprender a usar esse controle transacional?

2 - E quando eu tiver um domínio muito grande? não vai ficar complicado de gerenciar essa injeção de entities através da factory?

3 - No caso, o repositório do entity vai apenas cumprir o papel de “fazer consultas”, ou vai ser utilizado pra armazenar/deletar/atualizar o entity (isso não seria active record)?

O conceito de transação é bastante simples, o próprio link acima pode te ajudar. Agora se você quer aprender o controle transacional específico de um framework ou especificação, ai você deve ler direto da fonte. NO caso do spring, olhe a própria documentação dele. No caso de EJB3, existem vário slivros por ai, um que é free e eu indico para quem quer começar e ter uma idéia, é o Mastering EJB 3 (pdf free).

Pelo contrário, IMO. Quanto maior o dominio, maiores o relacionamento e etc, a Factory ajuda mais. Pois na factory você já pode criar os objetos com todos os relacionamentos necessários. Pior seria sair dando vários new Objeto() e fazer o relacionamento na camada de negócio, assim bagunçando tudo.
Além do mais, você não precisa necessariamente fazer o DI na Factory, se você não vai utilizar Factory por exemplo, você pode usar algum framework para fazer o DI, como EJB3, Spring, Google Guice, etc.

[quote=Erick Jeronimo]
3 - No caso, o repositório do entity vai apenas cumprir o papel de “fazer consultas”, ou vai ser utilizado pra armazenar/deletar/atualizar o entity (isso não seria active record)?[/quote]
Active Record é um outro padrão de projeto, não necessariamente agregado com DDD.
O repositório trabalha na camada de negócios, no dominio. Ele é o caminho para as entidades trabalharem com dados em memória, porém ele não se preocupa se eles dados serão persistidos em um banco de dados X, Y, ou se será em XML, YML, arqiuvo texto, etc… O repositório tem que ser algo o mais natural possível, aqui nomenclatura é MUITO importante. Fica muito mais simples você ter o método no repositório buscaOsDezUltimosClientesCadastrados() do que um find(select * from clientes…).
Como já foi dito, o Repositório em alguns casos pode ser apenas uma Interface e o DAO pode ser uma classe concreta que implementa essa interface, porém pode haver casos que o repositório tem sua própria implementação separada do DAO. Na minha experiência, geralmente CRUDs utilizam a primeira abordagem, enquanto quando você tem dominios mais específicos, a separação do respositório e dão são diferentes. Alias, Com JPA, a idéia de ter um DAO é quase nula, pois o EntityManager já pode fazer o papel de repositório e DAO, deixando a implementação mais simples.

E por fim, não saia criando milhões de layers sem necessidade. Tente fazer o mais simples possível. Por isso que não existe a fórmula para todos os problemas. Os padrãoes de projetos estão ai, mas devem ser usados sob-moderação (parece propaganda de cerveja :slight_smile: ).

Com relação a manter referência dos repositórios nas entidade eu diria que depende. Entidades e repositórios são objetos pertencentes ao domínio, portanto podem conversar entre si sem problemas. Não existe regra, mas sim avaliação de acordo com a situação.

Geralmente definimos as operações do repositório por meio de uma interface e pode acontecer da implementação do repositório ser feita apenas com uma DAO. Em casos bem simples acredito que isso é legitimo. No entanto, em casos mais complicados com a necessidade de acessar objetos de agregados diferentes, é necessário realizar a interface com uma classe concreta própria, pois pode existir a necessidade de um repositório acessar outro para cumprir seus objetivos. Infelizmente tudo depende do cenário.

Eu particularmente não concordo com Repositórios genéricos em sistemas mais complexos. Em seu livro, o Evans coloca muito bem que a razão da utilização de um modelo de domínio rico é a clareza que ele passa aos desenvolvedores e demais utilizadores. Sendo assim, se tivermos repositórios somente com método genéricos (GetById, GetByName, etc) acabamos deixando a clareza e expressividade do domínio de lado. Mas isso também não é uma regra visto que algumas vezes devemos escolher entre clareza e produtividade por exemplo.

Com relação a métodos de pesquisa, qual das duas formas está correta?

1 - cliente.buscaOsDezUltimosClientesCadastrados(); //metodo na entidade
2 - clienteRepository.buscaOsDezUltimosClientesCadastrados(); //metodo no repositorio

Com relação a persistir/remover/atualizar qual das duas formas está correta?

1 - cliente.store(cliente); //metodo na entidade
2 - clienteRepository.store(cliente); //metodo no repositorio

Caso eu coloque os métodos de pesquisa de persistir/remover/atualizar no repositório, meio que perde o sentido do entity ter uma referência ao ser repositório, ou eu estou enganado?

[quote=Erick Jeronimo]Com relação a métodos de pesquisa, qual das duas formas está correta?

1 - cliente.buscaOsDezUltimosClientesCadastrados(); //metodo na entidade
2 - clienteRepository.buscaOsDezUltimosClientesCadastrados(); //metodo no repositorio

Com relação a persistir/remover/atualizar qual das duas formas está correta?

1 - cliente.store(cliente); //metodo na entidade
2 - clienteRepository.store(cliente); //metodo no repositorio

Caso eu coloque os métodos de pesquisa de persistir/remover/atualizar no repositório, meio que perde o sentido do entity ter uma referência ao ser repositório, ou eu estou enganado?[/quote]

A segunda opção me parece melhor, é o repositório que irá fazer esse papel de dados. Mas como eu já disse, simplicidade é a melhor coisa. Existem casos que você nem mesmo precisa definitir uma interface para repositório. O próprio EntityManager do JPA já faz esse papel. Então ao invés de sair criando interface + classe concreta para ela, você usar diretamente o EntityManager fica mais simples. Ex EJB3:

@Stateless
public class CustomerBean implements Customer {
  @PersistenceContext
  private EntityManager em;

  public void saveCustomer(Customer customer) {
    em.persist(customer);
  }
}

Mais simples que sair criando vários layers, nao é? E também ficou bastante claro, quem ler esse código em teoria vai entender o que está acontecendo. Além de não estar acoplando as camadas :slight_smile:

Uma das coisas que o RoR (Ruby on Rails) me fez pensar e abrir a cabeça é sobre a simplicidade. Atualmente eu trabalho com EJB2 (eca), e tem muitas camadas, muitos padrões, tem que criar muita interface para coisas simples. O EJB3 já trouxe essa facilidade, com o Spring você também consegue. Então porque complicar se podemos facilitar? e ao mesmo tempo deixar o código claro

Não existe forma correta ou errada de fazer estas coisas, existe a mais apropriada para cada cenário.

ManchesteR

Achei bem interessante a tua sugestão :smiley:

Realmente simplifica bastante as coisas, mas eu pensei o seguinte, não ficaria muito misturado teus métodos que fazem operações com o BD ficarem junto com métodos de negócio, que não tem relação nenhuma com banco de dados?

Eu penso que poderia ficar estranho (não sei se eu é que não sou acostumado com esse tipo de arquitetura :roll: )

Queria também uma sugestão dos colegas…

Na minha arquitetura eu estou usando Spring+JPA+JSF. Alguma sugestão de como eu posso injetar o repositório nos entities? Eu não manjo nada de AOP :frowning:

Atualmente eu to usando o @PostConstruct do Spring, usando o repositório injetado no Managed Bean para criar a minha entidade. O que vcs acham dessa solução?

Desculpem a ignorância, mas qual a necessidade de (no meu caso) o managed bean ter uma referência para o repositório, e ao mesmo tempo, ter uma referência para a entidade (que também referencia o repositório).

Eu pensei em abstrair a referência direta do managed bean ao repositório, fazendo algo do tipo:

cliente.store(cliente);

Mas achei muito estranho um cliente armazenar outro cliente(ou uma referência pra ele mesmo).

Alguém poderia me dar uma luz? :smiley:

Obs.: pcalcado

O complicado é conseguir distinguir qual escolha vai ser melhor para um determinado cenário :?