DDD e JPA - Onde vão as annotations?

27 respostas
feliperod

Pessoal,

talvez eu tenha entendido errado algum conceito do DDD, mas eu procurei em muitos lugares, inclusive no GUJ e não achei nenhuma resposta simples para minha pergunta. Com certeza em algum lugar tem a resposta e talvez seja tão trivial que ficou perdida no tempo.

Eu entendo um pouco sobre DAOs e sobre Repositories, mas e as Entities?
Minha classe de Domain terá as regras de negócio e chama o repository para operações (como um service, certo?). O Repository pode executar algumas regras pertinentes a coleções de entities e chama o DAO quando necessário. O DAO precisa obter um objeto do Banco e no caso de um JPA da vida, deve utilizar um pojo com as anotações de JPA.

Mas aí é que fica minha dúvida. As anotações vão na Entity (falando em entity de Domain) ou vão em classes Java “replicadas” na camada de persistência. Caso sim, então eu tenho dois POJOs, um representando o Domain e outro simplesmente para a Persistência.

Pergunto isso porque não gosto da idéia de anotações no meu Domain. Minha classe de Domain não compila sem os jars do JPA.

Abração a todos…

27 Respostas

Javabuntu

tem um tópico aqui no GUJ que acho q vai tirar sua dúvida…

http://www.guj.com.br/posts/list/67988.java

Alessandro_Lazarotti

Duplicar nem pensar… não existe motivos para isso, ainda mais se falando de POJOS.
Se a Entity JPA é POJO e seu Entity DDD é POJO, então os objetos são identicos.

Metadados são simplesmente metadados.

Thiago_Senna

Talvez seja interessante utilizar o JPA com xml ao invés dos annotations. Isso para que o seu modelo não fique amarrado a forma que ele será persistido na base de dados. Mas não acho que seja grave utilizar annotations em seus entities e value objects. Só depende do quão purista você é, rsrs… Não é por que tem annotations que você não pode persistir as entidades utilizando jdbc.

Alessandro_Lazarotti

Em outras palavras, depende o quanto chato você quer ser… hehe. Seja um cara legal com sua equipe, use anotações :D.

Javabuntu

na verdade a escolha é sua, contanto que vc entenda que não fique ambos…ou um ou outro…no meu caso uso bean com anotações…não acho poluído não…

feliperod

Bom, primeiramente, obrigado pelas opiniões.

Mas ainda fica uma questão. Eu posso usar uma entity anotada com jdbc na unha, mas a questão é outra. Se meus domains tem que ser POJO, penso que ele não pode ter dependencias.

Acho que a dúvida seria a seguinte:

Se um POJO é suposto ser uma classe que não dependa de nenhuma API para executar, como uma entity JPA anotada seria um POJO?
Imagine que se eu anoto um POJO com a anotaao @Entity eu sou obrigado a fazer import javax.persistence.Entity e isso me obriga a levar o persistence.jar junto com o POJO para onde ele for. Será que ele ainda é um POJO?

Sei que é meio polêmico, mas quero saber com o pessoal tá usando isso no escopo de Domain Driven Design

Alessandro_Lazarotti

Anotações são apenas informações jogadas ao vento, não são códigos.
No caso do JPA, sua classe continua sendo POJO se apenas for anotada, mas deixa de ser se você utilizar EntityManager dentro dela (por isso use a abstração oferecida por um Repository).

Uma classe anotada não muda de comportamento, não ganha novas características nem nada, quem infere isso são os manipuladores das anotações… esses sim não são POJOS.

Levar os jars legados é um fato. Mas nada que uma refatoração não resolva. O melhor de tudo, a refatoração vai ser muito simples e sem possibilidades de erros em execução, pois as anotações não atribuem comportamentos inesperados… tudo que vc for pegar de erro será em tempo de compilação (importações, etc).

Eu utilizo algumas Entities JPA como entidades do DDD sem dor na consciência. :wink:

rodrigoy

Bom senso… bom senso… bom senso… desenvolvimento de software se resume a bom senso!

feliperod

É talvez seja um pensamento muito purista, hoje tenho utilizado com as annotations nas entities mesmo. Mas seria ótimo não precisar fazer isso.
Alias, consigo isso com frameworks que não são baseados em annotations. Acho que essa seria a solução para domains que são distribuidos como uma lib, para utilização em JEE, e JME ao mesmo tempo. Ou simplesmente manter dois projeto separados, um para JEE e um para JME.

De qualquer forma, acho que o rodrigo tem razão. Utilizar de bom senso resolve bastante coisa.

pcalcado

O problema eh que metadados (annotations) acabam por criar uma outra ‘dimensao’ nos seus objetos. Minha dica eh:

  • use o que for mais simples
  • nao perca muito tempo viajando sobre annotations ao inves de fazer seu trabalho, eh confuso mesmo
  • nao espalhe as anotacoes de infra pelas classes o quanto puder mas sem radicalismos

A forma com que os metadados sao usados em Java eh pessima. Metadados deviam fazer tagging apenas.

rodrigoy

Que risco você enxerga nas anotações da JPA e EJB3, Phillip?

Tenho criado algumas anotações minhas nos meus projetos. Você acha isso prejudicial de alguma forma também?

AvilaCS

Também estou criando as anotações JPA nas entidades e EJB3 nos repositórios!

Vocês vêem algum tipo de problema nisto?

Grato.

Emerson_Macedo

Lezinho:
Anotações são apenas informações jogadas ao vento, não são códigos.
No caso do JPA, sua classe continua sendo POJO se apenas for anotada, mas deixa de ser se você utilizar EntityManager dentro dela (por isso use a abstração oferecida por um Repository).

O que tem a ver ter um atributo de instância com ser um POJO ?

Thiago_Senna

Não vejo a utilização de annotations nas entidades como problema dependendo do projeto. Levando em consideração que o objetivo do DDD é criar um domínio e que este pode ser reaproveitado em outros projetos independente da base de dados, então acho bom não poluir o código com anotações específicas do JPA. Até por que não seria legal depender de um jar do JPA para compilar suas classes.

Enfim… quais são e quantos sãos os ambientes que o seu domínio terá que atuar? Sei lá… acho que ainda fica valendo o bom senso… rsrs…

Alessandro_Lazarotti

emerleite:
Lezinho:
Anotações são apenas informações jogadas ao vento, não são códigos.
No caso do JPA, sua classe continua sendo POJO se apenas for anotada, mas deixa de ser se você utilizar EntityManager dentro dela (por isso use a abstração oferecida por um Repository).

O que tem a ver ter um atributo de instância com ser um POJO ?

O termo quando foi cunhado por Fowler, tinha como objetivo dar um nome para classes Java simples, aquelas que não tinham necessidade de estender nem implementar nada de frameworks em específico que lhe rotulassem algo . Porém o termo é apenas uma referência, não é uma regra… mas isso é gosto particular. Tem gente que chama POJO de Bean e esta super bem com isso, outras pessoas acham que JavaBeans é apenas a definição de componentes para GUIs & RADs, etc.

Eu particularmente não chamo classes que dependem da infraestrutura de frameworks que lhe ditam como deve ser seu comportamento, de POJO.

Emerson_Macedo

Pois é, você tem razão quanto a isso mas esse problema é que agente mesmo critica pois tinha gente aqui que chamava Repositório de DAO em diversas discussões do GUJ dizendo que eram a mesma coisa e que se sentiam bem chamando assim.

Eu concordo com você que o termo é só uma referência e eu já havia lido o texto do Fowler, porém o mais aceito na nossa comunidade para POJO e as principais referências tem mais a ver com a não necessidade da classe em obedecer contratos de fameworks do que o conteúdo interno da mesma.

Em fim, eu queria só saber por que você tinha dito isso.

xandroalmeida

Eu uso Annotations. Eu sou muito mais feliz depois do Java 1.5 com suas Annotations.

Quem me conhece sabe que detesto xml para configurar e introduzir comportamentos no código. As Annotatins acabaram com isso, um bom exemplo de bom uso delas é o Hibernate e o JPA.

Então eu anoto diretamente minhas Entitys com as Annotations JPA ou Hibernate.

AvilaCS

Pessoal, não consigo ver o porque de não utilizar anotação JPA em minhas entidades!!
Alguém poderia passar alguns motivos?

le-silva

Gostei do camaradinha ai que disse pra ter BOM SENSO!

Tudo vai do projeto que você está trabalhando…

1- Qual a finalidade?
2- Sua entidades serão usadas somente neste projeto?
3- Haverá mesmo a necessidade de outras aplicações usarem estas entidades?
4- Tem certeza que vão usa-las mesmo?
5- Certeza absoluta?
6- Essas aplicações não vão usar JPA?
7- Certeza que não vão?

Então, cara, depende do projeto que você está trabalhando, do ambiente de desenvolvimento e execução das aplicações. É bom senso!

Haverá casos que usar anotações JPA serão tiro no pé. Outros que serão a salvação! Porque, meu chapa, configurar arquivos XML é um saco! E a possibilidade de erro aumenta de verdade…

Não dá pra ser xiita em desenvolvimento de software. O lance é: Resolva o problema do seu cliente da melhor forma!

E outra coisa: Faça o mais fácil; não se preoculpe com 100% dos problemas que podem acontecer num futuro distante, da ordem de 1%. Pense no agora e no daqui a pouquinho, não no daqui a 2 anos. Muita coisa muda!

Se o que alguém definiu como técnica XPTO serve pra você, ótimo! Se não serve 100%, tente adaptar para a sua necessidade. Não se a adaptação não for viável, mude para a técnica OTPX.

O lance é: Não é o seu a necessidade de software do seu cliente que tem que se adequar à técnica XPTO, mas sem a técnica XPTO te ajudar a atender 100% das expectativas do seu cliente.

Agrade o cliente com resultados 100% positivos, não às técnicas que deixam o seu cliente apenas 80% feliz.

Entregue o software que o seu cliente quer. Com as funcionalidades que ele quer.

Software funcionando e de qualidade total, este é o lema!

É o que eu penso…

Abraço!

feliperod

AvilaCS:
Pessoal, não consigo ver o porque de não utilizar anotação JPA em minhas entidades!!
Alguém poderia passar alguns motivos?

Pense no problema de extender um classe específica de um framework como no caso do Struts 1. Qual é o problema de extender?

O problema é que seu sistema fica atrelado ao framework struts. Aí rebuscaram o POJO nos frameworks mais novos, só que surgiu o problema dos metadados. Aí vieram com as annotations. Pensamos, com annotations minha classe é POJO, pois não extende nenhuma classe. Ótimo.

Mas o problema maior agora é a linha: import javax.persistence.Entity; por exemplo. Essa linha faz com que sua classe não compile sem o jar do JPA por exemplo. Ou seja, o acoplamento com alguns frameworks ainda existe. E foi o que gerou essa discussão.

Como o Philip falou, evitar ao máximo o uso de annotations no Domain. Obviamente as pessoas tem dificuldade de ver problema nisso, pois a maioria dos projetos não reusa o Domain para outros ambientes.

Imagine que seu Domain deva ser usado para ambiente Web e ambiente Mobile. Com anotações JPA na sua classe de Domain, terá que arrastar o jar do JPA para o ambiente Mobile (Nem precisa dizer que 2MB para o JPA funfar não é bom pra mobile né?).

Mas a parte do bom senso matou a pau, pois se você tem certeza de que sua aplicação não vai pra outro ambiente, esqueça essa discussão.
Se você for purista e gostar muito de best pratices, procure uma solução adequada a seu caso.

feliperod

pcalcado:
O problema eh que metadados (annotations) acabam por criar uma outra ‘dimensao’ nos seus objetos. Minha dica eh:

  • use o que for mais simples
  • nao perca muito tempo viajando sobre annotations ao inves de fazer seu trabalho, eh confuso mesmo
  • nao espalhe as anotacoes de infra pelas classes o quanto puder mas sem radicalismos

A forma com que os metadados sao usados em Java eh pessima. Metadados deviam fazer tagging apenas.

Concordo contigo. Acho que as annotations seriam muito melhores se não fosse necessário importar dentro da Tag, pois aí seriam simplesmente ignoradas na falta do Jar e funcionariam em qualquer ambiente.

Só por curiosidade, você vê alguma situação onde escrever duas classes com os mesmo atributos seja interessante? Uma classe para a persistência e outra para o Domain?

pcalcado

rodrigoy:
Que risco você enxerga nas anotações da JPA e EJB3, Phillip?

Imagine um exemplo simples:

@Entity
@Table(name="tbl_sky")
public class Sky implements Serializable {...}

Temos nestas linhas informacao que nao pertence ao dominio mas esta definida dentro da classe de dominio Isso eh ruim do ponto de vista da modelagem de negocios mas eu ainda tenho duvidas obre o real impacto em modelagem.

O grande problema eh que nao temos muita escolha. Se nao tem remedio remediado esta. Por enquanto :wink:

le-silva

pcalcado:

O grande problema eh que nao temos muita escolha. Se nao tem remedio remediado esta. Por enquanto ;)

Concordo!

Não temos muita escolha mesmo, já que a meneira como Java trata metadados é pura gambs.

sfidencio
rodrigoy:
Bom senso... bom senso... bom senso... desenvolvimento de software se resume a bom senso!

Rodrigo, sei que o post já é meio antigo, porém toda discussão que gera idéias magnificas como este, considero-o de suma importância dentro do contexto. Portanto, segue alguns questionamentos e dúvidas de minha parte:

1. Eu sempre fui adepto a desenvolver software usando padrões arquiteturais do GoF(Strategy, Facade, Singleton, Composite) e os Patters da SUN para especificação J2EE(Não estou dizendo que no DDD não usamos esses patterns), detalhe isso quando precisei de usar os tais (Não usei só prá dizer que usei padrão XY e Z) e outra o que estou me referindo e da arquiteturra BOLOVO (BusinessLayer, LayerObject, ValueObject)..usando e abusando de Transaction Scripts(Como você citou no teu blog) gerando um forte acoplamento entre as classes e quebrando e diminuindo a coesão (SRP - Principio da Responsabilidade Unica).
Porém agora estou desenvolvendo meu projeto (ERP segmentado para o ramo varejista) dirigido ao Dominio (DDD). Já andei lendo o livro do Evans, os Posts do Fowler, Adam Bien, GUJ..efim, revirei tudo antes de iniciar um projeto com DDD. Percebi que no DDD existem os Patterns que o acompanham e os anti-patterns, que porcerto contrariam os principios. vi aqui: http://www.infoq.com/articles/ddd-in-practice. Observei também que deve ser usar uma linguajar de negocio na manipulação dos artefatos, visto que todos envolvidos, Team, StakeHoldes, ScrumMaster, ProductOwner falam a mesma lingua(linguagem do dominio). Uma coisa que achei interessante no teu http://blog.aspercom.com.br/2009/08/11/repositorios-ddd/, você comentou também acerca de nomeclaturas, ou seja, eu tenho um repositorio de Pedidos, então não
sou obrigado a chama-lo de PedidoRepository, ou melhor, nem vejo isso como obrigação ou posso até está sendo tolo em ser influênciado a fazer isso, porquanto trata-se de convenção, afim de faclitar a idenficação, No Entanto eu concordo contigo, imagina o cliente ver esse diagrama de classes , será que ele vai saber o que significa esse tal de PedidoRepository? Pergunto isso porque muitos estão se levando a fazer isso, ou seja, colocar como sufixo da classe o nome do Pattern e eu estava pensando em fazer isso, porém nos Exemplos que achei pela net inclusive o proprio exemplo usando pelo Evans do Sistema de Transporte de Carga a interface se chama CargoRepository. É obvio que cada caso é um caso, e como você disse temos que ter Bom senso, e nesse caso eu acho que você usou o bom senso, porquanto eu achei extremamente lógico a tua colocação, eu achei mais limpo e mais claro na visão de Business Expert.
(Lembrando que to fazendo papel de Domain Expert tambem, porquanto conheço o ramo de negocio por 7 anos)

package se.citerus.dddsample.domain.model.cargo;

import java.util.List;

public interface CargoRepository {

  /**
   * Finds a cargo using given id.
   *
   * @param trackingId Id
   * @return Cargo if found, else {@code null}
   */
  Cargo find(TrackingId trackingId);

  /**
   * Finds all cargo.
   *
   * @return All cargo.
   */
  List<Cargo> findAll();

  /**
   * Saves given cargo.
   *
   * @param cargo cargo to save
   */
  void store(Cargo cargo);

  /**
   * @return A unique, generated tracking Id.
   */
  TrackingId nextTrackingId();

}
OBS: Esse CargoRepository está sendo implementado na camada de infraestrutura.

2. Outra coisa que eu queria te perguntar. Vocês estão falando acerca de Annotations, se usa-la dentro do Dominio estaremos poluindo nossas classes de dominio. Eu particulamente acho isso horrivel, se pudesse usar JPA sem annotations, se alguem conheçe me avisa, so não uso hibernate puro porque quero me beneficiar da JPA2. O que você acha disso? Uso Hibernate como implementação, sem anotação e sem chance de abstração ou JPA com anotação com N implementação e com chance de abstração do provider ORM?

3. Vou postar meu diagrama de projeto de classes aqui logo mais, e a estrutura das minhas classes como está ficando.

att
fidencio.

PedroTOliveira

Olá amigos eu tive essa mesma dúvida (E ainda me questiono bastante a respeito).

No meu caso o problema não estava somente relacionada a questão de colocar anotações na minhas Domain Classes mas também com o fato de que as minha entidades de domínio tinham um modelo diferente das minhas tabelas no banco de dados e em determinados casos eu poderia acessar outros Datasources que não eram tabelas em um banco relacional.

Nesse caso eu criei uma outra camada e separei com interfaces que chamei de Repository e neles eu injeto DataMappers fazendo sempre o mapeamento do Domínio para a Camada de Integração.

O padrão relacionado que encontrei é o http://martinfowler.com/eaaCatalog/dataMapper.html

Nesse caso eu ganhei porquê tornei meu domínio totalmente independente do framework de persistência, porém perdi aumentando a complexidade do mapeamento dos dados para o modelo de persistência.

sfidencio

PedroTOliveira:
Olá amigos eu tive essa mesma dúvida (E ainda me questiono bastante a respeito).

No meu caso o problema não estava somente relacionada a questão de colocar anotações na minhas Domain Classes mas também com o fato de que as minha entidades de domínio tinham um modelo diferente das minhas tabelas no banco de dados e em determinados casos eu poderia acessar outros Datasources que não eram tabelas em um banco relacional.

Nesse caso eu criei uma outra camada e separei com interfaces que chamei de Repository e neles eu injeto DataMappers fazendo sempre o mapeamento do Domínio para a Camada de Integração.

O padrão relacionado que encontrei é o http://martinfowler.com/eaaCatalog/dataMapper.html

Nesse caso eu ganhei porquê tornei meu domínio totalmente independente do framework de persistência, porém perdi aumentando a complexidade do mapeamento dos dados para o modelo de persistência.

Posso concluir que JPA/Hibernate é um mapeador de objetos para modelo relacional e vice-versa? ou um DataMapper ?

PedroTOliveira

No meu caso o DataMapper virou o mapeador das minha classes de Dominio para as Entities do JPA (Espelho da minha base) e vice-versa.

Criado 23 de novembro de 2007
Ultima resposta 6 de out. de 2010
Respostas 27
Participantes 12