O que usar no lugar de VOs?

136 respostas
V

Aqui sempre vejo muita gente "metendo o pau" em VOs (também chamados de TOs e DTOs). Não use isso, isso é uma gambiarra e blablabla.

Pois bem, vejo muita gente metendo o pau, mas pouca gente propondo uma solução. Que tipo de arquitetura VO-less vocês usam? Onde os dados são armazenados em memória? As classes de negócio tem estados ou não?

Suponha que você tenha um sistema que contém uma classe CellRendererGenerico<? extends VO> e uma classe CellRendererCliente extends CellRendererGenerico<ClienteVO>. Que tipo de refatoramento você faria nas classes CellRendererGenerico e CellRendererCliente?

136 Respostas

F

Princípio da OO: manter dados e lógica no mesmo objeto.

Vc nao precisa necessariamente programar Orientado a Objetos. Frameworks como o BC4J da Oracle, e o JCompany, usam objetos que só representam estado. E ja ouvi argumentos como o de ‘performance’ ( … a, ta bom, vc vai instanciar 10000 objetos prum relatorio, tendo estado em todos eles?.. ), a favor de usar VO.

Mas sei lá… vai de analisar e ver qual sua necessidade.

S

Já o pessoal do Design-Domain Drive
Fala do uso de VO… …

tb gostaria de saber … pq o pessoal não gosta?

:?:

T

sandeco:
Já o pessoal do Design-Domain Drive
Fala do uso de VO… …

tb gostaria de saber … pq o pessoal não gosta?

:?:


O VO que o pessoal de Domain-Driven Design fala não é o mesmo que o Data Transfer Object (DTO, nome atual do antigo VO catalogado pela Sun). O Value Object de DDD é um objeto que armazena valores, que não possui identidade ou ciclo de vida e deve ser imutável. Já o Value Object da Sun é um objeto que possui apenas dados, como se fossem os structs de C ou os records de Pascal. Seu uso deve ser empregado em ambientes onde serializar um objeto pode ser custoso (um ambiente distribuído, por exemplo).

R

Não confunda ValueObject [Fowler] com DTO[CoreJ2EEPatterns]. ValueObject é um conceito de dominio.

Atualmente trabalhamos com POJOS. Não temos problemas em criar um CellRenderer<PedidoVenda>. Este pedido venda pode ser um @Entity, é persistente, pode ter métodos de negócio e não é um DTO.

A

ok, vamos manter dados e lógica no mesmo objeto.
Nossa classe “QualquercoisaVO” agora vai se chamar “Qualquercoisa” e então terá uma série de métodos.

Mas com certeza teremos que trafegar o objeto “qualquercoisa” pelas camadas da nossa aplicação.

Como fica isso quanto a performance/serialização desse objeto ?

R

andersonlfl:
ok, vamos manter dados e lógica no mesmo objeto.
Nossa classe “QualquercoisaVO” agora vai se chamar “Qualquercoisa” e então terá uma série de métodos.

Mas com certeza teremos que trafegar o objeto “qualquercoisa” pelas camadas da nossa aplicação.

Como fica isso quanto a performance/serialização desse objeto ?

Não só uma serie de métodos mas também uma série de associações de negócio. O “Qualquer coisa” trafega sim pelas camadas da nossa aplicação sem problemas pois é um POJO (não confuda POJO com DTO). Esse objeto é serializado e trafegado da mesma forma que ocorre com o DTO, pois a serialização é com relação ao estado.

As camadas são lógicas e não fisicas. Não tem problema manusear uma Entidade na camada de view, como exemplo. De qualquer forma, não é qualquer aplicação que precisa serializar objetos. Uma aplicação web comum não usa isso. Não distribua seus objetos.

R

Esse foi o principal engano que todo mundo causou com os DTOs. Eles foram feitos para diminuir o overhead do tráfego de rede, no tráfegos de objetos pelas camadas de rede(tiers/física) da sua aplicação, e não nas camadas da aplicação(layers/lógica).

A

Tem razão, afinal o que trafega pelas camadas da aplicação é na verdade um endereço de memória e não um objeto em si.

E quanto ao Hibernate?
Tenho um “Qualquercoisa.hbm” representando um "xxx.Model.Qualquercoisa"
Esse cara guarda os estados que serão populados na base. Aqui meu objeto será serializado certo ? Se meu model “Qualquercoisa” agora tem uma série de métodos e associações de negócios, a performance/serialização disso não será prejudicada ?

C

Tem razão, afinal o que trafega pelas camadas da aplicação é na verdade um endereço de memória e não um objeto em si.

E quanto ao Hibernate?
Tenho um “Qualquercoisa.hbm” representando um "xxx.Model.Qualquercoisa"
Esse cara guarda os estados que serão populados na base. Aqui meu objeto será serializado certo ? Se meu model “Qualquercoisa” agora tem uma série de métodos e associações de negócios, a performance/serialização
disso não será prejudicada ?

Pelo que eu sei, não é assim que a banda toca. Já pensou se você tivesse 1000 objetos da sua classe QualquerCoisa instanciados, sendo que QualquerCoisa declara 4 métodos e esses métodos também fossem “instanciados”, ou seja, se houvesse 4000 métodos em memória?
Não é assim que acontece, os objetos possuem apenas seu respectivo estado. O código dos métodos está em algum lugar da memória mas é compartilhado por todas as intâncias. Logo, serialização não tem relação alguma com os métodos, métodos não são serializados, apenas dados (estado).

Alguém por favor me corrija se falei besteira :slight_smile:

V

Certo. O que ocorre é que nos primeiros 4 ou 8 bytes de memória alocado a um objeto existe uma referência à classe deste (que pode ser obtida pelo método getClass()). Após estes primeiros bytes, seguem os demais campos pertencentes ao objeto. Primeiro os da superclasses e depois os das subclasses, e na ordem em que são declarados. Os métodos e construtores são referenciados no objeto Class, que mantém uma estrutura de dados com ponteiros para os métodos e construtores. Na inicialização de Class estes ponteiros são inicializados com cópias dos ponteiros dos métodos da superclasse, alguns destes são sobrescritos por outros métodos (e aí ocorre a sobrescrita) e são adicionados mais alguns ponteiros para os métodos novos.

Mas, voltando ao foco do tópico:

O VO (ou TO, ou DTO) contém getters e setters burros para todos os seus campos, o que não provê um encapsulamento verdadeiro (dá quase na mesma que ter todos os atributos públicos). Como objeto de negócio, apenas métodos de mais alto nível acessam os campos, provendo um encapsulamento verdadeiro, o que dispensa a necessidade da maior parte dos getters e setters.

Mas, e quando você utiliza algum tipo de framework, tal como Hibernate ou algo baseado em Reflection para construir ou alterar instâncias dinamicamente? Como você evita de ter que colocar getters e setters para todos os campos deixando o encapsulamento fraco e ao mesmo tempo permitindo que o tal framework faça o seu serviço direito?

C

victorwss:
cassio:


Certo. O que ocorre é que nos primeiros 4 ou 8 bytes de memória alocado a um objeto existe uma referência à classe deste (que pode ser obtida pelo método getClass()). Após estes primeiros bytes, seguem os demais campos pertencentes ao objeto. Primeiro os da superclasses e depois os das subclasses, e na ordem em que são declarados. Os métodos e construtores são referenciados no objeto Class, que mantém uma estrutura de dados com ponteiros para os métodos e construtores. Na inicialização de Class estes ponteiros são inicializados com cópias dos ponteiros dos métodos da superclasse, alguns destes são sobrescritos por outros métodos (e aí ocorre a sobrescrita) e são adicionados mais alguns ponteiros para os métodos novos.

Mas, voltando ao foco do tópico:

O VO (ou TO, ou DTO) contém getters e setters burros para todos os seus campos, o que não provê um encapsulamento verdadeiro (dá quase na mesma que ter todos os atributos públicos). Como objeto de negócio, apenas métodos de mais alto nível acessam os campos, provendo um encapsulamento verdadeiro, o que dispensa a necessidade da maior parte dos getters e setters.

Mas, e quando você utiliza algum tipo de framework, tal como Hibernate ou algo baseado em Reflection para construir ou alterar instâncias dinamicamente? Como você evita de ter que colocar getters e setters para todos os campos deixando o encapsulamento fraco e ao mesmo tempo permitindo que o tal framework faça o seu serviço direito?

No Hibernate você tem opção de colocar as annotations direto sobre os atributos ou nos getters (não sei no caso de XML, aprendi Hibernate já usando annotations e não gosto de XML…). No caso de colocar nos atributos, mesmo que esses atributos sejam privados e não existam os respectivos getters e/ou setters, o Hibernate acessa os campos através de reflection e seta/lê os valores sem problemas.

F

“Pelo que eu sei, não é assim que a banda toca. Já pensou se você tivesse 1000 objetos da sua classe QualquerCoisa instanciados, sendo que QualquerCoisa declara 4 métodos e esses métodos também fossem “instanciados”, ou seja, se houvesse 4000 métodos em memória?
Não é assim que acontece, os objetos possuem apenas seu respectivo estado. O código dos métodos está em algum lugar da memória mas é compartilhado por todas as intâncias. Logo, serialização não tem relação alguma com os métodos, métodos não são serializados, apenas dados (estado).”

Alguém mais me confirma isso?

P

Esse foi o principal engano que todo mundo causou com os DTOs. Eles foram feitos para diminuir o overhead do tráfego de rede, no tráfegos de objetos pelas camadas de rede(tiers/física) da sua aplicação, e não nas camadas da aplicação(layers/lógica).

Perfeito!!! DTO é para trafegar beans entre TIERS, nao entre LAYERS! Entre layers é perfeitamente aceitavel que layers diferentes acessem suas entidades de dominio!

V

fabiocsi:
“Pelo que eu sei, não é assim que a banda toca. Já pensou se você tivesse 1000 objetos da sua classe QualquerCoisa instanciados, sendo que QualquerCoisa declara 4 métodos e esses métodos também fossem “instanciados”, ou seja, se houvesse 4000 métodos em memória?
Não é assim que acontece, os objetos possuem apenas seu respectivo estado. O código dos métodos está em algum lugar da memória mas é compartilhado por todas as intâncias. Logo, serialização não tem relação alguma com os métodos, métodos não são serializados, apenas dados (estado).”

Alguém mais me confirma isso?

Sim, é isso.

G

:smiley:
http://forum.java.sun.com/thread.jspa?threadID=5142354&tstart=105
:stuck_out_tongue:

B

Ok, se o princípio é manter os dados e sua lógica juntos, o que faríamos então se o tal objeto é o grande objeto principal da aplicação? Como evitar que este se torne um Chuck Norris Object :lol: de 3000 linhas, mapeador ou agregador de dados vindos de 30 colunas de tabelas diferentes?

Não estaríamos sobrecarregando o papel dele?

B

Se existir algo como “grande objeto principal da aplicação”, em primeiro lugar, já é sinal de que seu problema é outro.

R

É, se realmente existir um ‘Grande Objeto Principal’ na sua aplicação, tipo um Canivete Suiço, é sinal que tem algo bem bizarro com o design de teu projeto.

E

olá amigos
abaixo topico longo e confuso, igual a minha cabeça quando penso nisso…

Sabe as vezes eu acho esse negocio de nomes em java um saco e passo a não levar a serio mais padrões de projeto…

Hoje usamos POJO (Plain Old Java Objects) Anotados…
quer dizer porque Martin Fowler em Setembro de 2000 usou a expressão para falar de objetos simples em java…
passamos a usar POJO… legal…

Pegunta 1:
Alguem sabe porque ele não usou JavaBean??? uma vez que JavaBean e uma coisa e Enterprise JavaBean e outra coisa completamente diferente…

Pergunta 2:
POJO não seria um JavaBean??? Uma vez que utilizamos os mesmos padrões de nomenclatura?

Pergunta 3:
Já DTO utilizamos para transferencia entre camadas, mais DTO’s não seriam POJO’s ? POJOS’s não passam por camadas? hoje com EJB3 e JPA representam entidades, Isso me lembra VO ???

Pergunta 4:
VO não seria um POJO?

Entity Beans esses sim não são POJO’s, ele falou de POJO para diferenciar um Objeto Java em relação a um Entity Bean não e isso?

honestamente? acho que esses caras (cada um investam um nome para tudo) na verdade estão protegendo os seus empregos e egos “investando” padrões que na verdade já existiam…

Porque já que temos que cultuar as pequenas diferenças de utilização,teremos que começar chamar POJO’s Anotados de “Plain New Annotated Java Objects”.

o cv a um tempo atraz fez um topico questionando o porque ninguem entendia o porque VO’s eram uma má ideia… na epoca o topico tomou outro caminho…

me sinto muito burro de não entender porque são uma má ideia…

porque quando penso como fazer um sistema distribuido sem passar as “entidades” para o cliente popular e me passar para persistir no meu humilde banco de dados, fila MQ enfim… sem VO’s, TO’s, DTO’ ou “raio que o parta O”

Alguem pode me ajudar a entender?

B

POJO não necessariamente é um JavaBean.

VOs/DTOs são POJOs, também. Só que não contém lógica de negócio. E a idéia defendida é justamente usar os POJOs para modelar a lógica de negócios - o que afasta a necessidade de VOs.

Não esquecer:

Se um sistema distribuído é realmente necessário… Bom, existem outros modos: http://tomayko.com/articles/2004/12/12/rest-to-my-wife
:wink:

F

No meu entendimento a questão toda é que objetos Java não são meros empacotadores de dados (o que equivaleria ao typedef struct da linguagem C).

Empacotadores de dados descaracterizam a idéia da orientação a objetos. Até mesmo as classes Wrapper do Java, apesar do nome, não são meros empacotadores, uma vez que oferecem métodos para facilitar operações com os tipos.

Assim, a pergunta que faz sentido para mim é: qual é a finalidade de agrupar um monte de atributos com getters e setters em um objeto sem atribuir funcionalidades (métodos com lógica de negócio) ao mesmo? Que eu creio que seja o cerne da questão.

Ainda mais considerando que na maioria desses casos nem mesmo a hierarquia chega a ser bem utilizada, acabando por descartar de vez a orientação a objetos.

O que uma Pessoa (classe Pessoa) tem e faz? nome, idade, sexo, etc… ela anda, pula, come e, extendendo a classe Pedreiro, trabalha em construções.

O que um VO tem e faz? Tem um monte de atributos e não faz nada, é cego, surdo, mudo e tetraplégico, e a menos que alguém na aplicação o carregue nas costas, serve só como peso morto a ser carregado, mesmo…

Assim, com certeza há design patterns mais modernos e inteligentes que colocam a funcionalidade, a regra de negócio, no objeto, junto com os seus atributos, em uma modelagem que faz uma utilização ampla e rica do paradigma OO, utilizando interfaces para proporcionar loose coupling.

Por exemplo o Spring com a IoC: veja que na IoC, por exemplo, o objeto não é mais só um peso a ser carregado… ele passa a ter inteligência… ele pode inclusive ter a flexibilidade de executar mais de uma lógica dependendo da injeção de dependência realizada…

R
Esta lógica de negócios a que vc se refere significa que o VO seria uma classe para um amontoado de dados sem ligação direta entre si? Tipo... no POJO, vc armazena todos os dados de uma tabela, no VO, vc armazena os atributos que vc necessita trafegar pela aplicação?

valew,

Rodrigo.

B

É, se realmente existir um ‘Grande Objeto Principal’ na sua aplicação, tipo um Canivete Suiço, é sinal que tem algo bem bizarro com o design de teu projeto.

Não é um canivete suíço, é um objeto que é o foco principal da aplicação.

Seria a classe ‘Pessoa’ num sistema de gerenciamento de pessoas, que visa agregar o máximo de informação sobre ela.

A classe ‘Venda’ de um grande sistema de vendas.

A ‘molécula’ em um sistema de simulação fisioquímica muito detalhado.

Basicamente aquelas classes típicas que podem juntar muita informação nelas. E mais típico ainda, você é o programador a a decisão da linda arquitetura não teve a sua participação/foi decidida há muito tempo.

A questão é, como agregar muitas funções de dados e lógica e manter a complexidade baixa?

F

Você já ouviu falar em dividir para conquistar?

É disso que a própria orientação a objetos se trata…

Desenvolvedores ortodoxos estabelecem até uma marca… acima de X linhas de código tá na hora de criar outra classe, porque a atual já está ficando desnecessariamente grande e complexa…

B

Não. Orientação a objetos se trata de colocar a lógica próxima dos dados, em pequenos “sistemas” que interagem entre si (objetos). Modelando a lógica em POJOs, é justamente isso que fazemos (e, notar, ninguém está defendendo que existam “getters” para todos os atributos - como escreveu o Kent Beck, deve-se expor mínimo possível de dados através de getters - quando há necessidade de expor muitos dados, sinal de que a lógica está longe deles e deve ser movida)

VOs vão contra os princípios da orientação a objeto. Foram uma solução para problemas criados por uma tecnologia que já passou.

Tendo seu domínio (“lógica”) modelado em POJOs, qual o problema de fazê-los transitar pela aplicação?

A

rdantas:
“bzanchet”:

VOs/DTOs são POJOs, também. Só que não contém lógica de negócio. E a idéia defendida é justamente usar os POJOs para modelar a lógica de negócios - o que afasta a necessidade de VOs.

Esta lógica de negócios a que vc se refere significa que o VO seria uma classe para um amontoado de dados sem ligação direta entre si? Tipo... no POJO, vc armazena todos os dados de uma tabela, no VO, vc armazena os atributos que vc necessita trafegar pela aplicação?

valew,

Rodrigo.

Eu acho que a “idéia” pelo o que eu entendi é outra, é na verdade não fazer do POJO apenas um amontoado de getters/setters com atributos privados, mas também ter métodos de negócio/regra de negócio , como na classe Pessoa, ter um método andar(), dormir() e comer() por exemplo…estou certo? Agora deixa ver se eu entendi, uma prática comum que eu vejo por ai é o pessoal usando a classe de domínio usada pelo hibernate por exemplo e encapsulando ela até um determinado layer da aplicação e daquele layer pra cima usar um outro objeto com a mesma representatividade pra tratar a lógica da apresentação e outras coisitas mas… isso sim é ruim e o certo seria eu usar a própria classe de domínio entre os layers e se o meu negócio necessitasse criar métodos para deixar ele mais “inteligente”, acertei?

E

Valeu por responder rapidinho…

bzanchet:
POJO não necessariamente é um JavaBean.

Sim e fato…

Como, como faço o mapeamento objeto relacional? vou ter que ter um parser para passar meus POJO’s com seus atributos de acordo com o negocio para os meus DTO’s que são “POJOS anotados” ??? isso e pratico?

uma frase que na pratica e bonita só pra não dizer nada…

Se meu sistema for distribuido (pelo amor de Deus, sem entrar no merido de precisa ou não) vamos assumir que sim, ele é, e sim ele precisar ser ok? e ai? como meu cliente vai acessar ? atraves de objetos simples na chamada da façade?

public void incluirCliente(Integer codigo, String nome, String sobreNome, String endereço, String[]  telefones) ....

ou vou distribuir ou meu ClienteVO, TO, DTO, XPTO ???

Não quero discutir se preciso ou não de distribuir meu sistema, estou questionando se não estamos fazendo marketing demais com nomes de objetos…

na pratica…

POJO = Qualquer objeto java.
VO, TO, DTO etc etc etc = Objetos que representam dominios de negocio (uma vez que as tabelas do banco representam no negocio)

POJO não e padrão de projeto e um simples nome “ponposo” e Martin Fowler falou e tudo mundo fica igual umas maritacas falandom (força de expressão apenas)

o que eu estou tentando dizer e que as vezes criamos um monte de sopa de letras que não tem muita diferença entre elas…

não acha que nós que trabalhamos com java fazemos isso? ou não? esses padrões são uteis, esses nomes são uteis e eu sou maluco(a chance de eu ser maluco e grande)…

Ai que eu volto a perguntar… porque VO’s são uma má ideia?

abraços

F

Eu trabalhei em um sistema que permitia fazer lançamentos… (não vou entrar em detalhes porque tem sigilo).

Nesse sistema, o coração eram os lançamentos.

Fizeram uma classe BLancamento com mais de 6000 linhas de código. TODOS os lançamentos se resumiam em chamar o método tratar() da classe BLancamento, passando pra ele um VLancamento.

Esse VLancamento era um VO gigantesco, com muitos atributos, e o método tratar() fazia milhares de IFs, chamando milhares de outros métodos que faziam milhares de outros IFs dentro da própria classe BLancamento.

O pessoal perdeu a oportunidade de bolar uma bela arquitetura, criando um lançamento básico abstrato e extendendo ele para créditos e débitos, extendendo os créditos e débitos para cheques, saques, etc, etc… e cada objeto desses, sendo um objeto “de verdade” (não só um saco de atributos) poderia ter a lógica adequada para tratar o seu próprio caso.

E os lançamentos mais específicos poderiam herdar lógica dos lançamentos mais gerais…

Cada classe poderia ficar pequena, fácil de compreender mesmo por quem não conhecesse a aplicação, caracterizando uma manutenção simples e rápida, uma escalabilidade eficiente…

É possível perceber o quanto uma arquitetura boa pode facilitar a vida de todo mundo envolvido no projeto?

Classes boas não são classes grandes e difíceis cheias de códigos que ninguém entende. Muito pelo contrário: classes boas são as que até um iniciante entende facilmente.

Só que pra desenvolver um sistema complexo com classes tão simples que até um iniciante entenda, é preciso ter muita experiência com arquitetura, uma arquitetura rica possibilita uma modularidade e um baixo acoplamento suficientes para que cada classe realize com eficiência apenas o mínimo necessário.

B

Eu particularmente não acho que eles sejam uma má idéia. Eles servem seus propósitos.

Mesmo para POJOs, eles também servem seus propósitos.

O que eu acho má idéia é ser radical pra qualquer lado.

Seja nem 8 nem 80. Dá pra fazer ótimas aplicações usando qualquer um deles.

Como o Fox disse, é preciso ter muita experiência com arquitetura para fazer algo simples. Estranho não?

B

Quem está falando de mapeamento objeto-relacional? Isso é oooutra história.

edpipole:
como meu cliente vai acessar ? atraves de objetos simples na chamada da façade?

public void incluirCliente(Integer codigo, String nome, String sobreNome, String endereço, String[] telefones) ....


Tu sabes o que é sistema distribuído, mesmo? Acho que não estamos falando a mesma língua.

Qualquer, não. Qualquer old java object. :wink:

Ei, peraí. Se as tabelas do banco representam o negócio, pra que objetos, em primeiro lugar?

São uma má idéia porque afastam a lógica dos dados - quando, ao usar OO, estamos justamente tentando aproximar as duas coisas!

F

Em termos musicais, o tema da 9ª sinfonia de Beethoven é uma das coisas mais simples que existem. Notas fáceis, ritmo descomplicado… e é uma das obras mais conhecidas e aclamadas no mundo todo desde que foi composta.

Mas foi preciso um Beethoven para mostrar a grandeza de uma coisa simples… e ele só o fez após ficar surdo.

Ele só o fez quando deixou de ouvir a música com os ouvidos e passou a ouvi-la com a alma…

Mas só quem ama aquilo que estuda chega nesse ponto…

E para isso é preciso transpôr, às vezes, a correria prática do cotidiano dos projetos…

Quantas vezes somos incapazes de resolver um problema no trabalho, algum algoritmo, e depois em casa, embaixo do chuveiro, relaxados, de repente temos uma idéia que resolve o problema?

Bom, o ser humano ainda usa menos de 10% da sua capacidade cerebral durante toda a sua vida, a maioria não chega a 6%…

E é tão fácil a gente se julgar conhecedor de alguma coisa… quando isso mesmo nos impede de crescer mais…

Hehehe, deixa eu parar com esse momento filosófico antes que alguém tenha uma reação alérgica…

E

Falei pro Fox que eu ia ser insultado… mais vamos lá…

Também acho que não e 8, 80 na verdade e isso que estou tentando explicar, porque para mim sistemas grandes apenas com POJOS de negocio com os atributos ficam uma zona a longo prazo…

bzanchet, tudo bem…

vamos assumir que eu seja esse idiota que vc esta tentando dizer que eu sou…

Por favor parece simples demais pra você, me explica como eu faço um sistema usando apenas POJOs de negocio (Business Objects) com os atributos necessarios para cada BO dispensando os VOs dessa forma…

1 -) eu vou ter que fazer um parser de objetos para minha camada de persistencia… se não como? porque minhas entidades no banco refetem sim o meu negocio… isso e simples? facíl de manter?

2- ) O relacionamento entre as entidades sera apenas na persistencia?

3-) Como o mapeamento objeto relacional pode ser “outra coisa” se meu negocio tem que integir com ele o tempo todo?

estou pensando no todo…

Algum caso de sucesso? sem VOs e derivados? ou isso e apenas teoria? eu acho dificil manter parsers para os DTO`s do BO em diante… eu diria custoso para equipe…

nos projetos que eu tenho feito arquetura nos ultimos 3 anos sempre usei VOs, ou TOs ou DTO`s de ponta a ponta… sem parsers, pois sempre que tentei usar dava um trabalho danado por pouca recompensa…

E

Me ensina isso também… tabelas não representam o negocio?
Quando eu olho um banco eu vejo o negocio do cliente, uma pizzaria, tem a tabela de pedidos, de entregas, estoque essas coisas… não e isso?

Mais você concorda eu que vou ter que fazer um parser para popular os objetos do meu mapa relacional?
se sim, esse parser não e um saco de fazer em um sistema enorme?

além das interfaces o que eu passo para meu querido cliente remoto? caso eu tenho um? essa solução de unir negocio e dados e viavel para distribuir? não? sim? porque?

e cv tinha razão e dificil entender mesmo…

P

Orientação a Objetos tem décadas e até agora nada tomou seu lugar nod esenvlvimento de aplicações então esse ‘longo prazo’ é estranho :wink:

Não. Qualquer framework moderno (Hibernate/JPA, Btais, TopLink…) suporta o uso de objetos simples, não de DTOs. Na verdade estes frameworks encorajam o uso de objetos de negócio no lugar de objetos burros.

Não entendi essa pergunta

Mapeamento Objet-Relacional não faz parte da Camada de negócios, faz parte da Camada de Persistência. Objetos de negócio interaem entre si quando é preciso persistir algo ou buscar uma informação no banco isso é delegado à Camada de Persistência.

A grande maioria dos projetos utilizando Sping (desde a primeira versão), Hibernate, JPA ou coisa parecida seguem este modelo. EJB 3.0 é exatemnte sobre simplificar o modelo e conseguir criar objetos de negócio de verdade, sem DTOs.

Não existe a necessidade de parser.

edpipole:
bzanchet:

Ei, peraí. Se as tabelas do banco representam o negócio, pra que objetos, em primeiro lugar?

Me ensina isso também… tabelas não representam o negocio?
Quando eu olho um banco eu vejo o negocio do cliente, uma pizzaria, tem a tabela de pedidos, de entregas, estoque essas coisas… não e isso?

Num sistema orientado a objetos o que representa o negócio é seu modelo de objetos não seu modelo de dados. Na maioria das vezes o modelo de dados vai servir apenas para persistir os objetos.

Ah, acho que agora entendi o parser. isso não é um parser, é apenas um objeto que az mapeamento entre conceitos diferentes e existe um adrão muito difundido para isso: DAO, ou seu ‘pai’ genérico Data Mapper.

Depende do que você quer que eu cliente remoto faça. Se você possuir interfaces de granularidade baixa pode passar os próprio objetos serializados e azer chamadas remotas, se não pode utilizar o DTO: ele foi feito para isso.

E

acho que estou me expressando mal pra caramba…

eu sei que quem busca as coisas do BD e a camada de persistencia, mais que tipo de objeto ela vai me trazer? não seria um objeto simples? que representa uma tabela e seus relacionamentos?
quando eu pegar essa objeto simples não vou tratar seus dados na minha camada de negocio?

e disso que estamos falando não e mesmo?

Me ensina isso também… tabelas não representam o negocio?
Quando eu olho um banco eu vejo o negocio do cliente, uma pizzaria, tem a tabela de pedidos, de entregas, estoque essas coisas… não e isso?

Num sistema orientado a objetos o que representa o negócio é seu modelo de objetos
não seu modelo de dados.
Na maioria das vezes o modelo de dados vai servir apenas para persistir os objetos.

O banco ainda e relacional por isso fazemos o Mapeamento Objeto Relacional, mais o banco tambem representa o negocio
segundo o conceito dele, quando vou para meu sistama ai os meus objetos passam a representar segundo o seu conceito…

Sim acho que você entendeu, Data Mapper… isso mesmo…

O meu ponto nisso tudo e quando e custoso mapear as entidades do banco para objetos simples, depois mapear os objetos simples
para meus Objetos de negocio que foram desenvolvidos sem nem tomar conhecimento do banco de dados, na hora de persistir isso e um
saco ficar passando valor de um objeto para outro, o custo gerencial, garantir que o meu clienteBO tenha os mesmos atributos
que meu Objeto de banco para depois persistir isso tudo, nomes de campos e etc…

fizemos um projeto grande assim um tempo atraz, 20 desenvolvedores, desenvolvendo sem tomar conhecimento do banco, trabalhando apenas com
o Objeto de negocio, enfim… quando tinhamos que pegar algo no banco, tinhamos que acessar o DAO pegar o Objeto que vinha mapeado,
depois setar os atributos na minha BO e usar, para persistir tinhamos que pegar os valores que estamos trabalhando setar
nos Objetos de Mapeamento do banco e depois persistir…

era muito custoso…

você concorda com isso?
eu prefiro pegar o Objeto do banco o usalo ponta e ponta, fica mais simples de trabalhar com a informação…
o que vocês acham? entenderam o que eu fiz dizer?

Depende do que você quer que eu cliente remoto faça.
Se você possuir interfaces de granularidade baixa pode passar os
próprio objetos serializados e azer chamadas remotas, se não pode utilizar o DTO:
ele foi feito para isso.[/quote]

legal mais ai usamos ele(DTO) ponta a ponta…

B

edpipole:
O meu ponto nisso tudo e quando e custoso mapear as entidades do banco para objetos simples, depois mapear os objetos simples
para meus Objetos de negocio que foram desenvolvidos sem nem tomar conhecimento do banco de dados, na hora de persistir isso e um
saco ficar passando valor de um objeto para outro, o custo gerencial, garantir que o meu clienteBO tenha os mesmos atributos
que meu Objeto de banco para depois persistir isso tudo, nomes de campos e etc…

Não! Quando defendemos a modelagem da lógica de negócios em POJOs, é justamente isto que estamos evitando. São seus objetos Cliente, Pizza, Mozzarella, Calabresa, que vão deixar de ser “burros” e vão passar a ter lógica (junto aos dados). E que podem ser persistidos para o banco quando necessário - sem “parser” nem “clienteBO”.

E

bzanchet:
edpipole:
O meu ponto nisso tudo e quando e custoso mapear as entidades do banco para objetos simples, depois mapear os objetos simples
para meus Objetos de negocio que foram desenvolvidos sem nem tomar conhecimento do banco de dados, na hora de persistir isso e um
saco ficar passando valor de um objeto para outro, o custo gerencial, garantir que o meu clienteBO tenha os mesmos atributos
que meu Objeto de banco para depois persistir isso tudo, nomes de campos e etc…

Não! Quando defendemos a modelagem da lógica de negócios em POJOs, é justamente isto que estamos evitando. São seus objetos Cliente, Pizza, Mozzarella, Calabresa, que vão deixar de ser “burros” e vão passar a ter lógica (junto aos dados). E que podem ser persistidos para o banco quando necessário - sem “parser” nem “clienteBO”.

hum… legal… mais ai caso tenha um cliente remoto, tenho que seguir o conselho do pcalcado e minhas interfaces irão receber objetos simples serializados? mesmo porque não vou poder passar esse POJO uma vez que ele tem a regra de negocio junto certo?

J

Bom, nessa situação, como ja foi dito antes, o uso de VO/TO/DTO/BLA… se justifica.
E caso vc for usar, p/ copiar os valores das propriedades entre eles, vc pode usar o bom e velho BeanUtils.copyProperties(beanDestino, beanOrigem);

[]´s

E

jgbt:
edpipole:

hum… legal… mais ai caso tenha um cliente remoto, tenho que seguir o conselho do pcalcado e minhas interfaces irão receber objetos simples serializados? mesmo porque não vou poder passar esse POJO uma vez que ele tem a regra de negocio junto certo?

Bom, nessa situação, como ja foi dito antes, o uso de VO/TO/DTO/BLA… se justifica.
E caso vc for usar, p/ copiar os valores das propriedades entre eles, vc pode usar o bom e velho BeanUtils.copyProperties(beanDestino, beanOrigem);

[]´s

tudo bem, então agora eu entendo quando falam VO/TO/DTO/XPTO não e uma boa ideia…
para sistemas não distribuidos podemos sem problemas usar POJO’s.
BeanUtils.copyProperties(beanDestino, beanOrigem);
contanto que os nomes dos atributos sejam os mesmos… isso vale…

para sistemas distribuidos também podemos usar POJO’s contanto que tenhamos o cuidado de manter a estrutura dos atribudos dos POJO’s em relação aos TO’s/VO’s/DTO’s/XPTO’s ai podemos usar o BeanUtils por exemplo… caso contrario teremos que estar dispostos a saber que o Desenvolvedor que criou a variavel nomeUsuario do DTO pensa diferente do desenvolvedor que criou o atributo usuario no POJO .
ai setamos de um para o outro na mão…

e ai? entendi?

V

Ok, deixa eu tentar imaginar um sistema qualquer sem VOs (ou qualquer outro nome sinônimo):

Vamos supor que eu queira saber quais os funcionários que trabalham em uma determinada empresa e rodar a folha de pagamento deles (um exemplo muito comum do dia-a-dia de sistemas CRUD).

Aqui eu já começo com uma instância da empresa. Utilizo o método getFuncionarios nela, que vai a camada de persistência e chama um método que FABRICA instâncias de funcionários. Correto?

Vamos supor que eu decida fazer usando a JDBC diretamente (sem reflection, hibernate, JPA e nada disso). Eu teria que ter setters para todos os campos para poder setar um valor para cada um deles conforme eles são lidos do banco, ok?

Vamos supor que eu pegue uma ferramenta de reflection que o meu primo criou que acessa os campos ou os setters automaticamente (seja por annotations, reflection bruto, xml, bola de cristal ou qualquer coisa). Ele vê a coluna NOME no ResultSet e chama o método setNome do funcionário que ele recém criou. Correto?

Quando a camada de persistência devolver a lista de funcionários para o objeto de negócio da empresa, beleza. O objeto de negócio chama os métodos de negócio que quiser (inclusive getters e setters), mas no geral são métodos de negócio.

Suponha que você queira cadastrar/inserir um novo funcionário na empresa X. Neste caso você instancia o funcionário com todos os campos com valores iniciais 0 ou null, dá um setEmpresa nele, chama o método setIsso, setAquilo e no final chama o método persistir, que chama a camada de persistência e gera uma SQL INSERT INTO …

Para preencher os valores do PreparedStatement do INSERT, será preciso utilizar os getters.

Agora chegamos no ponto: O objeto de negócio tem os campos para armazenar a informação. Setters burros para receber dados da camada de persitência e getters burros para passar dados a camada de persistência. Pronto! Seu encapsulamento foi pro saco porque no fim das contas o que você fez foi apenas criar VOs anabolizados onde você enfiou um monte de métodos de negócio e decidiu chamá-los de camada de negócio.

E então, como corrigir o modelo acima?

E

cara pra mim isso e tão nebuloso mais o pessoal fala tão bem que as vezes me lembro do chapolim falando da roupa invisivel que apenas os inteligentes podiam ver a roupa…

não consigo imaginar um sistema sem Objetos de “burros” para passar os dados de um lado para o outro…
fica bagunçado… como seu exemplo acima…

“Porque segundo a OO Objetos metodos e dados devem ficar no mesmo Objeto”…
isso e pratico? eu acho que não…

B

Primeiro, seu encapsulamento não foi pro saco. Se os dados são acessados por métodos, estão encapsulados. Mas ninguém está discutindo encapsulamento, de qualquer jeito. Não vale a pena misturar (mais) um assunto.

E, não, não há o que corrigir. Se o seu modelo é pobre, o seu modelo é pobre, ué. Se 70% do trabalho é fazer persistência no banco, que tal procurar alternativas onde essa tarefa pode ser feita de forma mais simples, hein?

Tu achas que não, é? E isso é argumento, agora? :? Que tal elaborar um pouco mais essa resposta?

E

ha… na boa… tanto faz…

abraços

F

Por que não dividir a resposta em uma ou mais situações onde o uso de VOs é indicado?

Por exemplo, eu tenho um sistema que utiliza os seguintes frameworks:

:arrow: JSF
:arrow: Hibernate

e não é distribuído, devo utilizar VOs? E o que dizer de BOs?

Falou

V

Eu não disse que o modelo é pobre, eu não disse que 70% do trabalho é persistência no banco e mesmo que você troque a JDBC na unha por um JPA ou qualquer outro método de persistência em um layer a parte, o resultado é o mesmo. O que eu tentei expor aqui é que o fato de haver uma camada de persistência força você a ter getters e setters para todos os atributos. E, como exposto no trecho do artigo da fragmental que eu copiei e colei aqui em cima, o encapsulamento vai para o saco.

E o objetivo aqui é exatamente migrar do modelo anêmico para o modelo ideal. O que eu coloquei no meu post anterior já é mais da metade do caminho, pois os BOs e os VOs já foram unificados. Mas ainda não é o modelo certo, pois o encapsulamento ainda tá no saco.

C

Pq nao existe nenhuma situacao onde usar VOs ou BOs eh indicado. DTOs, outro padrao relativamente proximo, eh pra ser usado apenas em sistemas distribuidos, e mesmo assim apenas quando os dados a ser trafegados precisam de uma granularidade diferente do que a com que o sistema trabalha internamente.

F

Pq nao existe nenhuma situacao onde usar VOs ou BOs eh indicado.

Ok, aprendi OO e sei que isso não faz parte do conceito MAS a sua resposta não deu margem para nada, ou seja, implicitamente quer dizer que quem usa ou usou, cometeu um erro arquitetural!

É isso?

B

Muito interessante a citação, mas acredito que a sua interpretação foi errada! Veja bem, o VO pode entrar em estado inválido justamente porque ele não contém lógica - apenas getters/setter burros - e portanto não pode “se proteger” de um estado inválido (no modelo anêmico, essa lógica estaria somente no “BO”). Levando em conta que VOs contém getters/setters “burros” para todos os atributos, aí sim podemos dizer que não há encapsulamento.

No caso da lógica modelada num POJO, o métodos de acesso podem (e devem) conter lógica, modelando o mundo real, podendo assim evitar estados inválidos, por exemplo. Dados encapsulados.

É possível evitar a necessidade de getters e setters, mas não vejo grande benefício em fazer isso. Já que os POJOs contém a lógica de negócios, escrever getters e setters “inteligentes” onde necessário são uma garantia de que o encapsulamento não foi “pro saco”, não.

R

Pq nao existe nenhuma situacao onde usar VOs ou BOs eh indicado.

Ok, aprendi OO e sei que isso não faz parte do conceito MAS a sua resposta não deu margem para nada, ou seja, implicitamente quer dizer que quem usa ou usou, cometeu um erro arquitetural!

É isso?

Eu já acho que usar VO não é errado. Errado é usar VO e achar que está programando OO. Separar o código entre dados e operações é escrever Pascal em Java. Se é isso que você quer, vai fundo e seja feliz. Mas aí seja honesto e exiba os atributos como públicos em vez de criar pares get/set e achar que está encapsulando alguma coisa.

P

rubinelli:

Eu já acho que usar VO não é errado. Errado é usar VO e achar que está programando OO. Separar o código entre dados e operações é escrever Pascal em Java. Se é isso que você quer, vai fundo e seja feliz. Mas aí seja honesto e exiba os atributos como públicos em vez de criar pares get/set e achar que está encapsulando alguma coisa.

Então você não está usando TO (VO é outra coisa ha um bom empo), você está usando estruturas de dados, pura e simplesmente. P padrão TO serve para meia dúzia de problemas causados pela complexidade acidental do EJB 2.x, e mesmo para isso existem alternativas.

R

victorwss:

Eu não disse que o modelo é pobre, eu não disse que 70% do trabalho é persistência no banco e mesmo que você troque a JDBC na unha por um JPA ou qualquer outro método de persistência em um layer a parte, o resultado é o mesmo.

Com Hibernate, JPA e outros ORM, persistência não é nem 5% do trabalho. Dá pra fazer o mapeamento do projeto inteiro em 1 dia (é meio BDUF, mas dá pra fazer). Você está trabalhando com uma abstração de uma entidade, e com isso, pouco importa o que ocorre na persistência. Não é trabalho nosso. É trabalho do framework.

R

felipeguerra:
Por que não dividir a resposta em uma ou mais situações onde o uso de VOs é indicado?

Por exemplo, eu tenho um sistema que utiliza os seguintes frameworks:

:arrow: JSF
:arrow: Hibernate

e não é distribuído, devo utilizar VOs? E o que dizer de BOs?

Falou

Dá uma olhada nos exemplos do Jboss Seam que fica mais claro. Action Frameworks tradicionais forçam um pouco você a usar DTOs pois trabalham com a abstração de um HtmlForm. Com um framework mais moderno como o Seam, a própria entidade pode ser manuseada na camada de view, sem ter objetos burros trafegando de um lado para o outro para serem persistidos na camada inferior. Avoid too many layers.

O Seam tem outros problemas (estamos no mundo real), mas não precisamos de DTOs de jeito nenhum, só nos casos já citados (o que precisa aparecer na tela é algo granularmente diferente da entidade, exemplo, você precisa apresentar os pedidos agregados por cliente, ou mostrar o valor total das compras por mês e local de entrega). Com EJB3 e Managed States das Entidades nem mesmo um sistema distribuído necessariamente precisa usar DTOs. Já desenvolví aplicações grandes com cliente Swing e meus entity beans saiam do servidor e iam para o cliente sem precisar de DTOs.

R

Somente dados não representam o negócio. Na análise estruturada a gente se enganava achando que o MER representava o negócio. Não representa! Seu modelo de tabelas nada mais é que um conjunto relacional de dados.

Sistemas orientados a objetos são orientados a objetos e não orientados a tuplas. E olha, as tabelas não interessam, bom, para falar a verdade elas interessam muito pouco. Nesse mundo de Hibernate, JPA, iBatis e etc, faz uns bons 3 anos que não ligo para o banco de dados. O que interessa são os objetos.

C

Exatamente. Que bom que estamos claros no assunto :wink:

R

Eu ja tive algumas discussões com o autor desse artigo, mas eu aconselho que vcs leiam pois os conceitos são complicados.

http://fragmental.com.br/wiki/index.php/Fantoches
http://fragmental.com.br/wiki/index.php/Evitando_VOs_e_BOs

Segue abaixo uma parte do texto que retrata o problema.
É um bad smell se seus objetos são guiados através de forças ocultas, se seus objetos se
comportam como marionetes sendo manipuladas por uma função-mestre, o mestre dos fantoches

V

Bem, até aqui ok. Getters e setters burros apenas são uma forma de tornar os atributos públicos mantendo-os privados. Acessar os campos diretamente com setAccessible(true) é uma aberração.

O problema aqui é evitar que o objeto de negócio entre em um estado inválido.
Vamos ver o que o framework de persistência faz para criar um objeto que ele leu do banco de dados:

Hipótese 1: Ele usa o construtor sem parâmetros do objeto de negócio e cria um objeto Funcionario sem nome, sem data de nascimento, sem CPF, sem nada. Ao término do construtor ele já terá nascido inconsistente.
Porém, a medida que o framework lê campos do ResultSet ele invocará os setters e preencherá o objeto de negócio e no fim espera-se que ele seja válido.

Hipótese 2: Ele usa o construtor que recebe um caminhão de parâmetros e cria um objeto Funcionario que em essência já nasce pronto.

Pois bem, o problema da hipótese 1 é que o objeto já nasce em estado inválido. O problema da hipótese 2 é que cria-se um tipo forte de acoplamento entre o framework de persistência e um construtor muito frágil do objeto de negócio (frágil porque qualquer mudança no objeto força uma mudança na assinatura do construtor).

Então agora estamos na frente de mais um problema no caminho rumo a arquitetura ideal: Como evitar de se ter um construtor com uma assinatura frágil e gigantesca e ao mesmo tempo permitir que o objeto nunca esteja inválido, nem mesmo logo após ser instanciado?


Não é nem 5% do trabalho se você considerar que o banco de dados é bem estruturado, não há nada de legado nele, você tem controle total sobre o banco, que não há registros inconsistentes e que nunca é necessário usar-se alguma Stored Procedure para fazer-se alguma maluquice. Quando o negócio é assim, realmente tudo são flores. Mas o problema é quando você tem que lidar com bancos de dados legados problemáticos pertencentes a terceiros, que são usados por diversas outras aplicações e estão em produção. Como lidar com isso sem criar monstros arquiteturais e POGs?
Ok, neste caso acredito que não haja dúvidas de que o certo seria mandar o DBA para a cadeira elétrica e daí o coitado do programador é que vai ter que se virar em lidar com esse tipo de coisa. Mas aí o problema não é só do framework, passa a ser problema do programador fazer o framework conseguir digerir o pepino. Ou seja, o mapeamento objeto relacional é 5% do trabalho SE E SOMENTE SE você tem liberdade para fazer o que quiser com a estrutura do banco de dados.

P

Se o consrutor não garante a invariante do seu objeto ele deve ser isntan ciado por uma factory, e frameworks de persistência agem como factories.

V

Ok, então o framework chama a factory.
Mas, logo após o framework chamar a factory, antes de chamar qualquer setter. Em qual estado estaria o objeto?
Ou o framework passa um caminhão de parâmetros ou o ResultSet para a factory e ela se vira?

C

O que o shoes quis dizer eh que o framework eh a factory.

V

Ok, então continuamos no mesmo lugar.
O framework (que age como factory) para produzir uma instância do objeto pode ou chamar o construtor sem parâmetros que faz o objeto nascer insconsistente, mas logo em seguida vários setters são chamados pelo framework de forma que ele saia do framework consistente.

Ou então o framework chama o construtor passando um caminhão de parâmetros.

P

Não. A Fatory substitui a chamada ao construtor, obviamente que ela chama o construtor mas exceto pelas factories ninguém mais o faz. Quando precisa de um objeto dessa classe os outros usam factories. Dessa orma voc6e nucna vai ter objetos inválidos.

De qualquer modo, o que o artigo fala não é sobre invariante na cosntrução do objeto e sim pré/pós condições de um método.

R

O próprio uso do DAO já não seria um problema ? pois o DAO iria ser um fantoche manipulando as informações do banco de dados.

P

DAO Não é objeto de negócio então aidna que seja rpeferível que ele seja um objeto ‘de verdade’ acho que não é o maior problema e não o for. De qualquer modo o DAO não é um fantoche, ele é um conversor que pega uma estrutura de dados (i.e. resultsets) e transforma em outras (i.e. objetos de negócio)

V

Sobre o artigo (é você o autor ou você só publicou?), o que eu me referia mesmo era acerca do parágrafo sobre o encapsulamento.


Ok, mas dentro do método da factory, por alguns nanosegundos após o construtor ter rodado o objeto está em estado inválido, não? Pergunto isso porque dependendo do tipo de verificação de consistência que for feito no objeto de negócio, ela pode fazer a factory falhar lançando alguma exceção (exemplo: IllegalStateException) pelo simples fato de o objeto nascer inconsistente, mesmo que ele fosse ficar neste estado por menos de um milisegundo.

E outra, isso ainda me força ter setters burros para serem usados pela factory?

P

victorwss:

Sobre o artigo (é você o autor ou você só publicou?),

é meu mesmo

eu também

Sim, mas isso Não é relevante. Se você não utilizar código sincronizado num construtor é muito fácil fazer um objeto ficar em estado inválido, basta preemptar thread atual e chamar o objeto em outra thread. Da mesma forma você pode tornar o código que isntancia o objeto via factory thread safe.

Se a fração de segundo que o objeto fica em estado inválido é importante paravocê então seja com factories ou diretamente com construtores você tem que utilizar código thread safe.

victorwss:

E outra, isso ainda me força ter setters burros para serem usados pela factory?

Acho que não entendi exatamente o que você está chamando de objetos burros, ou não entendi a pergunta. Pode elaborar?

V

Sobre a parte do synchronized, ok. Acho que isso deve resolver.

Os setters burros, são setters que não fazem nada mais além de repassar o valor para o atributo. Assim como getters burros nada mais são do que getters que simplesmente retornam o valor do atributo.

Não há nada de errado com o getter burro, mas ter setters burros é ruim pois facilmente o objeto entra em estado inválido.

É óbvio que um setter vai verificar os parâmetros e tal para certificar-se que o objeto não entra em estado inconsistente. O problema é quando, por exemplo, para ser consistente deve-se ter ambos o UF e a cidade ou então nenhum deles.
Quando a factory invocar o método setUF, ele vai ver que a cidade é nula e lançar uma exceção, o que faz com que o objeto não possa ser corretamente fabricado. Por outro lado se o método setUF não fizer a verificação, nada garante que o método setCidade seja chamado posteriormente, o que pode deixar o objeto inconsistente.

Outro problema de ter tais setters é que por exemplo: Eu não quero que o atributo X possa ser alterado fora da minha classe de negócio (mas dentro sim). Vamos supor que esse atributo X corresponde a um campo vindo de uma tupla no banco de dados. Só que o problema é que para a factory poder setar este campo, eu tenho que ter um método público setX que não é bem-vindo. Esse tipo de problema o friend do C++ ou algum outro tipo de visibilidade mais fine-tuned que existe em outras linguagens resolveria, mas e no java como fica?

R

Ok, você está usando o seu TO ou DTO para fazer course-grained RPC. Isso não é procedural também?

R

Isso é onde eu queria chegar. O DAO também funciona como o cerne do mecanismo de persistencia, como vc mesmo disse, ele pode pegar uma estrutura de dados (i.e. resultsets)e transformar em outras (i.e. objetos de negócio). Porem existe um problema que eu não consigo abstrair completamente: Como definir o objeto de negócio ?

Lendo os conceitos no artigo, e no próprio livro do DDD, o objeto de negocio é algo claro de se entender no mundo real mas dificil de por em prática de uma forma não procedural. Analizando os conceitos do DAO e implementando este no meu código eu me sinto como na dita frase Bad Smell: Você olha, cheira, vê que tem algo errado, e tem que descobrir a causa.

O cheiro ruim é devido ao DAO fazer todo o encapsulamento de persistencia, tirando essa lógica do objeto de negócio. Portanto… para persistir um crédito na conta corrente de um cliente eu preciso recorrer aos mecanismos do DAO pois este processo envolve uma série de transações com outros objetos de negocio.

Adotando o processo acima eu acabo criando outro problema, pois no conceito do DAO, este pode somente manipular um objeto de negocio, ou seja, um DAO para cada tabela no banco de dados, e consequentemente para cada POJO

Portanto para resolver esse problema começamos a usar os chamados BO, este por sua vez pode fazer uso de quantos DAOs forem necessários, pois para persistir um crédito na conta corrente do cliente, é necessário remanejar mais que um objeto de negócio.

Fazendo isso nós caimos no chamado modelo anêmico do Fowler, o que irá nos trazer mais problemas e voltamos ao tópico inicial: Como evitar tudo isso ?

A solução seria colocar a nossa lógica de nogócio nos objetos de negócio, e isso parace muito claro. Mas ao fazer isso nos encontramos os já conhecidos problemas da persistencia e do controle da transação. Mesmo assim algumas pessoas começaram a fazer isso:

Fornecedor fornecedor = ?; List contas = fornecedor.getContasPagasDesde1999()
Sim, por tráz das cenas o método getContasPagasDesde1999() irá usar um repositório, e esse repositório pode ser a implementação de um DAO, e sinceramente ainda sinto um Bad Smell :? pois acredito que seja possível fazer isso com C e por favor me corrijam se estiver errado pois eu conheço pouco de C.

V

Você está chegando aonde eu quero chegar também. O que nos empurra a um modelo anêmico é o DAO e o problema de evitar o modelo anêmico começa a se reduzir a evitar que o DAO seja intimamente acoplado ao objeto de negócio.

O único lugar que você falou besteira foi na parte de programar em C. C faz tudo e qualquer coisa. As partes do java que não foram feitas no próprio java são feitas em C e C++, e um dos grandes problemas do C é justamente este, nada te impede de fazer cagada. Mas isso já está offtopic.

R

Desculpa não ter mencionado, mas a referência que eu faço ao C é a mesma sobre o artigo do Fantoche.
Vou tentar lhe poupar tempo com o texto a seguir e esclarecer um pouco o porque da referencia ao C, mas também peço que leia o artigo novamente e com mais atenção.

Se vc esta fazendo um programa em java para controlar um estacionamento, como no exemplo do artigo, e por acaso vc também consiga fazer o mesmo programa em C e ver que a maior diferença esta na mais fútil convenção de nomenclatura, então irá perceber que existe alguma coisa errada.

Dito a frase acima, pense: Se o C que é uma linguagem procedural consegue fazer a mesma coisa que eu numa linguagem orientada a objetos é porque existe alguma coisa de errada, e com certeza não é a linguagem, e sim a forma de como vc esta escrevendo os seus programas.

S

Simples. Chame DAO ao BO e chame TableGateway ao DAO.

O ponto é que DAO não é aquilo que normalmente se vê por ai. Um DAO por entidade é um design furado e por isso tem todos esses problemas. No fim vc precisa de um orquestador para multiplos dao.
Entenda que vc sempre deve ter esse orquestador, pois é o logico. Chame de BO, Repositorio ou qq outra coisa, o fato é que vc quer persistir um objeto complexo que se espande por multiplas tabelas.
A função do DAO é converter comandos java em comandos SQL e isso deve ser feito por meio de mecanismos abstractos.

Enfim, vc precisa de um design mais poderoso e afinado se quer ter persistencia inteligente.

P

ronildobraga:
O cheiro ruim é devido ao DAO fazer todo o encapsulamento de persistencia, tirando essa lógica do objeto de negócio. Portanto… para persistir um crédito na conta corrente de um cliente eu preciso recorrer aos mecanismos do DAO pois este processo envolve uma série de transações com outros objetos de negocio.

Acho que você não está levando em consideração uma coisa muito importante: persistência é um cocneito ortogonal a negócio. "Persistir uma C/C"não é regra de negócio, é limitação tecnológica. O DAO e seus amios servem para ajudar a contornar os problemas causados por essa limitação.

O que você precisa fazer é executar a regra de negócio apenas com objetos e persistir o estado final. Voc6e executa a regra de negócio e depois “aperta o botão salvar”. Até você “apertar o botão” nada de persistência é envolvido (não diretamente).

Como você usa os objetos que fazem as regras não depende de existir um objeto burro ou inteligente -se o DAO cospe estruturas de dados ou objetos. Isso, como falei, é ortogonal.

Você pode fazer isso com C(com adaptações) e isso não é problema. O problema é programar em java comos e programa em C e não programar em C como se programa em Java.

O Repositorio existe exatamente para abstrair a existência de um DAO do modelo de negócios. Ainda não entendi porque um DAO acarretaria em BO/TO.

V

Sim, quanto a esse negócio de utilizar um DAO por tabela, isso só funciona para CRUDs simples. O DAO deve utilizar várias tabelas. e criar objetos de negócio cujas regras podem estar em várias tabelas. Até aqui ok.

O porque do DAO te empurrar para o modelo BO/TO é por causa daqueles setters e getters. O DAO precisa de getters e setters (normalmente burros) no objeto que ele está manipulando. Isso nos leva ao modelo onde a consistência do objeto de negócio poderia ser quebrada facilmente por causa desses setters e getters. Para “resolver” isso, a “solução” seria separar esse objeto em BOs e TOs, ou seja, o modelo anêmico.

O problema aqui é que é preciso alguma outra estratégia para fazer o DAO poder acessar os dados internos do objeto de negócio enquanto este está sendo criado. Ou seja, volto ao que coloquei no meu post anterior:

E então, no java como fica?

B

Meu palpite é que exigir “cidade e UF ou nenhum deles” sendo estes campos independentes no POJO é um bad smell por si só.

A outra sugestão é fazer o setter garantir o estado válido (lançando IllegalStateException) e fazer a ferramenta de ORM preencher os valores via reflection.

S

victorwss:

O porque do DAO te empurrar para o modelo BO/TO é por causa daqueles setters e getters. O DAO precisa de getters e setters (normalmente burros) no objeto que ele está manipulando. Isso nos leva ao modelo onde a consistência do objeto de negócio poderia ser quebrada facilmente por causa desses setters e getters. Para “resolver” isso, a “solução” seria separar esse objeto em BOs e TOs, ou seja, o modelo anêmico.

O problema aqui é que é preciso alguma outra estratégia para fazer o DAO poder acessar os dados internos do objeto de negócio enquanto este está sendo criado.

Um objecto persistivel, embora não seja essa a prespectiva normal, é uma implementação do padrão memento.
É preciso entender que o objeto tem atributos e metodos, mas não tem dados. Os dados são coisas que são introduzidas (injetadas/ settadas) no objeto. à partida um objeto de qq classe permite qq valor nos seus atributos.
Se o objeto está sendo populado pelo DAO os dados no banco já foram validados antes. (tudo bem que os dados no banco podem mudar “sozinhos” mas isso é uma porcaria de arquitetura)
O ciclo de vida de um objeto persistivel é
antes de ser persistido : criada (vazio) , preenchido (pela aplicação) , persistido.
depos de ser persistido : criado (vazio) , preenchido (pelo sistema de persistencia) , retornado à aplicação , alterado , persistido.

O uso de get e set é diferente se foi usado pelo DAO ou pela aplicação.
Vc pode colocar logicas especias de controle de consistencia de estado no seus setters para que quando o programador preenche o objeto na aplicação erros possam ser interceptados. E nesta caso o DAO tem que setar os campos sem usar os setters (setando directamente os atributos).
Em alternativa vc pode ter setter sem nenhuma consistencia e colocar essas regras num objeto especifico para isso. Um objeto de especificação. Esse objeto é usado para validar o objeto como um todo. No caso do UF e da cidade pode haver casos em que isso é um erro e casos em que não. Colocar a logica de consistencia num objeto à parte permite não só um bom SoC mas tb implementar várias regras para o mesmo objeto em contextos diferentes.

Então o objeto fica burro ? Não. Inteligencia não é validar consistencia.
Inteligencia é prover métodos que sejam uteis a quem usa o objeto. Ou seja, é introduzir métodos auxiliares
O exemplo tipico é a idade. Existe um método idade(Date day). Isto não é um campo , nem um atributo. É uma regra da entidade. Pessoas têm idades, mas elas são calculadas, são dinamicas. Dependem da data em que se fizer a pergunta. Isto que é inteligencia de um objeto persistivel. Pode haver outras, mas nenhuma será um serviço.
Coisas como contaA.transfere(100, contaB) não são inteligentes. São idiotas. A transferencia em si é uma objeto do dominio que usa contas. Não são as contas que usam transferencias.
Enfim, objetos persistiveis podem ter inteligencia, podem ter regras de dominio e até regras de negocio, mas não podem fazer o sistema todo. Essa é afinal a diferença entre programa em java e em SQL.
Sendo que não podem ser o sistema todo são necessários outros objetos. Isso não é um problema, é a solução.
E esses objetos nem têm que ser todos persistiveis.

L

vejo q o assunto ja disvirtuou para outra coisa…

mas voltando ao assunto base… e para as views? o que usar para trafegar a informação na view?

P

Não é porque vocêtem set/get para o DAO que seu modelo é anêmico. O que faz o modelo ser anêmico é ser tratado proceduralmente ao executar regra de negócio, não haver set/get que são utilizados apenas em outra Camadas. Você vai ter esse mesmo problema na Camada de apresentação, que vai precisar de gets.

De qualquer forma, entendo que às vezes a existência de um set numa classe pode trazer problemas. Sugestões:

  1. Padrão memento
  2. Usar uma nterface sem get/set na camada de negócios e sua implementação com get/set na camada de persistência.
  3. azer o DAO criar uma subclasse da classe real que possua set/get
R

luistiagos:
vejo q o assunto ja disvirtuou para outra coisa…
mas voltando ao assunto base… e para as views? o que usar para trafegar a informação na view?
Essa questão ja foi respondida na primeira página, segue abaixo resposta.
Paulo Silveira:
Perfeito!!! DTO é para trafegar beans entre TIERS, nao entre LAYERS! Entre layers é perfeitamente aceitavel que layers diferentes acessem suas entidades de dominio!
Portanto as entidades de dominio são os seus POJOs, que podem ser trafegados assim como vc fazia para os VOs.

Entendi que o repositorio serve para abstrair o mecanismo de persistencia e que isso é ortogonal. Mas eu digo que o DAO acaba acarretando em um BO porque o DAO não pode ser manuseado exclusivamente pelo POJO.

O exemplo fornecedor.getContasPagasDesde1999() funciona para um problema simples, uma consulta. Quando estamos conversando com o cliente e definimos uma solução para um determinado problema, acabamos por perceber que a lógica dessa solução envolve outros objetos de negócio, portanto quando estamos fazendo a arquiterura do sistema não podemos adicionar essa lógica a um POJO como no exemplo fornecedor.getContasPagasDesde1999().

A solução seria criar um serviço, e se eu entendi bem acho que essa é a abordagem do DDD. Esse serviço irá funcionar como a função mestre citada no artigo do fantoche, o que parece ser um problema.

Na solução do Sergio onde ele disse: No fim vc precisa de um orquestador para multiplos dao. Entenda que vc sempre deve ter esse orquestador, pois é o logico.

Refletindo a frase acima, isso se encaixa no problema dos fantoches, mas me parece lógico para um problema muito comum em um sistema bancário, pois precisamos desse orquestrador com toda a sua lógica para gerenciar difentes contas correntes.

V

Realmente é um bad smell por si só, mas em certos casos é difícil fugir de coisas assim.
E quanto a acessar direto o campo, isso resolve o problema em alguns casos, mas não em todos (por exemplo, quando eu tenho getters e setters inteligentes, que não acessam o campo diretamente e sim fazem outras coisas como salvar logs, acessar aquivos e criar outros objetos, por qualquer motivo que seja). O exemplo da idade do sergiotaborda é um bom exemplo.

Isso em geral é uma boa idéia. Tende a levar ao memento que o pcalcado citou abaixo. Volto nesse assunto mais abaixo.

Na verdade os getters não são problema, logo não haverá nada de errado com a camada de apresentação.

A alternativa 3 me parece criar mais problemas do que resolver.

A alternativa 2 é legal, apesar que um cast seria o suficiente para quebrá-la. Mas mesmo assim é boa.

A alternativa 1 é boa e funciona. O DAO cria o memento e o manipula como quiser. Daí ele salva o memento no objeto de negócio ou então o joga fora. Quase perfeito, o porém é que esse objeto memento não seria um TO disfarçado? Apesar de que mesmo que seja, o modelo já não é mais o anêmico, pois ao invés de todos usarem o TO, todos usam o objeto de negócio e o memento (TO disfarçado) só serviria para a comunicação com o DAO.

A

Pessoal, seria mto idiota criar um BO e dentro dele (somente dentro dele) um objeto DAO?
Assim o objeto de negocios poderia conter os atributos de estado, os metodos de negocio e a camada de persistencia encapsulada num objeto DAO mas q seria acessivel somente internamente ao BO…
Assim o BO seria sempre responsavel por armazenar o estado das variaveis… as regras de negocio e ainda a camada de persistencia… besteira oq eu falei? :oops:

A

Eu acho que muitas das coisas que estamos discutindo aqui já foram debatidas aqui:

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

e aqui:

Muita coisa ficou clara pra mim após ler atentamente. Vale a pena dar uma olhada, principalmente no post do Kung.

P

Qual?

Isso é forçar a barra. Se você usar um cast para burlar as leis de static tyying o que te impede de acessar métodos privados diretamente?

victorwss:

A alternativa 1 é boa e funciona. O DAO cria o memento e o manipula como quiser. Daí ele salva o memento no objeto de negócio ou então o joga fora. Quase perfeito, o porém é que esse objeto memento não seria um TO disfarçado? Apesar de que mesmo que seja, o modelo já não é mais o anêmico, pois ao invés de todos usarem o TO, todos usam o objeto de negócio e o memento (TO disfarçado) só serviria para a comunicação com o DAO.

Não é um DTO, é um memento. Aho que você etá assumindo que qualquer objeto que não é um objeto de negócios é (1)burro e (2)DTO, o que não é verdade.

P

Acho que você está fazendo uma confusão entre o que é um BO de um modelo anêmico e um Service (ou Façade). Um BO executa regras de negócio de forma prcedural, um Service apenas os objetos (Não-BOs) que executam as regras de negócio.

A

:idea: Talvez vocês se entendam mais se começarem a discutir em cima de exemplos (pode ser pequenos trechos de códigos).

V

Estava pensando naqueles problemas do EJB 2 e em outros problemas que a herança costuma trazer. Mas, após pensar um pouco sobre os problemas reais que isso pode trazer, confesso que não consegui pensar em nenhum problema real. Mas de qualquer forma prefiro evitar de ter que usar herança nesse caso, porque herança é algo que você usa só se você tiver certeza que é para usar (e eu não tenho certeza).

Sim, é forçar a barra. Mas isso é fácil de resolver com algum refatoramento.
Acho que uma factory no mesmo pacote que o objeto de negócio pode usar setters com visibilidade de pacote no objeto de negócio. Quanto aos getters não vejo problema, mas se houver também dá para resolver.

Quanto a acessar os campos diretamente via reflection, o System.getSecurityManager().checkAccess(blabla) cuida disso.

Vejamos. Eu sei que você já sabe muito bem o que é um (V|[D]T)O e está cansado de saber, mas vamos analisá-lo:

Um DTO é um objeto que contém:

  1. Um construtor sem parâmetros e quase sempre vazio.
  2. Um monte de atributos privados.
  3. Getters burros (que apenas retornam o valor do atributo) para cada atributo.
  4. Setters burros (que apenas fazem uma simples atribuição no valor do atributo) para cada atributo.

Alternativamente (e pior ainda) poderia conter apenas um construtor vazio e um monte de atributos públicos.

Um DTO pode também em alguns casos implementar Cloneable e/ou Serializable. Pode herdar de outro DTO (embora na minha opinião isso é horrível). E pode também sobrescrever métodos (tais como clone(), toString(), equals(Object) e hashCode()). E pode também usar annotations a vontade.

Mas enfim, a maior e pior característica do DTO é que ele não ter lógica de negócio alguma, e por causa disso os getters e setters são sempre burros, que é quase o mesmo que fazer os atributos serem públicos.

Agora eu pergunto sobre o memento: A estrutura dele não seria a mesma que um DTO? Um construtor sem parâmetros, um monte de atributos e um monte de getters e setters burros.

Apesar de que volto a frisar. A alternativa 3 já resolveu o problema do modelo anêmico, de separar dados de regras de negócio. Ela só não eliminou a necessidade de ter um objeto burro trafegando dados entre o negócio e o DAO (no caso o memento).

C

Porque pensar que algum objeto de dominio precisa ser criado por um caminhao de parametros?

Objetos de dominio são compostos por outros objetos de dominio e um dos principios da OO é a atribuicao de responsabilidades de maneira que nao haja objetos sobrecarregado de responsabilidades.

Se eu tenho um metodo/construtor com muitos parametros é um sinal que preciso criar um outro objeto capaz de agregar esse ‘caminhao’ de parametros em algum conceito que faca sentido no meu dominio.

editado: O que vcs acham?

editado: editado: O que vcs acham?

S

O que vc descreveu é um POJO ( Plain Old Java Object) , um objeto java normal, que não implementa interfaces especiais.
Detalhes um DTO sempre tem que implementar Serializable e mais do que isso deve implementa os metodos privados de read e write. Todo o objetivo do DTO é maximizar a eficiencia da transferencia entre nodos. A qual acontece via mecanismos de serialziação.

Mas os POJO tm costumam ser serializable quando estamos em ambientes JEE. A única coisa que os destingue dos DTO é a sua inificiencia no transporte já que eles não sobreescrevem o algoritmo de serialização.

O DTO é realmente burro. Sempre foi, sempre será. Essa é a sua função.
Existe um padrão chamado HashDTO que é um DTO baseado na interface get/put semelhante a um mapa.

A estrutura de um memento seria exactamente a de DTO ( ou um HashDTO que ainda é mais facil graças a reflection) o ponto é que o objeto de negocio não é um memento

class Pessoa  {

       Date nascimento;
       String nome;
 ... 

  public int idade (){}

  .. get/set
}


class MementoAdapter {

     public static Memento getMemento(Object obj){
           // usa reflection e faz :
        // ara cada campo de obj  seta o memento com memento.put(nomecampo, valorcampo)
     }

     public static void setMemento(Memento  m , Object obj){
           // usa reflection e faz :
        // para cada campo de obj  lê o memento com memento.get(nomecampo)
     }
}

class Memento  extends HashMap{}


// uso 

Pessoa p = new Pessoa();
p.setNome("Sergio");

Memento m = MementoAdapter.getMemento(p);

// Agora vc pode enviar o memento para o DAO outro nodo etc.. 
// A class de negocio não é persistivel, apenas o memento é.

O ponto é : porque criar um mento se eu posso colocar a logica do MementoAdapter dentro do DomainStore/DAO
e usar o pojo directamente como o seu proprio memento ? Basta que o pojo seja serializable ( para navegar entre nodos) , mas nem isso é necessário se a aplicação é apenas local.

Pojos como Pessoa, Cliente, etc… nunca serão DTO. Exemplo de DTO é uma implementação de List que use um algoritmo de compressão quando é serializado , ou uma List que saiba a estrutrua dos objetos dentro dela e otimize a serialização ( por exemplo, uma Lista de N objetos iguais não precisa serilizar N objetos, apenas 1).

Não ha nada a ser usado no lugar de Pojo para os objetos de entidade. Recentemente com annotations os Pojo ficaram mais poderosos ( embora façam import de annotações é aceite que eles ainda são independentes de interfaces especiais)

Objetos inteligentes ( frameworks) usam as definições dos pojos ricos (ricos porque contêm meta informação)
para os gerenciar e dicidir o que fazer. internamente esses frameworks podem até usar mementos, mas isso é uma escolha interna. (por exemplo se pessoa não é serializvel, mesmo assim posso ereplicar o seu estado usando mementos e tornar um objeto pessoa remoto com o mesmo estado que este)

As regras de negocio, consistencia etc, ficam nos objetos de serviço.
A prova de que é aceitável usar Pojo / DTO são os Webservices e todos os mecanismo relacionados e a entreprise bus. E é assim que as empresas reais funcionam. Dados são apenas isso, informação. O que fazer com ela é a alma do negocio e depende de cada um; de cada sistema

C

Essa é A única caracteristica que define um DTO como tal.

victorwss:
Agora eu pergunto sobre o memento: A estrutura dele não seria a mesma que um DTO? Um construtor sem parâmetros, um monte de atributos e um monte de getters e setters burros.

Apesar de que volto a frisar. A alternativa 3 já resolveu o problema do modelo anêmico, de separar dados de regras de negócio. Ela só não eliminou a necessidade de ter um objeto burro trafegando dados entre o negócio e o DAO (no caso o memento).

Memento não é DTO, pelo contrário, se fosse usa-lo neste caso eu o implementaria como parte do domino. Repito, não são os parâmetros do construtor, atributos ou getters/setters ‘burros’ que definem o DTO, mas a ausencia de logica de negocios, e não há nenhuma obrigacao nesse sentido para objetos memento.

Particulamente não vejo problemas em usar reflection nesses casos, ou entao metodos setters. Neste ultimo faco o possivel para nao ter "setters inteligentes" nos meus objetos de dominio assim consigo defini r um padrao onde todos os setters existem apenas por uma questao de infraestrutura (negocio <-> DAO).

Espero ter sido claro.

C

Depende do dominio que vc esta lidando ne? Eu posso resolver um problema do meu negocio usando memento, qual o problema nisso?

Pois é, achei esse exemplo de memento overkill neste caso.

P

Sim, cuida disso e você não consgue usar JPA, Hibernate e praticamente qualquer outro framework ou biblioteca modernos que dependem disso propriamente.

Isso não é a decrição de um DTO. Um DTO é algo que transfere dados, não existe nnhuma especificação sobre ter construtor vazio ou o que quer que seja.

Novamente: DTO não implica em ter get/set burro, DTO é uma coia, objeto burro é outra. Você pdoe implementar o DTO come struturas de dados (i.e. objetos burros) ou não.

Da mesma forma você pode implementar um memento usando estruturas ou não.

victorwss:

Apesar de que volto a frisar. A alternativa 3 já resolveu o problema do modelo anêmico, de separar dados de regras de negócio. Ela só não eliminou a necessidade de ter um objeto burro trafegando dados entre o negócio e o DAO (no caso o memento).

Não vejo este problema. Se você realmente quer usar um memento para isso (que eu citei como uma alternativa mas só é útil em casos extremos, creio) você pdoe mantêr toda esta lógica na Camada de Persistência. Ainda que não mantivesse, como ja disse antes domínio anêmico não é ter estrutura de dados, e utilizar estruturas de dados para regras de negócio. Popular um objeto não é regra de negócio.

V

É, esse tópico está ficando grande :smiley:

Pois bem, na página anterior onde eu disse:

Leia-se:

Pronto, agora a descrição está melhor. :stuck_out_tongue:

Sim, o caminhão de parâmetros é uma coisa ruim, mas ele seria necessário para fazer o objeto nascer consistente. Criar um outro objeto para isso é mais ou menos o mesmo que criar o memento, e resolve esse problema.

:shock: Eu pensava que o (V|[D]T)O não tinha nenhuma função real, era simplesmente uma aberração arquitetural do modelo anêmico desnecessária e que devia ser eliminada. Tanto que o título deste tópico é “O que usar no lugar de VOs?”. Já vi artigos do Martin Fowler metendo o pau nisso, vários tópicos aqui no GUJ dizendo que isso não presta e o wiki do pcalcado também.

Tell me more, please.

Não entendi.

Eu acho que o que está havendo aqui é uma confusão de conceitos, pelo fato de que essas siglas se referem a mais de uma coisa e algumas dessas coisas não são muito bem definidas e podem ser interpretadas de distintas formas. O (V|[D]TO) ao qual me refiro é aquele bicho do modelo anêmico que contém um monte de atributos e um monte de getters e setters burros e mais nada ou quase nada além disso.

Concordo plenamente.

Certo, acho que você tem razão. Se você precisar do JPA e não puder ter permissão de reflection, você se fode e a única coisa que dá para fazer é chorar. Esse é o grande problema de ferramentas que abusam de reflection. Ofuscadores de código também são outra coisa que fodem total com o reflection.
Apesar que tem aquela classe PrivilegedAction lá que acho que pode resolver esse problema, só que eu não faço idéia de como funciona e eu nunca usei.

Eu não disse que havia problema, só disse que ele não eliminou a necessidade do objeto burro.
Mas, eu não entendi o porque de “casos extremos”, pensei que fosse uma alternativa comum e não apenas para casos extremos.

Quanto a parte do “Ainda que não mantivesse, como ja disse antes domínio anêmico não é ter estrutura de dados, e utilizar estruturas de dados para regras de negócio. Popular um objeto não é regra de negócio.”, eu concordo plenamente.

S

cmoscoso:
sergiotaborda:

…o ponto é que o objeto de negocio não é um memento

Depende do dominio que vc esta lidando ne? Eu posso resolver um problema do meu negocio usando memento, qual o problema nisso?

Não depende do dominio. Depende do mecanismo de persistencia que vc usa. O padrão Memento original é um padrão para resolver a persistencia do objeto. Isso é feito criando um segundo objeto e copiando o estado do primeiro. Este segundo objeto é chamado ele proprio de memento. O ponto é que o objeto de dominio não é serializável e contém metodos de dominio. O memento não contém absolutamente métodos nenhuns. Ele é apenas um conjunto de atributos cujos valores são copiados dos atributos do objeto principal. Esse objeto memento pode ser serializável, persistivel etc. O ponto é que o objeto de dominio tem o seu estado preservado fora dele mesmo. Isso é o conceito de persistencia.

Vc não desenvolveria negocios com memento. Vc desenvolveria mecanismos de persistencia que fazem uso do padrão memento. Os seus objetos de negocio poderia ser mais ou menos dependentes do padrão conforme a sua implementação. Se usar reflection qq pojo serve. Se usar alguma interface especial os seus objetos de dominio vão depender de um framework, o que, em tese, é ruim. Enfim, o ponto é que Memento tem a ver com mecanismo de persistencia e não com negocios ou dominios.


Pois é, achei esse exemplo de memento overkill neste caso.

O ponto é separado em duas partas: 1) demonstrar que o padrão memento é utilizado sim, mas não como o GOF definiu. O estado do objeto é copiado para um outro objeto e esse objeto é que é persistido. Na recuperação é ao contrário. O detalhe é que os frameworks de persistencia abdicam do objeto intermediário e passam diractamente para a tecnologia de persistencia ( normalmente SQL).
2) Vc pode criar um mecanismo de persistencia que use o padrão memento com reflection. Assim seus objetos de dominio não dependerão do mecanismo e nem têm que ser serializáveis ou qq coisa assim. Depois vc cria uma interface padrão para persistir esses mementos usando o padrão Strategy. Ou seja, cria várias estratégias de persistencia. Uma delas será persistencia em banco de dados. Outra pode ser usando JCache ou JGroups para ter um estado compatilhado e distribuido ( uma especie de cloud). Outra pode usar um mecanismo de prevalencia. etc… Como esses mecanismo apenas irão depender do objeto memento )que pode ser algo muito simples como um HashMap , por exemplo) vc pode reaproveitar esse mecanismo de persistencia ad infinitum.
Junto com outros padrões como QueryObjet e Interpreter vc pode criar um DomainStore independe do dominio à semelhança do que é feito em JPA/Hibernate mas que funciona não apenas para bancos de dados.

Em 3 palavras: Dao is Dead.
É tempo de pensar mais além.

C

Concordo com voce, nao é um padrão de domain model mesmo!

Mas não restrinja memento a persistencia apenas, o padrao diz mais respeito a externalizar o estado do objeto do que preservar o estado fora do mesmo.

sergiotaborda:

2) Vc pode criar um mecanismo de persistencia que use o padrão memento com reflection. Assim seus objetos de dominio não dependerão do mecanismo e nem têm que ser serializáveis ou qq coisa assim. Depois vc cria uma interface padrão para persistir esses mementos usando o padrão Strategy. Ou seja, cria várias estratégias de persistencia. Uma delas será persistencia em banco de dados. Outra pode ser usando JCache ou JGroups para ter um estado compatilhado e distribuido ( uma especie de cloud). Outra pode usar um mecanismo de prevalencia. etc… Como esses mecanismo apenas irão depender do objeto memento )que pode ser algo muito simples como um HashMap , por exemplo) vc pode reaproveitar esse mecanismo de persistencia ad infinitum.
Junto com outros padrões como QueryObjet e Interpreter vc pode criar um DomainStore independe do dominio à semelhança do que é feito em JPA/Hibernate mas que funciona não apenas para bancos de dados.

Em 3 palavras: Dao is Dead.
É tempo de pensar mais além.

Perfeito! Merece ir pro meu favoritos :slight_smile:

S

Como em tudo na vida, e informática não diferente, é preciso conhecer a Historia (com H) para entender os contextos das conversas. Eu tento usar os conceitos padrão tanto quanto possivel.
O DTO é realmente um padrão e é realmente util quando bem utilizado. A questão é que a os J2EE Core Patterns no tempo do EJB 1 e 2 disseram assim “cara, ejb entity é muito bom, mas tem o problema quando se usa de outra máquina. Existe muito overhead de manter o gerenciamento à distancia” e ai eles pensaram
"recomendamos que se usem objetos para o transporte da informação em vez de invocar os set/get remotamente para diminuir o overhead" Os objetos de transporte eram os DTO, mas com uma estrutura tão simples que nã otinha como otimizar o algoritmo de serialização ( o algoritmo padrão já é muito bom)
Então os DTO entram em cena. Como eles não eram realmente especializações de serialização a sun começou a chamade de VO (Value Object) porque era como se o valor ( o estado) do entity fosse transferido mas não o proprio entity em si, que apenas existiria no servidor ( isto é o padrão memento em ação)
O Martin Fowler inventou um outro padrão que não tem nada a ver com isto e que tb se chama VO.
Para diferenciar o VO do Fowler do VO da sun , o segundo começou a se chamar só TO ou DTO como antigamente (embora ele não seja um DTO verdadeiro).

O modelo anêmico nasceu do EJB ser uma salada que separa dados (entidade) se acções ( servico).
Note que a dualidae Entidade-Serviço está presente tanto em EJB quanto em DDD. O que muda são as implementações e responsabilidade. Mas no EJB existia esse TO voando entre as máquinas, que no DDD nem faz sentido ( porque o dominio não coisa de problemas de infraestrutura)

Mas o modelo anemico tem o seu proposito. Todas as tecnologias B2B funcionam dessa forma.
Vc precisa saber qual é a filosfia do seu desenvolvimento e as tencologias que vai usar antes de decidir que usar DTO é ruim.

Não ha muito a dizer. Em vez de vc criar uma classe por cada coisa que quer transferir , Cliente, produto etc…
Vc tem apenas uma classe, um HashMap que vc seta pares nome:valor e pronto. É mais simples de usar por frameworks mas mais dificil por pessoas.

O pojo é objeto que transita nas tencologias de hoje. Não se eliminou o DTO, elinou-se o EntityBean como uma coisa à parte. No EJB 3 os pojos são as entidades. A entidade é “abstracta” no sentido que ela é definita por anotações e não mais uma interface especial. Os pojos ebj3 são ao mesmo tempo TO e Entidades. O Hibernate usa esta ideia e como se sabe o JPA tem a mesma ideia do Hibernate.
O memento que viajava pela rede não foi eliminado. Foi aceite. E a tencologia mudou para dar cobertura a esse paradigma.

Em EJB o dominio é “anemico” por default e não tem outoro jeito. Por isso que coisas como Spring e DDD apareceram. Porque o EJB desafia o conceito de que as logicas devem estar atreladas ao objeto. EJB é uma solução tecnica para um dominio em ambiente distribuido.
O DDD é uma ideia boa ,mas apenas para modelagem do dominio. Quando chega na parte de implementar isso na prática com tecnologias reais e requistos não funcionais poderosos como distribuição o DDD começa a ser um problema como podemos ver pela quantidade de post sobre como implementar Repository ou como gravar um Entity no banco. São duas esferas diferentes.

P

Não, isso Não é um DTO típico. Um DTO típico é um objeto otimizado apra trafegar em reder e outras mídias de baixa performance.

O que ele disse, com muita razão, é que um objeto é composto d eoutros então Não faz sentido você recbeer muitos parâmetros pequenos e sim alguns poucos objetos que encapsulam estes parâmetros.

Você provavelmente pulou algun pontos importantes do texto.

http://fragmental.com.br/wiki/index.php/Evitando_VOs_e_BOs#Transfer_Objects.2FValue_Objects

Um DTO não é necesariamente um objeto burro, ele é um objetoe specializado.

Recomendo que antes de prosseguir ensta discussão você leia sobre os apdrões ciados aqui.

Como disse isso Não é um DTO, é uma estrutura de dados (i.e. struct) que não deveria er comum num programa OO.

O fatod e que Não teria eliminado a necessidade do objeto burro seria o problema, que eu não concordo.

Não, não é comum. Na maioria dos casos gets e sets são suficientes e esse carnaval de patterns e herança só é preciso se você possui um caso muito estranho ou está sendo muito preciosista.

T

Ótima observação! Pelo menos me serve de consolo… risos.
Quando surge uma nova idéia de Pet Project sinto-me obrigado a aplicar repositories. Aí, só o tempo que perco pensando em como aplicá-lo é suficiente para dar o tempo natural de desgaste da empolgação pelo Pet Project.

A

Não concordo totalmente com isso, justamente pq domínio e infraestrutura são esferas diferentes.
Quer distribuir objetos, ótimo, utilize Session Façades e preserve seu domínio. A(s) entidade(s) rica(s) podem inclusive pertencer como atributos destes beans em um modelo Stateful e terem seus estados mantidos e distribuidos em várias requisições.

Não vejo onde Domain-Driven influencia na distribuição de um sistema.

P

Thiago Senna:
Ótima observação! Pelo menos me serve de consolo… risos.
Quando surge uma nova idéia de Pet Project sinto-me obrigado a aplicar repositories. Aí, só o tempo que perco pensando em como aplicá-lo é suficiente para dar o tempo natural de desgaste da empolgação pelo Pet Project.

Talvez o problema seja exatamente que você perde muito tempo pensando em como aplicá-los. Para isso serve refatoração. Como o Alessandro falou abaixo são coisas dierentes, você não deveria mudar o domínio em unção da infra, pelo menos não com frequência.

S

Tudo bem. Mas quantos sistemas distribuidos vc fez sem usar EJB ?

C

sergiotaborda:

Tudo bem. Mas quantos sistemas distribuidos vc fez sem usar EJB ?

Não entendi. O que tem a ver EJB com DDD?

V

pcalcado:
victorwss:

Leia-se:

Não, isso Não é um DTO típico. Um DTO típico é um objeto otimizado apra trafegar em reder e outras mídias de baixa performance.

Ok, não importa o nome. O que eu me refiro é àquela coisa do modelo anêmico equivalente a um struct, e sempre que falo em VO, TO, ou DTO eu estou me referindo simplesmente aquilo e nada mais além do que aquilo, o nome não importa. Se ele é otimizado para trafegar em rede, se é usado para EJB ou se é usado no framework X ou no framework Y também não me importa. Eu abri esse tópico para entender como eliminá-lo, e não como usá-lo ou como nomeá-lo! O meu objetivo ao abrir este tópico é simplesmente dizer adeus a ele e nunca mais voltar a vê-lo.

Volto a dizer: O que eu me refiro é ao struct do modelo anêmico. O nome não importa. Se vai trafegar em rede ou em EJB também estou me lixando pra isso.

Ok, evita-se o uso do memento e o reserva para casos onde você você necessita de mudanças de estado mais complexas e atômicas (ex: Cidade e UF, ou os dois, ou nenhum).

Me cite um caso que utilizar o modelo anêmico seja a melhor solução. (Modelo anêmico = usar structs burros em todas as camadas).

Talvez para alguns frameworks seja bom, mas acho que para uso geral, isso é muito pior que o modelo anêmico, pois a capacidade do compilador verificar seu código é menor.

P

victorwss:

Ok, não importa o nome.

Victor, só uma dica: eu diria que 50% da importância de padrões, de projeto, arquiteturais ou o que for, é com relação a criarmos uma nomenclatura comum para nos referirmos às soluções. O nome que usamos ao nos referirmos a um padrao é muito importante, bastou você dizer que está falando de struct e não de TO/DTO que a coisa mudou completamente.

V

pcalcado:
victorwss:

Ok, não importa o nome.

Victor, só uma dica: eu diria que 50% da importância de padrões, de projeto, arquiteturais ou o que for, é com relação a criarmos uma nomenclatura comum para nos referirmos às soluções. O nome que usamos ao nos referirmos a um padrao é muito importante, bastou você dizer que está falando de struct e não de TO/DTO que a coisa mudou completamente.

O problema desses structs é que eles não tem um nome apropriado. Eles são chamados ora de VOs, ora de TOs e ora de DTOs. E cada uma dessas siglas corresponde a uma outra coisa diferente, o que gera muita confusão.

Pois bem, então de agora em diante o chamemos de “struct anêmico”, ok?

S

victorwss:
Eu abri esse tópico para entender como eliminá-lo, e não como usá-lo ou como nomeá-lo! O meu objetivo ao abrir este tópico é simplesmente dizer adeus a ele e nunca mais voltar a vê-lo.

A moral da historia é: vc não consegue eliminá-lo.
Vc consegue dar-lhe mais capacidades. Criar métodos de dominio e/ou negocio. Mas vc não consegue viver sem ele.

Procure por Enterprise Service Bus.
Nessa arquitetura os dados são desprovidos de metodos e transferidos com base em xml.
Eventos de processamento (um especia de trigger) são setados para os dados serem processados por serviços.
Os serviços podem ser constuidos por vc ou por terceiros. Os dados idem. Não ha uma correlação entre ambos.
Existem mecanismos de tranformação que adquam os dados os serviços. Nesta arquitetura em que fatores como volume e distribuição são importantes o modelo é completamente anêmico no sentido que os dados não sabem de logicas.
Esta arquitetura tem relação com os webservices e em geral com SOA (Service Oriented Arquitecture) - onde os serviços são mais relevantes que os dados. Por oposição a sistema de bancos de dados onde o foco são nos dados.

Vc pode melhorar o padrão com uso de Generics para aumentar o strong typing, mas sim, é um padrão virado para ferramentas.

A

sergiotaborda:
Lezinho:

Não vejo onde Domain-Driven influencia na distribuição de um sistema.

Tudo bem. Mas quantos sistemas distribuidos vc fez sem usar EJB ?

Só uso EJB quando faz parte de requisitos, realmente não é o modelo que mais me agrada (tão quanto um modelo de distribuição que o faça necessário).
Mas também não sei onde DDD tem haver com isso …

S

Lezinho:
sergiotaborda:
Lezinho:

Não vejo onde Domain-Driven influencia na distribuição de um sistema.

Tudo bem. Mas quantos sistemas distribuidos vc fez sem usar EJB ?

Só uso EJB quando faz parte de requisitos, realmente não é o modelo que mais me agrada (tão quanto um modelo de distribuição que o faça necessário).
Mas também não sei onde DDD tem haver com isso …

Eu já tinha respondido a isto mas parece que não ficou…

O que queria perguntar era: Quantos sistemas como EJB e DDD já fez ?

Quando vc faz um modelo distribuido em que o cliente é minimamente inteligente vc precisa do modelo de dominio no cliente tb.
Se vc usar um repositorio no cliente o repositorio tem que se reportar ao repositorio central no servidor. As entidades que vc controla precisam de mais mecanismos como controlo de concurrencia via um campo version. E ai , ou o seu modelo deixa de ser puramente DDD e contém coisas como getVersion() ou vc força o modelo DDD e tem que se haver com esses detalhes tecnicos.Vc não pode delegar todos os serviços ao servidor pq isso tem baixa performance, logo pelo menos alguns têm que ter inteligencias locais.
Sim, pode usar um Façade mas ele tem que ser esperto para distinguir se está sendo chamado no cliente ou no servidor. Este problema não se poe se aplicação é web ou só desktop, mas quanto é distribuida em muitos desktop a coisa complica.
Pelas documentações do DDD e pelas conversas no foruns parece que DDD foi inventado enquanto se faziam programas fechados ( ou seja, em que ha criação do codigo end-to-end) e não parece que haja um resposta para usar DDD em sistemas em que ha intervenção de tecnologias conhecidas. Para começar a implementação de repository já causa dor de cabeça em sistemas não distribuidos.

Enfim, se o sistema é distribuido ( digamos que com EJB) usar DDD vira um anti-pattern porque o seu conceito de nucleo de dominio independente do resto, não funciona. Bom, pelo menos não vi funcionar. Por isso perguntei quantos sistemas assim vc fez já que defendeu que não ha problema em usar DDD em ambiente distribuido.

E não vale dizer que usa apenas os conceitos de Serviço, Entidade, VO , Repositorio porque isso já existe no EJB.
Para ser DDD tem que ter o conceito de nucleo independente de infra (pelo menos parecendo independente).

E

sergiotaborda:
Enfim, se o sistema é distribuido ( digamos que com EJB) usar DDD vira um anti-pattern porque o seu conceito de nucleo de dominio independente do resto, não funciona. Bom, pelo menos não vi funcionar. Por isso perguntei quantos sistemas assim vc fez já que defendeu que não ha problema em usar DDD em ambiente distribuido.

E não vale dizer que usa apenas os conceitos de Serviço, Entidade, VO , Repositorio porque isso já existe no EJB.
Para ser DDD tem que ter o conceito de nucleo independente de infra (pelo menos parecendo independente).


Você pode explicar melhor o que você quiz dizer nesse finalzinho? Acho que a grande maioria das pessoas neste forum não conseguiu entender o seu ponto de vista ou todos nós estamos viajando muito na maionese …

S

emerleite:

sergiotaborda:

E não vale dizer que usa apenas os conceitos de Serviço, Entidade, VO , Repositorio porque isso já existe no EJB.
Para ser DDD tem que ter o conceito de nucleo independente de infra (pelo menos parecendo independente).

Você pode explicar melhor o que você quiz dizer nesse finalzinho? Acho que a grande maioria das pessoas neste forum não conseguiu entender o seu ponto de vista ou todos nós estamos viajando muito na maionese …

não sei se entendi sua duvida… acho que se refere aos conceitos não formarem o DDD e sim a ideia de nucleo independente.

Bom, não sei como dizer melhor. Em EJB vc tem Serviços (stateless, statefull e message beans) , vc tem entidades
Entity Bean , voce pode ter VO (Integer , Date, são VO logo é dificil não os ter)
Repositorio também já que ha recomendações de usar o padrão DAO com EJB onde as Entidades são realmente guardadas. A diferença é que o DDD se posiciona para resolver o problema de modelagem do dominio. Apenas e só de dominio. Nada mais. não, obviamente, o repositorio do DDD não pode ser entendido como um tradutor/mapeador de tecnologias como o DAO, embora (acho que seja tb obvio) a escolha é no final de quem implementar o repositorio. É apenas o conceito que importam em DDD. O conceito de um objeto que representa a coleção de entidades como se fosse uma lista. A chave é “como se fosse”. Já dá a entender que sabemos que não é.

Portanto, apenas identificar os conceitos e usar os conceitos que o DDD usa, não é realmente estar usando DDD, é ser influenciado pela nomenclatura/ idiologia. O EJB usa uma nomenclatura semelhante e os conceitos são semelhantes. Se vcs perderem um pouco de tempo pensando como modelar um dominio, vc vão chegar no conceito do DDD. Se pensarem em como o implementar de forma distribuida vão chegar no EJB, mas os conceitos são os mesmos nos dois.

Então o que faz o DDD diferente ? Apenas a modelagem do dominio. Como o DDD apenas modela o dominio ele abstrai tudo o que não for de dominio. toda a infra é abstraida. Isso é feito com dois mecanismos : o Repositorio que abstrai o modelo da camada “abaixo” e os serviços que o isolam da camada “acima”. No centro estão as entidades que não tem nenhuma relação com infra nenhuma. Nem uma anotation sequer. Essa pureza do DDD é viável em sistemas completamente escritos do zero como poderia ser uma aplicação swing de criação de circuidos integrados , mas é complexa de implementar num ambiente distribuido.
Em ambiente distribuido existem muitos controles necessários ao estado das entidades ( aliás é por isso que o hiberante não é transparente em ambiente distribuido porque a sessão não é distribuida) como o DDD não enxerga isso, integrar as duas coisas é complexo.

Portanto, se vc tem uma entidade com alguma ponta de infra: vc não está usando DDD , vc está apenas sendo influenciado por ele.

E

Você não explicou a frase que diz que quando um sistema é distribuido usar DDD é um anti-pattern.

E mais, você pode modelar seu domínio e utilizar os Metadados das annotations para tirar o rastro, mas sinceramente nunca farei isso só pra dizer que meu Domínio é DDD compliance (Sé é que posso dizer isso). Deixo esse purismo de lado que nesse caso não serve pra nada. Prefiro ser mais prático, afinal, nesse caso não existe um jeito muito decente de integrar o domínio a infra sem essas anotações ou XMLs do inferno.

[editado]
E outra coisa, o fundamental do DDD nada tem a ver com isso que você está falando. Usar meta-dados ou não é uma questão que fica fora do Design do Domain Model. Esse “mau necessário” não invalida todo o resto dos conceitos.
[/editado]

A

sergiotaborda:

(…). As entidades que vc controla precisam de mais mecanismos como controlo de concurrencia via um campo version. E ai , ou o seu modelo deixa de ser puramente DDD e contém coisas como getVersion() ou vc força o modelo DDD e tem que se haver com esses detalhes tecnicos.(…)

Enfim, se o sistema é distribuido ( digamos que com EJB) usar DDD vira um anti-pattern porque o seu conceito de nucleo de dominio independente do resto, não funciona. Bom, pelo menos não vi funcionar. Por isso perguntei quantos sistemas assim vc fez já que defendeu que não ha problema em usar DDD em ambiente distribuido.

E não vale dizer que usa apenas os conceitos de Serviço, Entidade, VO , Repositorio porque isso já existe no EJB.
Para ser DDD tem que ter o conceito de nucleo independente de infra (pelo menos parecendo independente).

Sinceramente, acho questão de bom senso. Não acredito e acho purismo sem ganho efetivo, defender que um version estragaria toda sua modelagem orientada ao negócio. Como você mesmo menciona, nem todos os serviços são remotos (ou pelo menos não deveriam), o overhead da rede seria latente e isso já reduz sua gama de esforço para satisfazer a infra.

Eu utilizo Seam, pra mim EJB é amigo e não inimigo. Não utilizo distribuição para tudo, pq a distribuição é apenas mais uma feature do EJB e não toda sua motivação, por tanto para a maioria dos casos utilizo interfaces locais. A gerência transacional e de estados de beans pelo conteiner já é algo excelente a considerar para sua utilização. No caso de distribuição de objetos eleitos “remotos”, apenas adiciona uma fachada se acaso sua operação for direta em entidades, ou altero seu metadado para remoto no caso de interfaces de repositórios e services.

Fora os cases atuais em EJB3 e frameworks como o SEAM, tenho modelo rodando na Argentina de sistema de integração com EJB2.1, onde o domínio é isolado por façades e o negócio é fluente. Obviamente a distribuição é limitada pq é um sistema de integração, portanto os métodos remotos são específicos e repassam para o Domain o necessário de informação, nada mais. Nunca tive problemas …

Um modelo “lá e cá” distribuído por EJB, com grande massa de Domínio entre clients e servers na maioria dos casos, é um overkill tremendo que quase sempre pode ser evitado por outras opções de arquitetura. Em muitos casos, um simples modelo REST resolve (mas isso não muda a questão da distribuição dos domínios, o que é mais estratégico do que técnico).

V

Sergio, não daria para fazer algo assim:

Pacote 1 (ou projeto 1) contém toda a sua lógica DDD, sem annotations e sem EJB.

Pacote 2 (ou projeto 2) adapta DDD ao EJB. Contém um monte de Façades para os objetos DDD com todas as annotations necessárias.

E aí, o que acha?

S

Se vc tiver uma aplicação swing que se comunica com o servidor vc pode usar SEAM ?
Se vc usa interfaces locais seu sistema é distribuido ?

Quando digo distribuido digo :“roda em nodos diferentes” e não "roda em camadas/containers diferentes"
Existe serialização envoldia e o mesmo dado logico está em diferentes lugares fisicos (jvm).

Não sou eu que acha que getVersion é violar o purismo do DDD. Isso é obvio. getVersion não é uma método de dominio nem de negocio, logo não pertence na entidade. Claro que ha formas de criar um getVersion sem conspurcar a class de dominio (Proxies que herdam a classe e implementam uma interface de controle) mas o ponto é que se eu declarar explicitamente estarei violando o DDD. A única forma de usar DDD em ambiente distribuido é injetar um monte de proxies que deixa o dominio livre de infra. Quem faz isso ?
Eu concordo que é purista: mas hei! conceitos são coisas puristas. Como disse, na prática vc não usa DDD porque é demasiado restritivo (é um anti-patern: um padrão que atrapalha). Vc usa uma modelagem de dominio, se inspira até nos conceitos , mas como já disse , esses conceitos não são propriedade do DDD.

Tb não digo que annotations, metadados em geral, sejam maus. Mas porque vc precisa de metadados ?
Para trabalhar com os dados de forma automática. Ora, em DDD , em tese, isso não é necessário porque o sistema é feito do principio pensandos nas entidades do sistema. Não é generico. não ha frameworks, não ha truques. Tudo é simples e de desenvolve em torno do dominio. Não visa ser um padrão tecnologico, apenas de modelagem. Eu nunca disse que era ruim usar metadados. O que eu disse é que colocar
imports no arquvio da entidade que sejam de infra é contra a ideologia DDD. Mas eu tb disse que essa ideologia pará no dominio. Então a construção da aplicação, da infra, é livre. Mas não me digam que é aceitável usar getVersion em DDD porque não é. Isso é resultado de trade-off ou de gambiarra, não da teoria que o DDD defende.

Em sistemas distribuidos onde as logicas têm que estar em mais do que um ponto do sistema, os nucleos de dominio têm que ser sincronos. Esse sincronismo é feito à custa de tencologia e truques de manipulação como proxies dinamicos. Então, porque me dar ao trabalho de criar um sistema purista se usar EJB (ou qq outra tecnologia distribuida) já resolve ? Não vou. Então porque me preocupar com os v[D{T}]O se eles são necessários a uma prática menos purista mas mais pragmática ?

O meu ponto era apenas:
1)Colocar logicas nos objetos de dados é uma ideia do DDD e de OO em geral. Essa ideia é boa em tese e executável em certo limite como o pessoa.getIdade () ou produtoItem.getCusto() em que ha uma redução a operar sobre os dados já contidos no objeto. Essas logicas nunca farão o sistema funcionar. O proprio DDD admite isso ao entender a necessidade dos Serviços.
2)Por outro lado usar V[D{T}]O é o que se faz em tenologias modernas como EJB 3 e em qualquer framework que se destine a ser generico. A persistencia não se importa com o comportamento, apenas com os dados e sempre, sempre, ela usará V[D{T}]O porque ela é “forçada” a seguir o padrão Memento.
3) Desafiar a separação entre V[D{T}]O e Serviços não faz sentido nem em DDD nem em nenhum modelo de dominio que se preze. Nem EJB faz isso. O modelo anémico é realmente o que é usado na prática e não ha como ser de outra forma quando queremos usar tencologias de mercado. Portanto não ha como se livrar do V[D{T}]O se queremos ser práticos e menos puristas.
3.1) se quiser ser purista pode, mas em sistemas limitados, não distribuidos. Em sistemas distribuidos a pureza é um empecilho e isso rápidamente significa que se não ha purismo, não ha porque eliminar os V[D{T}]O.

É boa ideia criar um getIdade e um getCusto, concerteza. Mas criar um conta.transfere(100, conta) é errado.
E parece ser ha uma defesa da segunda quando na realidade tudo o que se pede é a primeira.

Não ha necessidade de eliminar os V[D{T}]O o que ha necessidade de eliminar é codigo assim:

double preco = produto.getPreco();
double quantidade = produto.getQuantidade();

double custo = preco * quantidade;

if (custo > 200.00){
    desconto = 100.00;
} else {
    desconto =0;
}

// e

Date nascimento = pessoa.getDataNascimento();

Calendar nascimentoCalendar = Calendar.getInstance();
nascimentoCalendar .setTime(nascimento);
Calendar agoraCalendar= Calendar.getInstance();
agoraCalendar.setTime(new Date());

int idade =   agoraCalendar.get(Calendar.YEAR) - nascimentoCalendar .get(Calendar.YEAR);

if (agoraCalendar.get(Calendar.MONTH) < nascimentoCalendar.get(Calendar.MONTH) || (agoraCalendar.get(Calendar.MONTH) == nascimentoCalendar.get(Calendar.MONTH) && agoraCalendar.get(Calendar.DATE) < nascimentoCalendar.get(Calendar.DATE))){
   idade--;
}

por

desconto = produto.getCusto()>200.00 ? 100.00 : 0.0;
idade = pessoa.getIdade();

As pessoas tendem a programa a mesma logica para o mesmo calculo cada vez que precisam dela. Isso que é errado. Isso que deveria ser eliminado e não os pobres dos V[D{T}]O

S

victorwss:
Sergio, não daria para fazer algo assim:

Pacote 1 (ou projeto 1) contém toda a sua lógica DDD, sem annotations e sem EJB.

Pacote 2 (ou projeto 2) adapta DDD ao EJB. Contém um monte de Façades para os objetos DDD com todas as annotations necessárias.

E aí, o que acha?

Daria. E em tese é assim de que deve ser.
O ponto é: vc consegue fazer ? Alguem consegue ? É mais facil ou dificil que usar EJB directamente ?
Meu cliente não quer EJB, dá para fazer como Hibernate e Spring ? Dá para fazer distribuido com Hibernate e Spring ? Não tem problemas de cache ou latencia ou carga ? …

A

Sim, e com várias opções (utilizando jbossmc, @Remote e scriptings, tunelamento http/webservice), etc. Nas próximas versões isso só esta melhorando …

Eu falei que só uso interface locais ou disse que a maioria das interfaces possuem apenas a necessidade de serem locais?

sergiotaborda:
Quando digo distribuido digo :“roda em nodos diferentes” e não "roda em camadas/containers diferentes"
Existe serialização envoldia e o mesmo dado logico está em diferentes lugares fisicos (jvm).

Eu disse o contrário?

… é, acho que o ponte de corte faltante então seja o não menos importante na arquitetura de um projeto, o chamado “bom senso”. getVersion não mata ninguém Sergio, tão pouco sua modelagem (assim como hashCode, toString e outros tbm não). :wink:

S

Eu estava só esclarecendo a minha posição.
E concordo que não mata ninguem. Eu já passei por essa escolha. No fim usei o getVersion, mas sempre fica a impressão que é gambiarra já que o correto é usar um proxy dinamico. ( Veja por outro lado: getVersion não pode ser usado para tomar decisões no dominio, mas o fato dele ser publico e disponivel a qq ambiente permite que o programador faça asneira. É um trade-off , mas não é tão simples quanto vc faz parecer)

E

Sérgio, dizer se getVersion descaracteriza DDD ta beirando o absurdo vai? Você está se prendendo ao pé da letra e não nos conceitos. Todo livro que eu leio eu tento pegar os conceitos e aplicar da “melhor maneira possível”. Repetindo: “melhor maneira possível”. Em Java, a “melhor maneira possível” de aplicar os conceitos, acredito ser a que estamos falando, com metadados das annotations, getVersion, etc.

Claro que uma aplicação sem Hibernate/JPA não vai ter getVersion, etc. Poderiamos fazer tudo com XML de mapeamento ou SQL dentro do DAO (ARGH), controlar o lock dos registros no braço, em fim, tudo como era antes. Também não acho o melhor dos mundos a forma como é feita hoje.

Agora te pergunto: tem alguma “melhor maneira possível” além dessa? Eu sinceramente não conheço. E outra: Essas coisas tornam DDD um anti-pattern quando usado com EJB como você falou?

A

Bom, o que vejo é que isso tudo acaba mesmo em questão de pontos de vista.

Na visão pragmática dos conceitos, realmente qualquer atributo diferente do model não se encaixa bem. Fora do conceitual e em termos de aplicabilidade, alguns acréscimos necessários, como dependencias de metadados em código ou métodos que satisfaçam a linguagem e não o negócio, acabam caindo em uso.

O que é certo ou errado, acho que não tem resposta. O sucesso de um design é medido no desempenho da equipe, na fluência do código e do resultado final junto com o cliente e sua resposta a mudanças. Se a variação do método for chamada de DDD, MyDDD, ou CustomDDD, acho isso o ponto de menor relevância.

[]'s

E

Bem política sua resposta, mas tudo bem :smiley:

A
S

emerleite:
Sérgio, dizer se getVersion descaracteriza DDD ta beirando o absurdo vai?

Entenda getVersion como um exemplo de método/atributo de infra/estrutura.

Eu acredito que os conceitos são para ser compreendidos ao pé da letra. Só depois de o compreeder ao pé da letra vc se pode dar ao luxo de não os seguir. Só depois de os entender o trade-off será realmente um trade ( uma troca) e não apenas uma escolha pelo mais simples, mais comum … ou mais gambiarra…
Apenas com um entendimento consistente pode haver um design coerente.

Se eu chamar de DDD qualquer coisa que tenha entidades , serviços , repositorios e VO , e não seguir ao pé da letra vou acabar concluindo que EJB é DDD. :shock:

humm… foi exactamente ao não usar Hibernate/JPA que precisei do getVersion, getKey e outros companheiros deles…

Poderiamos fazer tudo com XML de mapeamento ou SQL dentro do DAO (ARGH), controlar o lock dos registros no braço, em fim, tudo como era antes. Também não acho o melhor dos mundos a forma como é feita hoje.

Agora te pergunto: tem alguma “melhor maneira possível” além dessa? Eu sinceramente não conheço. E outra: Essas coisas tornam DDD um anti-pattern quando usado com EJB como você falou?

Maneira possivel ? Claro. O povo não gostou do EJB 2 , apareceu o Spring. O Spring matou a pau ? Toma EJB 3. Não gostou do DAO, apareceu o hibernate. Não gostou do System.out.println() apareceu o Log4J. Existe sempre uma maneira melhor

[explicação longa]

Eu considero que o melhor seria assim:

  1. Não reimplementar logicas de dominio.
  2. Não reimplementar logicas de persistencia
  3. Não reimplementar logicas de apresentação.

Com logicas de dominio não me refiro a logicas de negocio. Por exemplo, Pedido tem itens. Pertence a um cliente. O cliente é uma pessoa. A pessoa é um individuo ou uma empresa. Isso é dominio. Negocio é : se a pessoa está na faixa etária X recebe Y desconto. Se hoje é dia Z os produtos H são mais baratos., etc…

Persistir no banco, em memoria, distribuido, com cache ou sem cache, como HTTP ou sem. Prevayler, SQL Server , Postgres, XML , Banco orientado a objetos … Em ambiente de teste , homologação, produção … em qualquer situação , ocasião e tempo o meu sistema não depender de saber onde estão os dados.

Não ter que implementar mecanismos de procura de dados, filtro, cadastro, consistencia. Seja Swing, HTML, Ajax … Seja distribuido, ou standalone … Todo esse trabalho burocrático é um saco.

Existe sempre uma maneira melhor.
A minha maneira melhor pode não ser a sua. Mas se conseguir me livrar dos 3 pontos acima e poder me concentrar no que o cliente quer - a logica de negocio - já vou achar bom.

Eu entendo o DDD como uma forma de obter o 1. Para isso o dominio tem que ser completamente desprovido de ligações com a infra, porque so dessa forma vou poder reaproveitá-lo em outros sistemas. Pense o tempo que pouparia se existisse um framework de dominio como carrinhos de compras, clientes, produtos, notas fiscais , etc… tudo pronto. VC pega, ajusta e voilá. Isso só é psosivel se as classes forem completamente independentes de frameworks como Hibernate ou tecnologias como JDBC.

O nivel de trabalho, design e esforço necessários para alcançar este ponto são imensos. Por outro lado ha que analizar tecnologias que dão suporte a tudo isto. E mesmo quando vc tenha o framework martelinho de ouro ele ainda tem que ser compativel com padrões : ou então ele tem que ser super bom e virar o padrão.

[/explicação longa]

A

Essa é a busca da arquitetura perfeita Sérgio… mas acho que alguns pontos devem ser considerados:

  • Quanto de esforço ja foi feito em projetos para independência de frameworks, reaproveitamento massivo de front-ends, DAOs ultra-power-megalomanícos-genericos ?

  • Quanto destes esforços já vimos em tantos projetos onde o sistema não vai deixar de ser Hibernate para ser iBatis, trocar Pico pelo Spring ou trocar a interface web por GUIs Swing pelo menos nos próximos 100 anos ?

Acredito que a arquitetura ideal não seja a mais “independente”, justamente pq muitos projetos simplesmente não mudam sua infraestrutura técnica… o mais comum é que seja alterado varias vezes o domínio do negócio. Vejo que responder rápido a essas mudanças (aqui é onde o DDD deita e rola), tem prioridade do que alterar a “API de persistencia”.

Já vi muitos projetos onde o excesso de zelo com os padrões, tornam o mesmo incompatível com o número de horas para realizar tarefas simples, contudo, depois de anos, a arquitetura inicial permanece inalterada.

Isto não é apologia contra padrões, tampouco estou anulando alguma coisa de seu post anterior, mas acho prudente avaliar o que citei antes de optar por uma arquitetura “extrema”.

S

Lezinho:
Essa é a busca da arquitetura perfeita Sérgio… mas acho que alguns pontos devem ser considerados:

  • Quanto de esforço ja foi feito em projetos para independência de frameworks, reaproveitamento massivo de front-ends, DAOs ultra-power-megalomanícos-genericos ?

boa pergunta. quanto foi ? não encontrei até agora nenhum framework nessas condições. (com exceção tlv do naked objects … mas com algumas limitações)

Essa não é a minha preocupação. Se o cliente não quer mudar o problema é dele. A minha preocupação é poder criar rápidamente aplicações para qualquer cliente em qualquer tipo de arquitetura. Poder mudar rápidamente quando o cliente quiser mudar. Básicamente é não perder tempo com requistos não funcionais. É reutilização do ponto de vista da fabrica de software e não do cliente em si. É como ter máquinas e tooling* e não como vender um produto tudo-em-um. Acontece que em informática as ferramentas e o produto final se confundem.

(*tooling, para quem não sabe é a ter várias peças que montadas numa mesma máquina permitem a máquina exercer tarefas diferentes)

E

sergiotaborda:

  • Quanto destes esforços já vimos em tantos projetos onde o sistema não vai deixar de ser Hibernate para ser iBatis, trocar Pico pelo Spring ou trocar a interface web por GUIs Swing pelo menos nos próximos 100 anos ?

Essa não é a minha preocupação. Se o cliente não quer mudar o problema é dele …


Também é problema dele pagar horas demasiadas pra você fazer BDUF e ainda demorar mais pra entregar os releases.

Me explica como que você tem feito isso porque sempre temos que fazer mapeamentos seja por annotations, XML ou então colocando o SQL no DAO se você preferir. Não sei como que você consegue não gastar tempo com isso. Só se você estiver falando de Rails com ActiveRecord, ou algo parecido. Já em Java, desconheço.

Fábricas de Software são uma idéia falida. Faça uma busca aqui no forum sobre o assunto. Falando em reutilização, acho pouco provável você reaproveitar da forma que você está falando. Por acaso você acha que vai aproveitar o Domain Model de um projeto de um cliente em outro projeto de outro cliente só porque é meio parecido? Você vai ter é muita dor de cabeça isso sim. Até se você fizer uma DSL para seu cliente, não vejo muito como você reaproveita-la para outro cliente. Acho que vai conseguir é usar a experiência que teve com o ramo de negócio, mas cada caso é um caso.

T

Eu já acho que pode. O problema é que até aqui não tem sido viável. Talvez não role de usar o mesmo domain, mas você poderia especializá-lo ou criar outro que dependesse e encapsulasse(é assim que escreve?) o domain existente, adicionando então as características específicas necessárias.

Ao meu ver, o ideal era que fosse assim. Isso não quer dizer que seja fácil fazer assim.

S

Com java vc consegue muitas coisas. Concerteza não o fiz com um framework de prateleira. Tive que criar o meu. Sim, usa metadados ( já disse que não tenho nada contra), mas usa uma fabrica de metadados para possam ser lidos de onde for necessário: pode até ler do banco se quiser. E não usa entidades, usa HashDTO.
O meu problema agora é como encaixar isso com POJO.

Vc se prendeu demasiado com as palavras. Me referia ao ponto de vista de quem cria o sowftare, e não de quem o usa. Lá porque o cara quer ligação com oracle isso não significa que não posso reutilizar os componentes de um projeto antigo. E tb não estou dizendo que vai impleemntar todas as possibilidades de uma vez. O que estou dizendo é que a arquitetura e o design tem que ser tal que se eu precisar eu possa fazer.

Eu não posso usar o modelo de dominio do cliente X no Y, mas eu posso extender o dominio do X do A e o Y do A e aperfeiçoar o A quando necessário. Se vc reparar com atenção muitos dos problemas se devem a desconhecimento do dominio. Aquele que o cliente lhe passou não é real é o que ele usa. Uma versão simplificada. Na hora de integrar isso com outra empresa ou melhorar o sistema, não dá certo. E ai vem a gambiarra. Se vc tem um modelo de dominio prévio vc pode detectar os erros mais cedo: não deixando que se perca tempo programando algo que não irá funcionar.

E

sergiotaborda:
emerleite:

Me explica como que você tem feito isso porque sempre temos que fazer mapeamentos seja por annotations, XML ou então colocando o SQL no DAO se você preferir. Não sei como que você consegue não gastar tempo com isso. Só se você estiver falando de Rails com ActiveRecord, ou algo parecido. Já em Java, desconheço.

Com java vc consegue muitas coisas. Concerteza não o fiz com um framework de prateleira. Tive que criar o meu. Sim, usa metadados ( já disse que não tenho nada contra), mas usa uma fabrica de metadados para possam ser lidos de onde for necessário: pode até ler do banco se quiser. E não usa entidades, usa HashDTO.
O meu problema agora é como encaixar isso com POJO.


Ai que está o problema. Eu acho que Java tem limitações por concepção que dificultam muito o fazer uma coisa dessas. Vai ter que criar um monte de gambiarras pra “tentar” chegar aonde você quer. Tem certeza que você não está criando um frankstein?

Não entendi. Pode explicar melhor? Você vai reaproveitar que componentes? você tinha dito reaproveitar o Domain Model.

Você não disse que vai implementar tudo de uma vez mas disse que iria fazer um Design sem ao menos uma idéia se o cliente vai precisar da flexibilidade que você estava criando. Isso é BDUF sim.

Sinceramente eu tenho uma opinião bem diferente. Eu penso no domínio como algo especializado para uma empresa, que foi desenvolvido conversando com os Analistas de Negócio e o Product Owner. Quando for pensar no domínio de outra empresa o máximo que eu usaria é a experiência anterior para direcionar melhor, ganhar agilidade e tentar acertar mais rápido.

@thiago
Cara, como eu disse ao Sérgio, eu acho que no caso de 2 clientes que o ramo de atuação é o mesmo, aproveitar a experiência e dar uma olhada no Domínio feito para o primeiro cliente ajuda, mas dai a reaproveitar o Domínio sinceramente acredito que vai dar mais dor de cabeça que ajudar.

T

Realmente, entendo seu ponto de vista. Essa idéia de reaproveitar o domain nunca vi na prática e também não vejo no java uma forma agradável de se fazer isso. E de fato, reaproveitar o domínio é uma dor de cabeça. Mas o que acho é que isso não deveria ser uma dor de cabeça.

Acho estranho discutir DDD como uma ferramenta de modelagem somente. Acho que um benefíco que pode ser gerado por DDD a médio prazo é ‘como modelar um domínio que possa ser reutilizável sem gerar dor de cabeça’. :slight_smile:

S

O modelo é apenas um dos componentes. Veja os posts mais atrás.

Entenda que não me interessa se o cliente vai precisar. Me interessa se eu vou precisar. E eu tenho uma ideia do que eu preciso ( os 3 pontos que enumerei antes). O exemplo do DAO acho que é mais facil vc entender.
O design menciona um DAO. A arquitetura e tudo o resto está constuido em cima. A única peça que tenho que alterar para mudar Oracle para SQL Server ou JGroups é apenas o DAO. Quando o cliente1 pedir um sistema
com SQL Server eu vou lá e implemento o DAO. Ai ele fica guardado. Quando o cliente2 pedir um sistema diferente com o SQLServer eu vou lá e uso o DAO que já tinha; poupando o tempo de construção de um DAO.
Não é o cliente que vai mudar de banco, sou eu. Se N clientes quiserem N bancos diferentes tenho que implementar N DAO mas se N clientes quiserem M bancos ( M < N) só preciso implementar M. E M tende a ser pequeno ( <10) enquanto N pode ser arbitráriamente grande. (Obviamente estamos falando de um DAO genérico que funciona para qualquer entidade.) Isto não é dificil de conseguir. Veja o exemplo do Hibernate.
O ponto é que o hibernate só funciona via JDBC. O objetivo é funcionar com qq tecnologia necessária. Mas "funcionar" não significa que vc sai implementando para todas as tencologias.
Enfim, não é um trabalho tão arduo quanto parece.

E

Isso tudo que você falou sobre a fonte de dados se resume de forma simples em você criar uma interface usando o padrão Repository [Fowler] e implementa-lo da forma que achar melhor e por trás dos panos pode persistir onde quiser. Por termos demanda muito grande de aplicações que persistem dados num SGBD o Hibernate foca nisso, mas nada impede que você tenha uma implementação do Repository que salve em arquivo XML, VSAM ou [coloque o nome do que você quiser aqui].

E lembrando de DDD, Repository é mencionado como algo pertencente ao Domain Model e usando ele, mesmo com EJB3, não estará aplicando um anti-pattern.

C

sergiotaborda:
2)Por outro lado usar V[D{T}]O é o que se faz em tenologias modernas como EJB 3 e em qualquer framework que se destine a ser generico. A persistencia não se importa com o comportamento, apenas com os dados e sempre, sempre, ela usará V[D{T}]O porque ela é "forçada" a seguir o padrão Memento.
3) Desafiar a separação entre V[D{T}]O e Serviços não faz sentido nem em DDD nem em nenhum modelo de dominio que se preze. Nem EJB faz isso. O modelo anémico é realmente o que é usado na prática e não ha como ser de outra forma quando queremos usar tencologias de mercado. Portanto não ha como se livrar do V[D{T}]O se queremos ser práticos e menos puristas.
3.1) se quiser ser purista pode, mas em sistemas limitados, não distribuidos. Em sistemas distribuidos a pureza é um empecilho e isso rápidamente significa que se não ha purismo, não ha porque eliminar os V[D{T}]O.

DDD fala sobre integração, a ultima parte do livro se dedica exclusivamente a este topico. E o que vale pra integracao de dois sistemas distribuidos vale também quando um deles é a apresentacao. A regra geral é, não distribua seus objetos.

Quando vc diz que sistema distribuido é problema com DDD nao faz sentido pq a integracao ocorrre fora do dominio, e este não distribui seus objetos!

Acho até interessante a ideia de frameworks que fazem bind direto dominio<->apresentacao mas se envolvermos remoting a situacao muda, pq entao estaremos distribuindo os objetos.

Em relacao a persistencia discordo totalmente, acho superada qualquer necessidade de DTO.

S

Sim. De forma simples, se resume a isso. Mas de forma não resumida não é tão simples assim.

S

cmoscoso:
sergiotaborda:
2)Por outro lado usar V[D{T}]O é o que se faz em tenologias modernas como EJB 3 e em qualquer framework que se destine a ser generico. A persistencia não se importa com o comportamento, apenas com os dados e sempre, sempre, ela usará V[D{T}]O porque ela é "forçada" a seguir o padrão Memento.
3) Desafiar a separação entre V[D{T}]O e Serviços não faz sentido nem em DDD nem em nenhum modelo de dominio que se preze. Nem EJB faz isso. O modelo anémico é realmente o que é usado na prática e não ha como ser de outra forma quando queremos usar tencologias de mercado. Portanto não ha como se livrar do V[D{T}]O se queremos ser práticos e menos puristas.
3.1) se quiser ser purista pode, mas em sistemas limitados, não distribuidos. Em sistemas distribuidos a pureza é um empecilho e isso rápidamente significa que se não ha purismo, não ha porque eliminar os V[D{T}]O.

DDD fala sobre integração, a ultima parte do livro se dedica exclusivamente a este topico. E o que vale pra integracao de dois sistemas distribuidos vale também quando um deles é a apresentacao. A regra geral é, não distribua seus objetos.

Quando vc diz que sistema distribuido é problema com DDD nao faz sentido pq a integracao ocorrre fora do dominio, e este não distribui seus objetos!

Na teoria isso é muito bonito. Num sistema web isso é baba. Num sistema standalone tb.
Agora, experimente não distribuir o dominio num sistema swing cliente-servidor. Melhor, tente fazer isso num sistema sometimes-connected.

V

Hehe.
Isso acontece porque o Swing é um framework extremamente invasivo e sua arquitetura é anti-MVC. O EJB 2.x é fichinha perto do que o Swing te força a fazer. Os entusiastas do Swing dizem que ele é puro MVC, mas quem já trabalhou de verdade com ele e já deu uma olhadinha no código-fonte sabe que não é. Para separar o Swing de qualquer outra coisa são necessárias dezenas de AFLs.

  • AFL = Another Fucking Layer
S

victorwss:
sergiotaborda:

Na teoria isso é muito bonito. Num sistema web isso é baba. Num sistema standalone tb.
Agora, experimente não distribuir o dominio num sistema swing cliente-servidor. Melhor, tente fazer isso num sistema sometimes-connected.

Hehe.
Isso acontece porque o Swing é um framework extremamente invasivo e sua arquitetura é anti-MVC. O EJB 2.x é fichinha perto do que o Swing te força a fazer. Os entusiastas do Swing dizem que ele é puro MVC, mas quem já trabalhou de verdade com ele e já deu uma olhadinha no código-fonte sabe que não é. Para separar o Swing de qualquer outra coisa são necessárias dezenas de AFLs.

Bom, eu já usei o swing muito e continuo achando que MVC. Alias o verdadeiro MVC (não essa coisa que se usa em web) já existe uma camada para a separação : os models. Se vc usar como mandam as regras é simples e eficaz.
Agora, se anda por ai usando o DefaultTableModel mechendo com arrays e coisas assim, ai merece mesmo sofrer :twisted:
E depois alguem vem comparar Swing com SWT. Ah! quando é que se vão dar conta que SWT é um comcorrente do AWT ? O verdadeiro concorrente do Swing é o JFaces, que segue a mesma estrutura MVC.

Eu acho o swing muito util. O problema de programar desktop não é o swing, é o cache. As telas ricas demandam muita comunicação continua com o repositorio e se ele está remoto a performance é muito ruim. Por outro lado o cache é distribuido e dinamico. Isso que complica demais.

L

victorwss:

Isso acontece porque o Swing é um framework extremamente invasivo e sua arquitetura é anti-MVC.

Baseado em que “visão” vc afirma isso?

V

Quanto ao swing:

Se o seu uso de swing se limita a utilizar alguns componentes crus e setar umas propriedades. Sorria feliz e comemore, você está em um mar de rosas.

Agora, se você precisa personalizar TableModels, CellEditors, CellRenderers, ComboBoxModels, ListCellRenderer, aí a coisa fica BEM mais complicada. Todas estas coisas são fortemente acoplados a JComponents, de forma que reutilizar tais códigos em um ambiente que não tenha nada de swing é praticamente impossível, e é nestes pontos que as suas view vai se integrar com suas models e controllers. Então a saída seria AFLs.

Outra coisa perversa são os listeners. Eles estão fortemente acoplados ao AWT. Não é apenas um simples acoplamento de ser apenas algumas dependências para compilar (se fosse só isso, ainda estaria tudo bem) e sim que para que eles funcione corretamente é necessário se ter toda a estrutura do AWT por de baixo. Quanto ao MVC, é necessário que a sua model e/ou controller seja um listener para receber eventos do AWT. Como separá-los? AFL!
Mas por outro lado, quanto aos listeners, acho difícil imaginar uma outra arquitetura que pudesse ser melhor que essa (imaginar piores é fácil :twisted: ).

Ah, e alguém já tentou mudar a cor do texto em uma combo box disabled? Não existe nenhum setter ou getter para isso nem na ComboBox, na ComboBoxUI e nem no ComboBoxEditor. Ano passado eu tive que dar um jeito de fazer isso e está hardcoded nas profundezas do swing não lembro onde. Se quiserem posso até procurar. No final consegui fazer uma maluquice para resolver isso, mas foi difícil.

Criado 6 de fevereiro de 2008
Ultima resposta 28 de fev. de 2008
Respostas 136
Participantes 32