Em relação a arquitetura e regra de negócio é uma boa prática fazer um mapeamento bidirecional

Estou estudando Hibernate e vi que há mapeamentos unidirecional: um modelo tendo acesso a outro modelo. e bidirecional ambos tendo acesso aos dados dos modelos.

Mas isso é uma boa prática de arquitetura e regra de negócio? (bidirecional)
Não é delegar responsabilidades demais? uma classe alterar valores de outra e vice versa?
Não haverá inconsistência na base de dados que condenará toda a aplicação que irá gerar dados incorretos.
ou o desenvolvedor deve amarrar essas “vulnerabilidades” na regra de negócio?
ou vai de caso a caso dependendo do modelo de negócio que o projeto está realizando?
Sabendo que a maioria das aplicações são desenvolvidas no modo “botton-up” iniciando com o projeto de banco de dados.

Qual o conhecimento e opinião de vocês a respeito?

[quote=Alexsandro Lopes]Estou estudando Hibernate e vi que há mapeamentos unidirecional: um modelo tendo acesso a outro modelo. e bidirecional ambos tendo acesso aos dados dos modelos.

  1. Mas isso é uma boa prática de arquitetura e regra de negócio? (bidirecional)
  2. Não é delegar responsabilidades demais? uma classe alterar valores de outra e vice versa?
  3. Não haverá inconsistência na base de dados que condenará toda a aplicação que irá gerar dados incorretos. ou o desenvolvedor deve amarrar essas “vulnerabilidades” na regra de negócio?
    ou vai de caso a caso dependendo do modelo de negócio que o projeto está realizando?
  4. Sabendo que a maioria das aplicações são desenvolvidas no modo “botton-up” iniciando com o projeto de banco de dados.

Qual o conhecimento e opnião de vocês a respeito?[/quote]1) Pq não seria?
2) Não. Altera se quiser, não é obrigado.
3) Não. Se o desenvolvedo
4) Hibernate/JPA se adapta a aplicações legadas sem problema.

[quote=Alexsandro Lopes]
Mas isso é uma boa prática de arquitetura e regra de negócio? (bidirecional)
Não é delegar responsabilidades demais? uma classe alterar valores de outra e vice versa?[/quote]
Depende! Se você tem duas “entidades” (entidades no conceito de DDD) que se relacionam entre si não há problema, mas isso não é regra, bem pelo contrário, o ideal é sempre usar o padrão Aggregate.

Se são duas “entidades” não há problemas pois elas são classes independentes entre si e a alteração de uma não não deveria afetar as invariantes da outra classe! Porém se uma classe é dependente da outra para manter suas invariantes então isso pode ser um problema. Nesse caso provavelmente uma das classes não é uma “entidade” e sim um agregado e nesse caso o acesso deve ser sempre unidirecional e deve ocorrer a partir da raiz do agregado que normalmente é uma “entidade”!

[quote=Alexsandro Lopes]
Sabendo que a maioria das aplicações são desenvolvidas no modo “botton-up” iniciando com o projeto de banco de dados.[/quote]
Isso é outro problema. Se você modela dados não modela objetos! A Modelagem devem sempre começar pelos objetos e não pelos dados (claro que se é um sistema legado são outros quinhentos)! Modelar dados é bem diferente de modelar objetos pois são estruturas diferentes com propósitos diferentes. Quando você modela um sistema OO deve encarar o BD simplesmente como um repositório de dados pois ao contrário você terá que “adaptar” os objetos ao banco de dados e nesse caso eles acabam por não representar o dominio da aplicação corretamente. Esse tipo de abordagem embora antiga é muito utilizada ainda pois é amplamente ensinada nas universidades mas está claramente ligada ao modelo procedural. Quem perde com isso é a normalização dos dados que muitas vezes terá que ser sacrificada

Essa sua visão é importante, pois foi assim que aprendi na faculdade e em um estágio que fiz a base estava toda pronta e não poderia ser alterada(e mal modelada) , então você desenvolve em cima de como os dados estão sendo armazenados e certas falhas na base, o desenvolvedor tem que corrigir na aplicação.

[quote=Alexsandro Lopes][quote]
Isso é outro problema. Se você modela dados não modela objetos! A Modelagem devem sempre começar pelos objetos e não pelos dados (claro que se é um sistema legado são outros quinhentos)! Modelar dados é bem diferente de modelar objetos pois são estruturas diferentes com propósitos diferentes. Quando você modela um sistema OO deve encarar o BD simplesmente como um repositório de dados pois ao contrário você terá que “adaptar” os objetos ao banco de dados e nesse caso eles acabam por não representar o dominio da aplicação corretamente. Esse tipo de abordagem embora antiga é muito utilizada ainda pois é amplamente ensinada nas universidades mas está claramente ligada ao modelo procedural. Quem perde com isso é a normalização dos dados que muitas vezes terá que ser sacrificada
[/quote]

Essa sua visão é importante, pois foi assim que aprendi na faculdade e em um estágio que fiz a base estava toda pronta e não poderia ser alterada(e mal modelada) , então você desenvolve em cima de como os dados estão sendo armazenados e certas falhas na base, o desenvolvedor tem que corrigir na aplicação. [/quote]

Na verdade a visão não é minha, mas existem basicamente três cenários na modelagem Objeto Relacional

  1. O banco de dados é só um repositório. Melhor cenário pois é possível criar um modelo rico e a lógica do negócio não ficará espalhada. Apesar das vantagens muitas vezes será necessário abrir mão da normalização dos dados.

  2. O banco é usado somente pela aplicação: Então é possível ainda utiliza-lo como um repositório de dados. Isso deve ser feito somente para objetos novos. Para transformar dados antigos em novos objetos é aconselhável uma minuciosa refatoração de modo que toda a modificação deve ocorrer nos dados somente através desses novos objetos a fim de evitar inconsistências. Nesse momento a utilização de um “modelo anêmico” pode ser a melhor solução pois provavelmente as regras de negócios estão espalhadas pelo código (muitas vezes até pelo banco) e uma mudança mais radical pode ser inviável.

  3. O banco é usado por diferentes sistemas! Senta e chora! Nesse caso usar objetos é quase impossível, quando não inviável. Não ha garantia que novas classes não serão acessadas por outros sistemas tornando os dados inconsistentes. Nesse caso a única abordagem que vejo é um modelo totalmente anêmico devido a fragmentação das regras de negócio!

PS: Se você deseja ver mais sobre isso sugiro a leitura de 2 Livros o Domain Driven Design do Eric Evans e o Padrões de Arquitetura de Aplicações Corporativas do Martin Fowler

[quote=Hebert Coelho][quote=Alexsandro Lopes]Estou estudando Hibernate e vi que há mapeamentos unidirecional: um modelo tendo acesso a outro modelo. e bidirecional ambos tendo acesso aos dados dos modelos.

  1. Mas isso é uma boa prática de arquitetura e regra de negócio? (bidirecional)
  2. Não é delegar responsabilidades demais? uma classe alterar valores de outra e vice versa?
  3. Não haverá inconsistência na base de dados que condenará toda a aplicação que irá gerar dados incorretos. ou o desenvolvedor deve amarrar essas “vulnerabilidades” na regra de negócio?
    ou vai de caso a caso dependendo do modelo de negócio que o projeto está realizando?
  4. Sabendo que a maioria das aplicações são desenvolvidas no modo “botton-up” iniciando com o projeto de banco de dados.

Qual o conhecimento e opnião de vocês a respeito?[/quote]1) Pq não seria?
2) Não. Altera se quiser, não é obrigado.
3) Não. Se o desenvolvedo
4) Hibernate/JPA se adapta a aplicações legadas sem problema.[/quote]

O problema dessa pratica é ocorre quando se usa um modelo de dominio rico, ou seja, quando as regras de negocio ficam dentro das classes! Nesse cenário o acesso bidirecional pode ser um problema pois pode permitir a quebra das invariantes de um dos objetos ou até mesmo dos dois!

[quote=x@ndy]O problema dessa pratica é ocorre quando se usa um modelo de dominio rico, ou seja, quando as regras de negocio ficam dentro das classes! Nesse cenário o acesso bidirecional pode ser um problema pois pode permitir a quebra das invariantes de um dos objetos ou até mesmo dos dois![/quote]Ainda assim não vejo problema.

carro.autalizarSistema(); ou pessoa.getCarro().autalizarSistema(); para mim deve dar no mesmo.

[quote=Hebert Coelho][quote=x@ndy]O problema dessa pratica é ocorre quando se usa um modelo de dominio rico, ou seja, quando as regras de negocio ficam dentro das classes! Nesse cenário o acesso bidirecional pode ser um problema pois pode permitir a quebra das invariantes de um dos objetos ou até mesmo dos dois![/quote]Ainda assim não vejo problema.

carro.autalizarSistema(); ou pessoa.getCarro().autalizarSistema(); para mim deve dar no mesmo.[/quote]

http://uaihebert.com/?p=62

(putz… teu próprio blog! :lol: )

[quote=Alexandre Saudate][quote=Hebert Coelho][quote=x@ndy]O problema dessa pratica é ocorre quando se usa um modelo de dominio rico, ou seja, quando as regras de negocio ficam dentro das classes! Nesse cenário o acesso bidirecional pode ser um problema pois pode permitir a quebra das invariantes de um dos objetos ou até mesmo dos dois![/quote]Ainda assim não vejo problema.

carro.autalizarSistema(); ou pessoa.getCarro().autalizarSistema(); para mim deve dar no mesmo.[/quote]

http://uaihebert.com/?p=62

(putz… teu próprio blog! :lol: )[/quote]uia! esse aí é laaaaaa dos primordes do meu blog! =D

Tá aí mais um motivo para eu ainda pensar que bidirecional não é problema. [=

[quote=Hebert Coelho][quote=x@ndy]O problema dessa pratica é ocorre quando se usa um modelo de dominio rico, ou seja, quando as regras de negocio ficam dentro das classes! Nesse cenário o acesso bidirecional pode ser um problema pois pode permitir a quebra das invariantes de um dos objetos ou até mesmo dos dois![/quote]Ainda assim não vejo problema.

carro.autalizarSistema(); ou pessoa.getCarro().autalizarSistema(); para mim deve dar no mesmo.[/quote]
Se carro e Pessoa são duas entidades distintas não existe problema porém vamos dizer que temos um carro e ele deve obrigatorioamente ter um motor e não se pode ter um motor que não pertença a um carro

public class Carro{
  @OneToOne(cascade=CascadeType.REMOVE)
  private Motor motor;
  //Getters And Seters
  public void excluir(){
    Repositorio<Carro> repositorio = new Repositorio<Carro>(Carro.class);
    repositorio.excluir(this);
  }
}

E para o motor eu tenho:

public class Motor{
  @OneToOne(cascade=CascadeType.REMOVE)
  private Carro carro;
  //Getters And Seters
  public void excluir(){
    Repositorio<Motor> repositorio = new Repositorio<Motor>(Motor.class);
    repositorio.excluir(this);
  }
}

Agora imagine que alguem chegue e faça isso:

public class Carro{
  @OneToOne(cascade=CascadeType.REMOVE)
  private Motor motor;
  @OneToOne
  private RegistroDetran detran;
  //Getters And Seters
  public void excluir(){
    Repositorio<Carro> repositorio = new Repositorio<Carro>(Carro.class);
    detran.darBaixa();
    repositorio.excluir(this);
  }
}

Como ao alterar o Carro não sou obrigado das consequências disso sobre o Motor temos um problema ai! Na verdade não deveria haver uma relação bidirecional ali, até por que um Carro tem um motor mas um Motor não tem um Carro. Nesse caso o motor é um agregado do carro e deveria ser um Objeto Valor e todo o acesso ao motor deveria ser feito pelo carro, ele nem deveria ter um método excluir na verdade. Porém esse tipo de coisa acontece direto e acredito que seja sobre isso que o Alexandre Saudate se referia

[quote=x@ndy][quote=Hebert Coelho][quote=x@ndy]O problema dessa pratica é ocorre quando se usa um modelo de dominio rico, ou seja, quando as regras de negocio ficam dentro das classes! Nesse cenário o acesso bidirecional pode ser um problema pois pode permitir a quebra das invariantes de um dos objetos ou até mesmo dos dois![/quote]Ainda assim não vejo problema.

carro.autalizarSistema(); ou pessoa.getCarro().autalizarSistema(); para mim deve dar no mesmo.[/quote]
Se carro e Pessoa são duas entidades distintas não existe problema porém vamos dizer que temos um carro e ele deve obrigatorioamente ter um motor e não se pode ter um motor que não pertença a um carro

public class Carro{
  @OneToOne(cascade=CascadeType.REMOVE)
  private Motor motor;
  //Getters And Seters
  public void excluir(){
    Repositorio<Carro> repositorio = new Repositorio<Carro>(Carro.class);
    repositorio.excluir(this);
  }
}

E para o motor eu tenho:

public class Motor{
  @OneToOne(cascade=CascadeType.REMOVE)
  private Carro carro;
  //Getters And Seters
  public void excluir(){
    Repositorio<Motor> repositorio = new Repositorio<Motor>(Motor.class);
    repositorio.excluir(this);
  }
}

Agora imagine que alguem chegue e faça isso:

public class Carro{
  @OneToOne(cascade=CascadeType.REMOVE)
  private Motor motor;
  @OneToOne
  private RegistroDetran detran;
  //Getters And Seters
  public void excluir(){
    Repositorio<Carro> repositorio = new Repositorio<Carro>(Carro.class);
    detran.darBaixa();
    repositorio.excluir(this);
  }
}

Como ao alterar o Carro não sou obrigado das consequências disso sobre o Motor temos um problema ai! Na verdade não deveria haver uma relação bidirecional ali, até por que um Carro tem um motor mas um Motor não tem um Carro. Nesse caso o motor é um agregado do carro e deveria ser um Objeto Valor e todo o acesso ao motor deveria ser feito pelo carro, ele nem deveria ter um método excluir na verdade. Porém esse tipo de coisa acontece direto e acredito que seja sobre isso que o Alexandre Saudate se referia[/quote]Desculpe mas de todos os livros que eu já li sobre JPA (uns 4) e artigos na internet, em nenhum um Repositório é utilizado dentro de uma Entidade.

Não creio que para isso que ela foi criada e essa deva ser sua real utilização.

Se você não quer que a ação de um não influencie o outro, tire o cascade. Caso o Motor não possa existir sem o carro mas o carro exista sem motor, utilize orphan removal.

[quote=Hebert Coelho]Desculpe mas de todos os livros que eu já li sobre JPA (uns 4) e artigos na internet, em nenhum um Repositório é utilizado dentro de uma Entidade.
Não creio que para isso que ela foi criada e essa deva ser sua real utilização.[/quote]
Não precisa se desculpar pois não sei quais livros você leu mas eu vejo muita gente utilizando errado o repositório. Na verdade é muito comum as pessoas chamando DAO de Repositório.

Existe um artigo do Philip Calçado que fala sobre isso e o título é bem interessante Domain-Driven Design é Simples: Basta Chamar DAOs de Repositórios. Na verdade o assunto não fala nada sobre Repositório mas sobre como as as pessoas usam padrões vinculados a DDD sem realmente praticar DDD! O título é justamente sobre isso, pois muito desenvolvedores buscam o DDD mas pegam o padrão DAO renomeiam para Repositório e acham que tem DDD por causa disso!

Eu utilizo o a implementação mostrada no livro do Martin Fowler (Padrões de Arquitetura de Aplicações Corporativas) Aqui tem um exemplo, mas no livro é está muito melhor explicado.

No blog da Caelum eles também falam sobre isso: http://blog.caelum.com.br/repository-seu-modelo-mais-orientado-a-objeto/

Mas como foi dito o carro tem que ter motor, é uma invariante do carro!

Esse exemplo é bem simples e o cascade.Remove foi só um exemplo do que pode ocorrer. O verdadeiro problema é que determinados objetos só devem ser acessados através de objetos, ou seja, só existe um relacionamento unidirecional. O Motor nesse caso é um, os Itens de um Pedido podem ser outros. Esses são exemplos de Agregados, objetos que só devem ser acessados por outros objetos já que eles não existem sem este e o acesso incondicional a estes pode até mesmo quebrar as invariantes dos objetos envolvidos. Citando o Eric Evans:

Isso não quer dizer que deve-se banir o relacionamento bidirecional, ele só deve ser usado com moderação e aonde ele realmente se aplica!

[quote=x@ndy]Não precisa se desculpar pois não sei quais livros você leu mas eu vejo muita gente utilizando errado o repositório. Na verdade é muito comum as pessoas chamando DAO de Repositório.

Existe um artigo do Philip Calçado que fala sobre isso e o título é bem interessante Domain-Driven Design é Simples: Basta Chamar DAOs de Repositórios. Na verdade o assunto não fala nada sobre Repositório mas sobre como as as pessoas usam padrões vinculados a DDD sem realmente praticar DDD! O título é justamente sobre isso, pois muito desenvolvedores buscam o DDD mas pegam o padrão DAO renomeiam para Repositório e acham que tem DDD por causa disso!

Eu utilizo o a implementação mostrada no livro do Martin Fowler (Padrões de Arquitetura de Aplicações Corporativas) Aqui tem um exemplo, mas no livro é está muito melhor explicado.

No blog da Caelum eles também falam sobre isso: http://blog.caelum.com.br/repository-seu-modelo-mais-orientado-a-objeto/[/quote]Eu não vejo aplicação de DDD com Entity do JPA. Ainda mais por que em seus eventos Pre algo e Pos algo existem diversas regras quanto a transação e outras coisa. E se não me engano, eles não podem nem acessar a uma transação ou coisa do tipo. Não me lembro bem agora, posso olhar depois. Não sei se o DDD seria bem aplicado a uma Entity desse modo. Falo isso com relação a ideias original de Entidade, o que ela deve ser e fazer. Uma Entidade de JPA ao conhecer um repositório da vida estaria conhecendo mais do que deveria, e foge ao conceito de Entity do JPA.

[quote=x@ndy]
Mas como foi dito o carro tem que ter motor, é uma invariante do carro!

Esse exemplo é bem simples e o cascade.Remove foi só um exemplo do que pode ocorrer. O verdadeiro problema é que determinados objetos só devem ser acessados através de objetos, ou seja, só existe um relacionamento unidirecional. O Motor nesse caso é um, os Itens de um Pedido podem ser outros. Esses são exemplos de Agregados, objetos que só devem ser acessados por outros objetos já que eles não existem sem este e o acesso incondicional a estes pode até mesmo quebrar as invariantes dos objetos envolvidos. Citando o Eric Evans:

Isso não quer dizer que deve-se banir o relacionamento bidirecional, ele só deve ser usado com moderação e aonde ele realmente se aplica!
[/quote]Pra mim então houve erro de modelagem. Se um motor não pode ver carro ele nunca deve ser bidirecional. Se um motor pode ver um carro não vejo problema algum com relação a comportamento e qualquer outra coisa mais (tirando o DDD que não estudei ainda). Mas pelo que você mostrou, uma Entity (conceito de JPA apenas) nunca deveria conhecer um repositório ou seja lá o que for.

[quote=Alexsandro Lopes]Estou estudando Hibernate e vi que há mapeamentos unidirecional: um modelo tendo acesso a outro modelo. e bidirecional ambos tendo acesso aos dados dos modelos.

Mas isso é uma boa prática de arquitetura e regra de negócio? (bidirecional)
Não é delegar responsabilidades demais? uma classe alterar valores de outra e vice versa?
Não haverá inconsistência na base de dados que condenará toda a aplicação que irá gerar dados incorretos.
ou o desenvolvedor deve amarrar essas “vulnerabilidades” na regra de negócio?
ou vai de caso a caso dependendo do modelo de negócio que o projeto está realizando?
Sabendo que a maioria das aplicações são desenvolvidas no modo “botton-up” iniciando com o projeto de banco de dados.

Qual o conhecimento e opinião de vocês a respeito?[/quote]

Se A têm B e B tem A o problema não de birirecinalidade, é de lógica.
é muito raro que seja necessário ter navegação (a palavra OO é navegação entre A e B) bidirecional. Não pela tecnologia, mas pela lógica da coisa.

As entidades têm relações e agregação ou seja, umas estão contidas nas outras. Tanto no sentido físico, como no sentido de lógica.

Por exemplo, Empresas (clientes) e Pedidos. Pedidos são para uma empresa e empresas fazem pedidos. Parece que é necessário anvegação bidirecional, mas não. Pedidos precisam de uma empresa para serem completos. empresas não precisam de pedidos para serem completas. Logo, existe pedidos.getEmpresa, mas não empresa.getPedidos.

Em modelos avançados de domínio onde se usa o padrão memento, ou seja, a entidades do domínio não são as mesmas entidades (active record me vêm à cabeça) , seria possivel que empresa.getPedidos existisse. Seria até ideal , do ponto de vista do dominio, afinal essa é a relação real. Mas na prática isso seria mediado por um serviço/repositorio o que significa que não é uma relação “natural”, é apenas uma query. E é uma query porque eu não quero saber todos os pedidos de uma vez. normalmente quero filtrar. então é irrelevante que obtenha todos os pedidos. Ou seja, eu não faria um emprea.getPedidos e depois iria filtrar com for e if, eu simplemente pediria ao repositorios que me desse os pedidos conforme o filtro X.

Poderiamos argumentar que um modelo é DDD e o outro não é, mas o fato é que isso é irrelevante pois não trabalhamos com DDD de verdade onde o modelo não tem nada que ver com a persistência e vice-versa. Então no nosso mundo onde a entidade persistente e a de dominio são a mesma coisa, o modelo com uma só direção e queries à parte é mais gerenciável. Mas por exemplo, isto via para o espaço se vc tiver uma relaçao de arvore. Ai vc precisa que haja navegação bidirecional (o pai tem parent.GetChildren e o filho tem child.getParent ) e ai é um desafio. Mas vejam que isto é devido à estrutrua e não ao dominio em si.

[quote=Hebert Coelho]Eu não vejo aplicação de DDD com Entity do JPA. Ainda mais por que em seus eventos Pre algo e Pos algo existem diversas regras quanto a transação e outras coisa. E se não me engano, eles não podem nem acessar a uma transação ou coisa do tipo. Não me lembro bem agora, posso olhar depois. Não sei se o DDD seria bem aplicado a uma Entity desse modo. Falo isso com relação a ideias original de Entidade, o que ela deve ser e fazer. Uma Entidade de JPA ao conhecer um repositório da vida estaria conhecendo mais do que deveria, e foge ao conceito de Entity do JPA.
[/quote]
Entidade em DDD é um padrão de projeto e sendo assim eu posso implementa-lo com ou sem o uso da JPA. Nesse caso a Entidade JPA é somente uma ferramenta, um meio para que se possa implementar o padrão e como em qualquer implementação poderá ocorrer conflitos que deverão ser gerenciados, mas não quer dizer que o padrão não seja aplicável!

Um exemplo melhor de conflitos é o padrão Value Object que, conforme o padrão, deveria ter um construtor com parâmetros, mas isso o tornaria impossível de se usar com JPA! Então adapta-se o padrão a situação o que eu faço utilizando o padrão factory method para instanciar o objeto e manter as invariantes. O construtor publico continua existindo mas é proibido o seu uso no projeto (na verdade isso é regra para qualquer classe que deve ser sempre acessado a partir de sua fábrica nos projetos em que eu trabalho).

Citando o Evans novamente:

Sim houve um problema na modelagem ali! Por isso eu disse "Isso não quer dizer que deve-se banir o relacionamento bidirecional, ele só deve ser usado com moderação e aonde ele realmente se aplica!"
O relacionamento bidirecional só não deve ser usado indiscriminadamente e deve ser respeitado as invariantes nos relacionamentos através de padrão Aggregate.

Se for assim como evitar um modelo anêmico? Muitas operações para um modelo rico necessitam que o repositório seja acessado de dentro das Entidades! Se não for assim muitas operações terão que ser colocadas fora das classes o que leva a um modelo anêmico com classes quase sem responsabilidades e outras sendo responsáveis pelas regras de negócio! Acabaremos temos um modelo com os famigerados BOs e TOs

[quote=x@ndy][quote=Hebert Coelho]Eu não vejo aplicação de DDD com Entity do JPA. Ainda mais por que em seus eventos Pre algo e Pos algo existem diversas regras quanto a transação e outras coisa. E se não me engano, eles não podem nem acessar a uma transação ou coisa do tipo. Não me lembro bem agora, posso olhar depois. Não sei se o DDD seria bem aplicado a uma Entity desse modo. Falo isso com relação a ideias original de Entidade, o que ela deve ser e fazer. Uma Entidade de JPA ao conhecer um repositório da vida estaria conhecendo mais do que deveria, e foge ao conceito de Entity do JPA.
[/quote]
Entidade em DDD é um padrão de projeto e sendo assim eu posso implementa-lo com ou sem o uso da JPA. Nesse caso a Entidade JPA é somente uma ferramenta, um meio para que se possa implementar o padrão e como em qualquer implementação poderá ocorrer conflitos que deverão ser gerenciados, mas não quer dizer que o padrão não seja aplicável!

Um exemplo melhor de conflitos é o padrão Value Object que, conforme o padrão, deveria ter um construtor com parâmetros, mas isso o tornaria impossível de se usar com JPA! Então adapta-se o padrão a situação o que eu faço utilizando o padrão factory method para instanciar o objeto e manter as invariantes. O construtor publico continua existindo mas é proibido o seu uso no projeto (na verdade isso é regra para qualquer classe que deve ser sempre acessado a partir de sua fábrica nos projetos em que eu trabalho).

Citando o Evans novamente:

Sim houve um problema na modelagem ali! Por isso eu disse "Isso não quer dizer que deve-se banir o relacionamento bidirecional, ele só deve ser usado com moderação e aonde ele realmente se aplica!"
O relacionamento bidirecional só não deve ser usado indiscriminadamente e deve ser respeitado as invariantes nos relacionamentos através de padrão Aggregate.

Se for assim como evitar um modelo anêmico? Muitas operações para um modelo rico necessitam que o repositório seja acessado de dentro das Entidades! Se não for assim muitas operações terão que ser colocadas fora das classes o que leva a um modelo anêmico com classes quase sem responsabilidades e outras sendo responsáveis pelas regras de negócio! Acabaremos temos um modelo com os famigerados BOs e TOs[/quote]Não vou discutir o que é certo ou errado sobre DDD, eu não o estudei a fundo ainda.

A pergunta era relacionamento bidirecional do JPA e classes nos lados bidirecionais. JPA não inclui DDD e não tem suporte a suas idéias (partindo dos códigos que você postou aqui).

Se o cara quer colocar DDD e rasgar com o JPA, problema da aplicação dele. JPA não foi feito para isso.

O que eu posso afirmar é que, olhando a partir do bidirecional do JPA não existe problema algum em um relacionamento ser visto pelos dois lados da relacionamento. Não haverá problemas com os dados da aplicação ou métodos aplicados.

Não vou entrar em mérito de DDD, pois eu discutir DDD com alguém que sabe sobre esse assunto seria o mesmo que alguém que não é mineiro discutir sobre pão de queijo comigo. :lol: :lol: :lol:

[quote=Hebert Coelho]Não vou discutir o que é certo ou errado sobre DDD, eu não o estudei a fundo ainda.
A pergunta era relacionamento bidirecional do JPA e classes nos lados bidirecionais. JPA não inclui DDD e não tem suporte a suas idéias (partindo dos códigos que você postou aqui).
[/quote]
Na verdade usei DDD para justificar o problema que pode ser encontrado. Tudo depende como o cara modela se for optar por separar as regras de negócios das classes em um modelo anêmico, não tem qualquer problema (além, claro, do próprio modelo escolhido).

Com certeza, JPA é uma ferramenta e, como tal, deve ser usada apropriadamente!

Tirando o fato que um relacionamento bidirecional não é normal, realmente não existe problema :wink: ! O que eu quis expressar aqui foi justamente isso. A maioria dos relacionamentos é unidirecional, porém muita gente força um relacionamento bidirecional e isso cria um monte de problemas! A culpa é da JPA? Não! Ela é uma ferramenta. Relacionamentos bidirecionais realmente existem mas são raros, por isso tem que ser usados com moderação.

[quote=x@ndy]Tirando o fato que um relacionamento bidirecional não é normal, realmente não existe problema :wink: ! O que eu quis expressar aqui foi justamente isso. A maioria dos relacionamentos é unidirecional, porém muita gente força um relacionamento bidirecional e isso cria um monte de problemas! A culpa é da JPA? Não! Ela é uma ferramenta. Relacionamentos bidirecionais realmente existem mas são raros, por isso tem que ser usados com moderação.[/quote]Usando apenas JPA e sem DDD, quais problemas seriam esses? Tomando por base utilizando o JPA corretamente.

Você fez uma colocação interessante aqui: “Tomando por base utilizando o JPA corretamente

O problema é que não uma falha da JPA! No exemplo que eu coloquei seria errado fazer aquilo conforme a JPA? Não. Pois não tem nada na especificação que proíba esse tipo de coisa. É uma falha de modelagem. JPA é apenas uma especificação para fazer o mapeamento objeto relacional. Como alguém vai fazer a modelagem dos objetos não interessa para ela. Se alguém quiser usar TO’s e BO’s ou fazer um modelo rico tanto faz, pois JPA vai servir da mesma maneira!

O problema está no mapeamento bidirecional! Como a ferramenta me permite implementar isso facilmente eu terei problemas facilmente também, mas por falhas na modelagem e não da JPA. É a mesma coisa que culpar o carro por um atropelamento quando o motorista o conduz em alta velocidade. O carro permite que você corra, mas não é culpa dele se você fizer isso em um lugar não permitido e atropelar alguém.

Se você “modelar” corretamente não tera qualquer tipo de problema, seja com JPA para fazer o seu mapeamento objeto relacional ou outra forma qualquer. DDD só ensina técnicas para modelar o sistema de maneira adequada, porém conheço pessoas que o fazem sem nunca terem ouvido falar de DDD.

Então a pergunta melhor seria: Modelando corretamente e utilizando JPA para a persistencia objeto relacional, quais problemas seriam esses?

A resposta é nenhum!