Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?
Num JSF voces mapeam o Managed Bean com os mesmos campos do domain?
Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?
Por isso que as entidades de dominio não podem ter métodos que altera o seu estado ( aka ActiveRecord)
Das duas uma:
Suas entidades são ricas , tão ricas que contêm métodos que alteram o estado do sistema como um todo.
Um chamada no momento errado a esses métodos e “Bum!”. Neste caso não é bom passar suas entidades para lado nenhum. Crie outros objetos com o mesmo estado e sem métodos ( aka TO) ( trabalheira)
Suas entidades são pobre ou ricas, mas não tão ricas que contenham métodos que explodem seu sistema.
Neste caso um chamada aos método altera no máximo a propria entidade e suas filhas. mas como não ha um método “save” essas alterações não causam efeito no estado do sistema como um todo. Aqui não precisa de TO, pode usar os objetos de entidade normalmente.
É uma violação do isolamento do dominio ? Pode até ser que seja, mas é um trade-off. É melhor isso que criar TO iguazinhos às entidades só para que eles viajem nas camadas.
Emerson_Macedo
sergiotaborda:
rob1980a:
Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?
Por isso que as entidades de dominio não podem ter métodos que altera o seu estado ( aka ActiveRecord)
Pode explicar isso melhor? ActiveRecord por acaso é ruim na sua opinião?
sergiotaborda:
Das duas uma:
Suas entidades são ricas , tão ricas que contêm métodos que alteram o estado do sistema como um todo.
Um chamada no momento errado a esses métodos e “Bum!”. Neste caso não é bom passar suas entidades para lado nenhum. Crie outros objetos com o mesmo estado e sem métodos ( aka TO) ( trabalheira)
TO, DTO São para evitar chamadas remotas e não para evitar o problema em questão.
sergiotaborda:
É uma violação do isolamento do dominio ? Pode até ser que seja, mas é um trade-off. É melhor isso que criar TO iguazinhos às entidades só para que eles viajem nas camadas.
O que você acha de usar uma interface apenas com os métodos permitidos? Eu ainda prefiro que a camada de domínio seja ortogonal, mas …
sergiotaborda
emerleite:
sergiotaborda:
rob1980a:
Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?
Por isso que as entidades de dominio não podem ter métodos que altera o seu estado ( aka ActiveRecord)
Pode explicar isso melhor? ActiveRecord por acaso é ruim na sua opinião?
Padrões não são ruins ou bons, eles são uteis ou danosos em certos cenários.
No cenário em que eu quero utilizar o objeto da entidade como objeto de transporte (TO) eu não quero que isso possa interferir com o estado do sistema. Neste caso ActiveRecord é danoso. Mas qualquer método na entidade que altere o estado do sistema ( do sistema, não da entidade) é danoso neste cenário.
Isso é o que eles querem que vc acredite.
O ponto em questão é levar os dados (do dominio) até à camada de apresentação. Isso é inerentemente um problema de transporte. Logo é a própria definição de um objeto de transfrencia de dados, de transporte (TO)
Um caso particular do uso disse é quando fazemos chamadas remotas, mas isso é apenas um caso particular de um padrão mais genérico.
O problema do topico é: devo criar novos objetos que apenas contêm o estado das entidades do dominio para maniuplar em outras camadas, em particular a de apresentação ? Claro que não. Isso é uma trabalheira. Isso é o que se fazia com os TO e os EJB Entity Beans. Então a solução é utilizar os próprios objetos de entidade. Mas se eles são demasiado poderosos podem ferrar o sistema. É só isso.
Suponho que “permitidos” significa “seguros”, "que não provocam efeitos desagradáveis"
Poderia utilizar essa medida. É talvez um melhor trade-off que tudo ou nada. Mas num ambiente livre de métodos periogosos seria irrelevante. Só seria util se vc quiser incluir os métodos perigosos. A pergunta é , portanto: vc gosta de programar perigosamente ? Elimine os métodos perigosos e vc eliminou todos os seus problemas. Inclua-os e arrisque-se a que alguem ferre o seu sistema.
R
rob1980a
Realmente Sergio na pratica as coisas se complicam um pouco… DDD ta sendo interessante, mas tem problemas como esse que atrapalha (apesar de nao ser problema do DDD).
No JSF vcs mapeiam como no MB?
Alguem mais tem alguma ideia de como usar as classes de dominio na camada de aprentação? Como vcs fazem nos sistemas de vcs?
Laercio_Queiroz
Também prefiro a utilização de interfaces mais restritivas nos casos onde eu preciso garantir que alguns métodos não sejam invocados.
sergiotaborda
rob1980a:
Realmente Sergio na pratica as coisas se complicam um pouco… DDD ta sendo interessante, mas tem problemas como esse que atrapalha (apesar de nao ser problema do DDD).
Não entendi onde atrapalha …
Eu não uso JSF ( e antes que alguem pergunte: não uso porque não faço sistemas web) mas em principio
vc não tem que mapear de nenhuma forma especial. No MB vc tem que ter métodos que lhe retornem apenas o que vc precisa.
Se o método tem que fazer algum truque (como encapsular as entidades do dominio numa outra coisa) então que seja. Mas na realidade a coisa vai mais da necessidade das páginas do que do dominio em si. o MB é o seu “tradutor”.
R
rob1980a
transformar num TO o dominio ou criar uma interface, como voce mesmo disse é uma trabalheira, ou assumir o risco de jogar o dominio pra apresentação
sergiotaborda:
Eu não uso JSF ( e antes que alguem pergunte: não uso porque não faço sistemas web) mas em principio
vc não tem que mapear de nenhuma forma especial. No MB vc tem que ter métodos que lhe retornem apenas o que vc precisa.
Se o método tem que fazer algum truque (como encapsular as entidades do dominio numa outra coisa) então que seja. Mas na realidade a coisa vai mais da necessidade das páginas do que do dominio em si. o MB é o seu “tradutor”.
Imagino que a boa parte dos sistemas os atributos do dominio ficaria diferentes da tela, e pra mapear isso seria complicado. Alguem ja passou por isso?
sergiotaborda
rob1980a:
Imagino que a boa parte dos sistemas os atributos do dominio ficaria diferentes da tela, e pra mapear isso seria complicado. Alguem ja passou por isso?
Normalmente não. O objeto do dominio é usado directamente na tela.
Paulo_Silveira
sergiotaborda:
emerleite:
Isso é o que eles querem que vc acredite.
O ponto em questão é levar os dados (do dominio) até à camada de apresentação. Isso é inerentemente um problema de transporte. Logo é a própria definição de um objeto de transfrencia de dados, de transporte (TO)
Um caso particular do uso disse é quando fazemos chamadas remotas, mas isso é apenas um caso particular de um padrão mais genérico.
Em que caso usariamos esse padrao mais generico, e onde ha a descricao? nao consigo ver a utilidade de usar DTo/TO sem ser para transferir dados entre TIERS (e nao layers).
Emerson_Macedo
sergiotaborda:
emerleite:
sergiotaborda:
rob1980a:
Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?
Por isso que as entidades de dominio não podem ter métodos que altera o seu estado ( aka ActiveRecord)
Pode explicar isso melhor? ActiveRecord por acaso é ruim na sua opinião?
Padrões não são ruins ou bons, eles são uteis ou danosos em certos cenários.
No cenário em que eu quero utilizar o objeto da entidade como objeto de transporte (TO) eu não quero que isso possa interferir com o estado do sistema. Neste caso ActiveRecord é danoso. Mas qualquer método na entidade que altere o estado do sistema ( do sistema, não da entidade) é danoso neste cenário.
Nesse caso, se você achar realmente necessário, crie uma interface como sugeri anteriormente apenas com os métodos “não-danosos”.
O ponto em questão é levar os dados (do dominio) até à camada de apresentação. Isso é inerentemente um problema de transporte. Logo é a própria definição de um objeto de transfrencia de dados, de transporte (TO)
Um caso particular do uso disse é quando fazemos chamadas remotas, mas isso é apenas um caso particular de um padrão mais genérico.
Sergio, a sua referência é ao seu próprio Blog. Leiamos as fontes originais que citei acima. É possível que você tenha lido o livro Core J2EE Patterns em português, que a tradução é horrível, como 99% dos casos. Na tradução, está escrito camadas, sem fazer diferença entre Layer e Tier. No original em inglês, está escrito Tier e não Layer. Um camarada do trabalho uma vez ficou justificando que estava escrito camadas mas no caso ele também estava lendo em português e sustentando este argumento furado.
sergiotaborda:
O problema do topico é: devo criar novos objetos que apenas contêm o estado das entidades do dominio para maniuplar em outras camadas, em particular a de apresentação ? Claro que não. Isso é uma trabalheira. Isso é o que se fazia com os TO e os EJB Entity Beans. Então a solução é utilizar os próprios objetos de entidade. Mas se eles são demasiado poderosos podem ferrar o sistema. É só isso.
Caso você julgue danoso, crie uma interface apenas com o que poderá ser chamado. Criar uma interface ao invés de duplicar objetos é melhor, IMO.
Sinceramente ainda não entendi esse argumento de programar perigosamente. Poderia exemplificar em código pra ficar mais claro?
[EDITED]O Paulo ainda escreveu na minha frente de tão grande que ficou meu POST Mas ta valendo[/EDITED]
Alessandro_Lazarotti
De qualquer maneira o negócio esta codificado no domínio se sua entidade é rica. Não entendo pq tanto receio de que algum método seja invocado do ManagedBean.
Invocação não significa implementação do domínio… o código continuara na camada adjacente. O que obviamente não seria interessante é o domínio conhecer algo da application, o que não é o caso.
PS: Não estou entrando no mérito de façades pq acho que não é o ponto.
Alessandro_Lazarotti
Uma pergunta aos que sugeriram a interface:
Vocês fazem desta maneira para evitar que um método que não deveria ser invocado aconteça na applayer? Se isso é padrão adotado pela equipe (não invocar métodos do domínio pela app), esta implementação (uso de interface para restringir)é para evitar um programador que saia da regra?
Se a resposta da ultima for “sim”, como garantir que este mesmo programador vai inferir uma instancia concreta na interface restrita (pensada pelo arquiteto) ao invéz de atribui-la diretamante a uma referencia da classe?
Juro que não é crítica, é para entender este contexto que voces colocaram mesmo …
Emerson_Macedo
Alessandro,
É exatamente isso que você falou. Não tem como garantir nada. Mas no caso da interface, a unica coisa que da pra fazer é alguma ferramenta automatizada de QA que faça uma varredura e garanta que não há uso das classes de domínio. No caso de um retorno de método da camada de aplicação, estaria declarado o retorno como uma interface o que faria com que fosse usado esta (Novamente você tem razão, não da pra garantir).
Essa solução é uma solução posível para algumas Empresas/Pessoas que acreditam ser ruim “vazar” os objetos. Quero deixar claro aqui que eu detesto isso, mas no caso de uma restrição imposta por alguém de não expor os objetos (e acho que você entende o que eu quero dizer), a interface é uma opção melhor do que duplicar os objetos, IMO.
Alessandro_Lazarotti
Concordo Emerson, se for para replicar objetos volto para os ActionForms do Struts 1.x e continuo a matar bebês focas
(ta, a piada dos bebês focas hoje é sem graça, mas em 2004 no GUJ isso fazia sentido… )
L
Leonardo3001
Tem uma coisa que eu não entendi: como posso substituir TO por interfaces quando a apresentação e o negócio estão em TIERS diferentes? Até onde eu sei, o cliente recebe um objeto em formato serializável, e pra deserializá-lo, é necessário a definição da classe no lado cliente também.
Supondo que, com interface não dá, existe jeito de se separar a aplicação em TIERS, sem usar TO, mas ao mesmo tempo, concentrar a regra de negócio no lado servidor?
Emerson_Macedo
Leonardo3001:
Tem uma coisa que eu não entendi: como posso substituir TO por interfaces quando a apresentação e o negócio estão em TIERS diferentes? Até onde eu sei, o cliente recebe um objeto em formato serializável, e pra deserializá-lo, é necessário a definição da classe no lado cliente também.
Supondo que, com interface não dá, existe jeito de se separar a aplicação em TIERS, sem usar TO, mas ao mesmo tempo, concentrar a regra de negócio no lado servidor?
No caso em que a apresentação e o negócio estão em TIERS diferentes você sim usa TOs (DTOs). O ponto em que batemos aqui foi usar DTOs entre LAYERS e não TIERS. Como eu disse anteriormente, se a pessoa aprendeu sobre esse padrão através do livro Core J2EE Patterns em português, possivelmente quando leu a palavra camadas (que no original está TIER), pode ter entendido como LAYER e dai confunde tudo.
Emerson_Macedo
@lezinho
Esse negócio da foca realmente era engraçado. Tinha um monte de gente com isso na assinatura do GUJ . E tinha também uma mais ou menos assim: “Depois que usei o spring, nunca mais usei struts”. Acho que é mais ou menos isso
pcalcado
Se estamos falando de como a Camada de Apresentação de uma aplicação se comunica com a Camada de Negócios dela realmente qualquer coisa que Não simplesmente passar os objetos é estranho. No caso de uma API se proteger com interfaces e factories é mais do que suficiente, creio.
Ontem a noite quando eu estava postando sobre esse assunto eu aproveitei pra ler esse texto sobre LocalDTO. Realmente explica tudo.
sergiotaborda
Paulo Silveira:
sergiotaborda:
emerleite:
Isso é o que eles querem que vc acredite.
O ponto em questão é levar os dados (do dominio) até à camada de apresentação. Isso é inerentemente um problema de transporte. Logo é a própria definição de um objeto de transfrencia de dados, de transporte (TO)
Um caso particular do uso disse é quando fazemos chamadas remotas, mas isso é apenas um caso particular de um padrão mais genérico.
Pois, e vc acredita. Como eu disse " Isso é o que eles querem que vc acredite. "
Pense dois minutos. Qualquer objeto composto que vc passa num argumento de um método é um TO. Afinal todo o objetivo de fazer isso é inerente à propria OO : encapsular vários dados num só.
O detalhes que a chamada do método é remota é só um detalhe. O objetivo do padrão TO é alterar a granularidade. E isso pode ser feito pelas mais variadas razões. Serialização é apenas uma delas: a mais conhecida.
O pessoa do EJB começou a usar TO porque eles definiam chamadas assim :
O fato de X ser Serializable era uma obrigação do modelo do EJB que era remoto por default. O padrão TO não precisava disso. Era o EJB quem precisava. Afinal o EJB corre junto do Web container , porque chamadas remotas ? Porque o EJB não definia chamadas locais.
Quando começou a fazê-lo na nova versão do EJB com o LocalInterface o uso de TO não parou. Porquê?
Se o TO fosse para poupar invocações remotas, ele não seria mais necessário, já que elas não existiam mais.
Mas o objetivo do TO nunca foi esse. Sempre foi diminuir a granularidade. Por isso que mesmo com o advento do LocalInterface o TO continuou sendo usado.
Em que caso usariamos esse padrao mais generico, e onde ha a descricao? nao consigo ver a utilidade de usar DTo/TO sem ser para transferir dados entre TIERS (e nao layers).
Pense mais dois minutos: Num sistema web com EJB quantos tiers vc normalmente tem ? UM! (os casos em que vc tem mais que um são raros)
E então porque vc usava objetos remotos ? Porque o EJB obrigava (nas primeira versões)
Quando o LocalInterface chegou porque vc não parou de usar TO ? Afinal continuavamos tendo apenas UM tier e agora sem invocação remota: a razão de usar TO para diminuir invocações remotas não existia mais.
Então porque se continuou usando TO ? Porque continuou importante a necessidade de usar objeto coarse-grain.
Entendam que essa era a falha fatal do EJB pré-3 : todos os objetos eram serializáveis e invocados remotamente mesmo quando só existia um TIER. Aliás, mesmo quando só existia uma JVM.
Mesmo com o advento das interfaces locais que eximiam o EJB de fazer chamadas remotas as pessoas continuaram usando TO. Então estavam usando TO para passar objetos apenas entre camadas , já que a JVM era a mesma. O Tier era o mesmo !
Não precisa de literatura para entender este fato historico se vc alguma vez trabalhou com EJB e TO.
SEMPRE só houve um tier! Isos é ainda mais evidente com o uso de LocalInterface. Não me venham com essa conversa que objetos passados entre camadas não são TO que isso é completamente absurdo. O objetivo do padrão é alterar a granularidade. Apenas isso.
Hoje o Seams faz sucesso por implementar o obvio. Aquilo que o EJB deveria ter sido do inicio. Mas o EJB nasceu do Corba que é remoto por natureza. Esse foi o erro. Isso foi o que fez nascer coisas como o DDD e o Spring e o proprio EJB 3.
A única ocasião onde faz sentido falar em mais do que um tier era quando a interface não era web ( swing por exemplo) onde vc realmente tinha vários tiers. Ou quando vc comunicava com algum legado via CORBA.
Mas isso sempre foi raro. Rápidamente se percebeu que usar Web era muito mais vatajoso exactamente porque tudo estava no mesmo tier. A tecnologia não evoluio para o EJB 3 com interfaces locais porque a maioria dos sistema tem clientes remotos ou acessa legados remotos.
sergiotaborda
emerleite:
hummm… é possivel também que eu tenha citado essas mesmas fontes entre outras e tirado minhas própria conclusões. Essas eram as conclusões em que me baseie para responder e por isso citei o meu blog. Afinal um padrão que serve para “poupar invocações remotas” parece no minimo tosco. Tem que haver uma razão mais primitiva para que algo seja considerado um padrão. Mas como já tive que me explicar no outro posto , peço que o leia.
Eu sei isso. Veja no meu blog o artigo sobre arquitetura se estiver interessado.
// sem métodos danosos
classPessoa{privateStringname;privateDatebirthday;// get/setpublicintidade(Dateday){// calcula idade baseado em birthday e day// este não é um método danoso}}classPedido{publicvoidaddItem(Itemitem){// adiciona o item ao pedido// este não é um metodo danoso}}classDAO{updateObjecto);}
// com métodos danosos e interfaces “mascara”
interfaceActiveRecord{publicsave();}classAbstractActiveRecord{@InjectDAOdao;publicvoidsave(){dao.update(this);}}interfacePessoa{// get/setintidade(Dateday);}classPessoaImplextendsAbstractActiveRecordimplementsPessoa{privateStringname;privateDatebirthday;// get/setpublicintidade(Dateday){// calcula idade baseado em birthday e day// este não é um método danoso}}interfacePedido{//getsetaddItem(Itemitem);}classPedidoImplextendsAbstractActiveRecordimplementsPedido{publicvoidaddItem(Itemitem){// adiciona o item ao pedido// este não é um metodo danoso}}classDAO{updateObjecto);}
Estou usando o ActiveRecord porque é um exemplo claro de métodos que altera o estado do sistema , mas poderia ser quaisquer outros métodos como por exemplo uma implementação assim:
Não ha necessiade de criar objetos especiais que traduzem entre o dominio e o resto
garantia que o utilizador da classe não faz m!@#@#
Desvantagem:
Expõe os objetos de entidade ao mundo.
Vantagens do uso de entidades não seguras:
Não expõe os objetos de entidade ao mundo.
Não ha necessiade de criar objetos especiais que traduzem entre o dominio e o resto já que isso é feito declarando interfaces/classes diferentes.
Desvantagem:
Mais codigo é necessário
Não ha garantia que o utilizador da classe não faz m!@#@# passando o objeto com interface/classe errada
permitindo a invcação dos métodos não seguros.
O ponto é: É mais simples não ter métodos danosos do que mascará-los com interfaces.
(conhece a Navalha de Occam ? é por ai…)
Alessandro_Lazarotti
Como vocês classificam os objetos fakes como aqueles necessários em relatórios ad-hoc, que são apenas uma customização de dados do domínio? (claro, dentro da mesma tier)
C
cmoscoso
rob1980a:
Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?
Num JSF voces mapeam o Managed Bean com os mesmos campos do domain?
Vlw!
O que é um objeto de domínio? Uma entidade, um VO, um service, um repositorio?
Não vejo problema na apresentação chamar metodos de negócio mas as entidades especificamente têm um ciclo de vida que interessa ao domínio e sua exposição pode levar a perder esse foco.
C
cmoscoso
Como não pertencentes ao domínio.
C
cmoscoso
Você quer dizer estado persistente ne?
Eu não acho que uma entidade seja considerada mais “rica” pela capacidade de se persistir. Mas entendi seu ponto!
editado: não é necessário TO, basta lancar uma excecao caso a entidade não esteja num contexto persistente.
Alessandro_Lazarotti
Talvez tenha me expressado mal Moscoso, que ele não é domínio já esta implícito na sua condição de customização do domínio, não era a isso que me referia.
Se ele não é um VO (esse nome hoje tem uma referencia mais forte a sua definição em DDD), não é um TO/DTO (isso é, se você toma como convenção que essa padrão se aplica somente em invocações remotas)… então do que podemos chamar esses objetos que muitas vezes são necessários? Não me recordo do registro de algum padrão específico (se convencionarmos que DTO = remoteCall ) que dá nome para essa situação necessária em muitos casos.
sergiotaborda
Essa perguntinha é muito boa porque demonstra que TO tem muitas mais aplicações. :lol:
Infelizmente não sei se o pessoal vai apreciar toda a complexidade de responder a isso
Acho que o problema para que alguem responsa a isso é a forma como as pesquisas são normalmente feitas.
Acho que a maioria faz uma frase SQL directo no jasperreport via ireport e nem pensa em usar objetos.
Para aqueles que utilizam objetos usam os do próprio dominio (porque na realidade eles usam apenas objetos burros então não ha grande diferença )
Uma pequena minoria já utilizou objetos diferentes daqueles do resto do sistema. E só nesse caso saberiam responder à pergunta.
Mesmo tendo feito isso a minha primeira ideia foi responder “flyweight”, só depois me liguei que eram TO.
Muito boa pergunta, muito inteligente.
T
Tecnoage
Boa pergunta Lezinho eu estou com essa dúvida tb…
C
cmoscoso
Lezinho:
Talvez tenha me expressado mal Moscoso, que ele não é domínio já esta implícito na sua condição de customização do domínio, não era a isso que me referia.
Se ele não é um VO (esse nome hoje tem uma referencia mais forte a sua definição em DDD), não é um TO/DTO (isso é, se você toma como convenção que essa padrão se aplica somente em invocações remotas)… então do que podemos chamar esses objetos que muitas vezes são necessários? Não me recordo do registro de algum padrão específico (se convencionarmos que DTO = remoteCall ) que dá nome para essa situação necessária em muitos casos.
Será que precisamos de um padrão pra isso?
Eu apenas uso o sufixo Helper ou Result.
sergiotaborda
cmoscoso:
Será que precisamos de um padrão pra isso?
Eu apenas uso o sufixo Helper ou Result.
Essa sua pergunta tem tantas implicações que não me atrevo a descrevê-las todas. O essencial é:
Prefixos e Sufixos não fazem padrões.
Um objeto segue padrões mesmo quando vc não sabe que eles os segue ou não o desenhou pensando em algum padrão. Por vezes é institivo.
É como fazer 2+2=4 alheio ao fato disse ser possivel porque o conjunto dos inteiros é um grupo para a adição. Ignorar que é , não impede de usar.
C
cmoscoso
E qual a vantagem de estar sob as rédeas de um padrão que impõe várias restrições sendo que não vou utiliza-lo no contexto para qual ele foi criado?
Paulo_Silveira
Design Patterns, em sua maioria, costumam ser remendos que a linguagem ou a tecnologia nao conseguem suprir… É assim mesmo…
C
cmoscoso
Foi assim, por “instinto”, que concluiu isso?
Paulo_Silveira
So pra deixar claro. Nao é pra criar Local DTO e copiar e colar todos seus atributos. E sim quando voce quer decorar, diminuir, expor algo de maneira diferente para o outro layer.
Paulo_Silveira
cmoscoso:
Foi assim, por “instinto”, que concluiu isso?
É, o Sergio entendeu voce ao contrario denovo ai.
Alessandro_Lazarotti
Não precisamos usar padrão se assim preferirmos para nada Carlos. Contudo é uma forma para referirmos aos mesmos problemas e suas respectivas soluções.
O exemplo que citei é uma situação dessas. Como mencionado pelo Sérgio, você pode transferir uma SQL diretamente ou uma entidade de domínio, optar por um novo objeto customizado é uma solução diferente para a mesma motivação, que sabemos ser bem mais razoável do que os outros approachs.
sergiotaborda
Mais uma vez não tenho palavras para explicar como isso é um tremendo erro. Design Patterns são, sim, na sua maioria corolários do uso do Principio da Separação de Responsabilidade e/ou do Principio da Inversão do Controle. Não são rememdos. São mecanismos formais diretamente relacionados aos principios de OO.
Se colocar um numero de pessoas desenhando sistema OO durante um bom tempo, depois de algum tempo eles vão chegar na conclusão que estão criando sempre o mesmo tipo de objetos. O seguimento das regras de OO leva naturalmente a isso. Como essas implementações especiais , esses trade-off especiais se repetem , ele são catalogados. E isso é um pattern : um conjunto de aplicações de principios o OO que para um determinado problema sempre resultam na mesma solução. Então, sabendo o problema e a solução catalogada vc poupo o tempo e a pericia de utilizar os principios OO do zero. Afinal , não é todo o mundo que sabe fazer isso.
É mais ou menos como na fisica. Vc tem formulas. Mas elas são derivadas de principios primários. As formulas são apenas ajudas catalogadas para não derivar tudo do principio cada vez que é necessário.
Contudo, vc é livre de começar dos principios cada vez e chegar no objeto final. Muitas vezes isso é feito naturalmente - por instinto - se que vc se aperceba que aquilo é um padrão já catalogado. Aliás, para vc reconhecer isso vc tem que conhecer o padrão primeiro.
Me assusta que vc jogue no lixo todo um conjunto de teorias e principios que estão pode detrás de OO e reduza tudo a “remendos”…
O fato de X ser Serializable era uma obrigação do modelo do EJB que era remoto por default. O padrão TO não precisava disso. Era o EJB quem precisava. Afinal o EJB corre junto do Web container , porque chamadas remotas ? Porque o EJB não definia chamadas locais.
Quando começou a fazê-lo na nova versão do EJB com o LocalInterface o uso de TO não parou. Porquê?
Se o TO fosse para poupar invocações remotas, ele não seria mais necessário, já que elas não existiam mais.
Mas o objetivo do TO nunca foi esse. Sempre foi diminuir a granularidade. Por isso que mesmo com o advento do LocalInterface o TO continuou sendo usado.
Tanto isso não é verdade que na prova de Certificação em EJB geralmente caia uma pergunta sobre o uso dos Transfer Objects e a única resposta correta era para diminuição de chamadas remotas. O fato do TO não ter morrido na documentação da Sun se da mais pelo fato da falta de atualização correta, tanto que tem algumas paginas deles que ainda chamam esses objetos de VOs.
sergiotaborda:
Pense mais dois minutos: Num sistema web com EJB quantos tiers vc normalmente tem ? UM! (os casos em que vc tem mais que um são raros)
E então porque vc usava objetos remotos ? Porque o EJB obrigava (nas primeira versões)
Quando o LocalInterface chegou porque vc não parou de usar TO ? Afinal continuavamos tendo apenas UM tier e agora sem invocação remota: a razão de usar TO para diminuir invocações remotas não existia mais.
Então porque se continuou usando TO ? Porque continuou importante a necessidade de usar objeto coarse-grain.
Entendam que essa era a falha fatal do EJB pré-3 : todos os objetos eram serializáveis e invocados remotamente mesmo quando só existia um TIER. Aliás, mesmo quando só existia uma JVM.
Mesmo com o advento das interfaces locais que eximiam o EJB de fazer chamadas remotas as pessoas continuaram usando TO. Então estavam usando TO para passar objetos apenas entre camadas , já que a JVM era a mesma. O Tier era o mesmo !
Não precisa de literatura para entender este fato historico se vc alguma vez trabalhou com EJB e TO.
SEMPRE só houve um tier! Isos é ainda mais evidente com o uso de LocalInterface. Não me venham com essa conversa que objetos passados entre camadas não são TO que isso é completamente absurdo. O objetivo do padrão é alterar a granularidade. Apenas isso.
Hoje o Seams faz sucesso por implementar o obvio. Aquilo que o EJB deveria ter sido do inicio. Mas o EJB nasceu do Corba que é remoto por natureza. Esse foi o erro. Isso foi o que fez nascer coisas como o DDD e o Spring e o proprio EJB 3.
A única ocasião onde faz sentido falar em mais do que um tier era quando a interface não era web ( swing por exemplo) onde vc realmente tinha vários tiers. Ou quando vc comunicava com algum legado via CORBA.
Mas isso sempre foi raro. Rápidamente se percebeu que usar Web era muito mais vatajoso exactamente porque tudo estava no mesmo tier. A tecnologia não evoluio para o EJB 3 com interfaces locais porque a maioria dos sistema tem clientes remotos ou acessa legados remotos.
Não está correto seus argumentos. Quando você diz que sempre houve um só TIER, você ignora o fato do EJB 1.x não ter interfaces locais e por isso a criação dos padrões Session Façade e Transfer Object.
sergiotaborda:
hummm... é possivel também que eu tenha citado essas mesmas fontes entre outras e tirado minhas própria conclusões. Essas eram as conclusões em que me baseie para responder e por isso citei o meu blog. Afinal um padrão que serve para "poupar invocações remotas" parece no minimo tosco. Tem que haver uma razão mais primitiva para que algo seja considerado um padrão. Mas como já tive que me explicar no outro posto , peço que o leia.
Esse padrão para poupar invocações remotas surgiu de uma limitação dos Entity Beans e era a maneira recorrente de resolver o problema. Por isso um padrão.
Emerson_Macedo
Como não pertencentes ao domínio.
Lezinho:
Talvez tenha me expressado mal Moscoso, que ele não é domínio já esta implícito na sua condição de customização do domínio, não era a isso que me referia.
Se ele não é um VO (esse nome hoje tem uma referencia mais forte a sua definição em DDD), não é um TO/DTO (isso é, se você toma como convenção que essa padrão se aplica somente em invocações remotas)… então do que podemos chamar esses objetos que muitas vezes são necessários? Não me recordo do registro de algum padrão específico (se convencionarmos que DTO = remoteCall ) que dá nome para essa situação necessária em muitos casos.
ISSO NÃO É TO/DTO. REPITA COMIGO: NÃO É TO/DTO. MAIS UMA VEZ: NÃO É TO/DTO.
R
rob1980a
Valeu pelos posts pessoal,
Li o link http://www.martinfowler.com/bliki/LocalDTO.html e pelo que entendi ele fala que não seria um trabalho extra duplicar a informacao de dominio para a apresentacao(no caso MB) nos casos de diferencas entre aprensentacao e dominio, esta realmente correto isso?
Como vcs mapeariam um MB caso a solução fosse retornar o objeto de dominio para a apresentacao? Numa tela de cadastro de cliente, como ficaria mapeado o MB? Com os mesmos campos do Domain? Usariam o dominio como mapeamento?
Vlw!
sergiotaborda
emerleite:
De tudo o que vc disse eu vou só comentar esta parte porque o resto é incomentável.
Isto que vc disse é o exemplo do que eu me referia com “é isso que eles querem que vc acredite”.
Me diga, quais eram as outras opções ? Alguma delas era “para diminuir a granularidade da invocação” ?
Se vc quiser continuar acreditando nisso. Otimo. Quer continuar vivendo na ideade das trevas da tecnologia distribuida. Otimo.Mas que ninguem diga que eu não tentei levá-los à luz. :lol:
Gustavo_Serafim
pcalcado:
Se estamos falando de como a Camada de Apresentação de uma aplicação se comunica com a Camada de Negócios dela realmente qualquer coisa que
Não simplesmente passar os objetos é estranho. No caso de uma API se proteger com interfaces e factories é mais do que suficiente, creio.
DTOs are called Data Transfer Objects because their whole purpose is to shift data in expensive remote calls. They are part of implementing a coarse grained interface which a remote interface needs for performance. Not just do you not need them in a local context, they are actually harmful both because a coarse-grained API is more difficult to use and because you have to do all the work moving data from your domain or data source layer into the DTOs.
[size=18]Some people argue for them as part of a Service Layer API because they ensure that service layer clients aren’t dependent upon an underlying Domain Model. While that may be handy, I don’t think it’s worth the cost of all of that data mapping. As my contributor Randy Stafford says in P of EAA “Don’t underestimate the cost of [using DTOs]… It’s significant, and it’s painful - perhaps second only to the cost and pain of object-relational mapping”.[/size]
Another argument I’ve heard is using them in case you want to distribute later. This kind of speculative distribution boundary is what I rail against with the FirstLaw. Adding remote boundaries adds complexity. So I’d echo Randy’s advice “start with a locally invocable Service Layer whose method signatures deal in domain objects. Add remotability when you need it (if ever) by putting Remote Facades on your Service Layer or having your Service Layer objects implement remote interfaces.”
No contexto de CBD, algumas pessoas julgam necessária uma abordagem parecida como a citada por Fowler. Utilizando algo como um DTO ou PO para garantir que o cliente fique desacoplado de uma implementação (por exemplo, da implementação de um subsistema, POJOS com regras de negocio), considerando os DTOs e POs como parte da interface (API).
Assim poderíamos, por exemplo, alterar o domínio utilizando um padrão do GOF - visando flexibilidade - sem alterar a interface do subsistema. (substituir uma herança por uma estratégia state do GoF, PF e PJ herdando de Pessoa para Pessoa agrega uma interface comum de PF e PJ).
Essa abordagem parece razoável, mas tem um custo que não compensa (citado por Fowler). Principalmente em consultas, não existe muitas complicações em objetos de domínio “vazar…” Mas e na criação de um objeto?
Instanciar um objeto gera acoplamento (GRASP), no caso estaríamos instanciando um objeto de domínio fora da cama de negócio… Eu sei que a camada de apresentação não necessita desse “cuidado”, mas essa falta de “coesão” pode gerar outros problemas. Um objeto de domínio representa as regras de negocio, essas regras podem gerar exceções de negócio. Podemos ter regras em construtores e em métodos set…, disparando exceções de negócio (alterações de estados podem gerar validações).
Essas questões são tratadas na camada de negócio, mas no caso de um cadastro? O objeto deve ser instanciado na camada de apresentação? Criando para isso construtores e métodos set… sem regras e outros métodos com as regras para serem utilizados apenas na camada de negócio? Neste caso não é melhor usar um PO, deixando os objetos de domínios só com métodos de negocio?
Alessandro_Lazarotti
Qual o problema de vazar para a camada de aplicação uma exceção de negócio? Se você recebe uma exceção do domínio na camada app, prepare uma mensagem ao cliente UI relatando o problema… enquanto se isso acontece na camada de domínio, outros objetos poderiam tomar outras decisões ainda referente ao negócio (ou tbm propagar para app layer). De qualquer maneira, a camada de aplicação não codifica nada no domínio e nem implementou suas regras, portanto não vejo problemas.
Os PersistenceObjects de hoje em dia são classes convencionais tão quanto o modelo do domínio, pra que separar os dois? Replicar todos os objetos de domínio apenas pq algum programador pode fazer alguma besteira na camada de aplicação pode ser um trabalho imenso sem garantia de que o mesmo programador vai seguir a regra de usar o PO clean no lugar do DomainObject.
pcalcado
Gustavo,
Como falei uma APi como a exposta por um componente e serviço requer mais cuidado mas:
Ainda assim, principalmente se for um componente instance-based, você não precisa de objetos burros, basta usar interfaces que exibam apenas os métodos relevantes. Para componentes remotos ou type-based você pode facilmente utilizar contratos, e ainda assim objetos burros ou DTO não são necessariamente uma necessidade.
O desenvolvimento de um componente é completamente diferente da integração entre duas Camadas de uma aplicação
Gustavo Serafim:
Essa abordagem parece razoável, mas tem um custo que não compensa (citado por Fowler). Principalmente em consultas, não existe muitas complicações em objetos de domínio “vazar…” Mas e na criação de um objeto?
Instanciar um objeto gera acoplamento (GRASP), no caso estaríamos instanciando um objeto de domínio fora da cama de negócio… Eu sei que a camada de apresentação não necessita desse “cuidado”, mas essa falta de “coesão” pode gerar outros problemas. Um objeto de domínio representa as regras de negocio, essas regras podem gerar exceções de negócio. Podemos ter regras em construtores e em métodos set…, disparando exceções de negócio (alterações de estados podem gerar validações).
Essas questões são tratadas na camada de negócio, mas no caso de um cadastro? O objeto deve ser instanciado na camada de apresentação? Criando para isso construtores e métodos set… sem regras e outros métodos com as regras para serem utilizados apenas na camada de negócio? Neste caso não é melhor usar um PO, deixando os objetos de domínios só com métodos de negocio?
Isso não é falta de coesao e é acilmente resolvido com uma factory na Camada de Negócios. Você cria um serviço no seu domínio que instancia objetos.
//camada de apresentacaoclassCriaCoisaAction{publicvoidexecute(){// 'coisas' é um servico provido pela camada de negociosCoisanovaCoisa=coisas.criaCoisa(parametroX);//..forward pra pagina pra mostrar a coisa}}
R
rob1980a
No Managed Bean, eu teria que receber a camada de dominio, e na tela teria os atributos dela no Managed Bean, como eu mapearia isso? Teria duplicidade de atributos!
Gustavo_Serafim
Phillip,
realmente não é sempre necessário, mas para proteger a implementação de um componente (que no caso fica na camada de negocio), principalmente visando o desacoplamento, precisamos de interfaces bem definidas. Como você já conhece: pré, pós condições, exceções e outras considerações de interfaces bem definidas… ( bject-Oriented Design Using UML - Meilir Page-Jones). Assim, neste caso (componentes), talvez fosse interessante manter os objetos de negocio - que são encapsulados no componente e podemos considerar sua implementação - dentro dos componentes, creio.
Sim eu entendo, mas eu estava falando de componentes de negócio, por isso levantei essa questão. Minha preocupação e com o estado consistente do objeto de negócio (encapsulado dentro do componente). Para manter essa consistência, regras de criação e alteração de estado são necessárias, essas regras disparam exceções de negócio. Então deveriam ser manipulados (construtores e set…) apenas dentro do componente de negócio, eu acredito. Claro que esse formalismo depende do caso.
Contudo, trabalhar com interfaces e fabricas pode ser tão trabalhoso quanto usar objetos burros na interface de um componente de negócio. Com essa abordagem, objetos burros para interfaces, não teríamos objetos de negocio na camada de apresentação.
(em qualquer caso alguns desses mecanismos arquiteturais podem ser automatizados)
Gustavo_Serafim
Um exemplo simples, mas acho que pode contribuir.
Temos um objeto de negócio Funcionário. Ele tem um atributo de instância salário e outro atributo de instância que representa seu cargo. Temos duas regras de negócio: 1 - salário de um funcionário deve ser maior que o salário mínimo para seu cargo; 2 - um funcionário novo deve ganhar menos que a media do seu setor.
Toda vez que alterar o estado do objeto de negócio temos que validar algumas regras para o objeto não ficar inconsistente, disparando exceções se necessário. (&sr=1-1]MEILIR=PAGE-JONES - Fundamentos do Desenho Orientado a Objeto com UML)
Quando o método setSalario for usado, devemos validar suas regras. O método setSalario vai comparar o valor informado com o valor mínimo do seu cargo, garantindo a regra 1. (GRASP)
Ainda, uma classe Setor deveria ser responsável por criar um Funcionário (GRSP). Para garantir a pré-condição (Regra 2).
Assim não existiriam funcionários com estado inconsistente.
public class Funcionario {
private Double salario;
private Cargo cargo;
public void setSalario(Double salarioInformado) {
// validaRegraUm() se necessário dispara exceção de negocio
this.salario = salarioInformado;
}
}
publicclassSetor{privateList<Funcionario>funcionarios=newArrayList<Funcionario>();publicvoidcriarFuncionario(...){// validaRegraDois() se necessário dispara exceção de negociofuncionarios.add(newFuncionario(...));}}
Se escondermos esses métodos com regras em uma interface, possibilitando sua utilização na camada de apresentação, teríamos que criar também outros métodos "burros" para usarmos na camada de apresentação. Não sei se compensa...
pcalcado
O que se ganha nisso?
Eu entendi mas não importa se são componentes de infra-estrutura, negócios ou o que for, o design é completamente diferente.
Você pode dar um exemplo ou elaborar como criar uma interface pode ser mais trabalhoso que mantêr duas hierarquias paralelas de objetos (mais o devido códio para mapeamento)?
No seu exemplo, basta a interface não contêr o método setSalario, que faria parte da classe que a implementa. Ela teria um getSalario, entretanto. Não entendi seu ponto sobre criar métodos burros, existe uma diferença entre ter métodos burros e ter métodos sem efeito colateral (como um acessor).
Uma coisa interesante é que qualquer coisa nesse sentido é uma alsa segurança*, na verdade é mais um padrão da linguagem em específico.
Alessandro_Lazarotti
Neste seu exemplo Gustavo, o que de mal aconteceria se setSalario fosse acessado na camada de apresentação?
Gustavo_Serafim
Regras de negócio seriam executadas fora da camada de negócio, ou seja, exceções de negócio poderiam ser disparadas na camada de apresentação.
Se você não vê problema com isso, então não tem mal nenhum… Acredito que regras de negócio ficam melhor na camada de negócio. Uma abordagem com interfaces ou objetos “burros” controla melhor isso.
Alessandro_Lazarotti
Gustavo:
Regras de negócio seriam executadas fora da camada de negócio, ou seja, exceções de negócio poderiam ser disparadas na camada de apresentação.
Se você não vê problema com isso, então não tem mal nenhum… Acredito que regras de negócio ficam melhor na camada de negócio. Uma abordagem com interfaces ou objetos “burros” controla melhor isso.
Qual regra de negócio ocorreria? Receber exceptions e deixa-las “Gracefully” é tarefa desta camada mesmo…
É a opinião de quem vê mal nisso que gostaria de saber Gustavo. O que prejudica no design uma DomainException? Quem mal prático isso poderia acarretar em sua opinião?
Gustavo_Serafim
Phillip, qual parte? “Proteger a implementação” ajuda diminuir o acoplamento. “Manter objetos sempre em estado consistente” ajuda muito quando temos muitas regras complexas. Quando temos muitas trocas de mensagens para cumprir uma regra complexa, podemos inserir erros de lógica de negocio mais facilmente quando os objetos ficam inconsistentes em algum momento.
Se você diz que manter uma hierarquia de interfaces e fabricas não é mais trabalhoso, então eu acredito.
Tanto interfaces quanto objetos “burros” protegem a implementação de um componente de negócio, então acredito que as duas abordagem são úteis para componentes de negócio.
Gustavo_Serafim
Regra 1 - salário de um funcionário deve ser maior que o salário mínimo para seu cargo.
Alessandro,tenhocertezaquequalquerjustificativatecnológicaoupráticacomo,porexemplo,LazyLoadvocêmostrariaumasoluçãoelegante.(Pararesolveralgumasregrasdenegócioénecessárioacessaroutrosobjetos,porissocomenteidoLazyLoad)Naverdade,esseexemploémuitosimplesenãovaijustificarumaabordagemmaiscomplexacomodecomposiçãoemcamadas.([url=http://www.martinfowler.com/bliki/LayeringPrinciples.html]LayeringPrinciples[/url]) Abordagens como Business layer, CBD e Manter o estado dos objetos consistentes se destinam, na maioria das vezes, a supera limitações humanas, como lidar com grande quantidade de informações ou complexas (regras de negócio complexas ). Emalgunscasos,comosubsystem,sóépossíveljustificaraabordagemsepensamoscorporativamenteenoefeitoacumulativo,nãoemumprojetoespecifico.Porisso,estaéumaquestãodepadronizaçãoetalvezdereuso.
Gustavo_Serafim
Phillip, eu entendi, mas no design de um componente de negócio decidimos como será a interface desses componentes e eles podem expor os objetos de negócios ou não. Esses objetos podem acabar na camada de apresentação dependendo da abordagem, por isso aproveitei para levantar essa questão… Agora falar de componentes só com um chopp…
Alessandro_Lazarotti
Esta regra é contida no domínio. A appLayer é simplesmente notificada do sucesso ou não desta, mas ele não a possui. Sabendo do resultado decorrente da ação do domínio, é natural que a camada de aplicação/apresentação controle o flow e apresente de forma clara para a view o ocorrido, isto esta dentro do seu escopo de execução desta camada.
Mas é sobre isso mesmo que estou indagando Gustavo, a decomposição de camadas e não ir contra isso. Tal decomposição não implica na independência de camadas em direção bilateral (isto é adjacente -> subjacente e subjacente -> adjacente). Uma camada adjacente conhece elementos da subjacente, o contrário não é verdadeiro.
Um Command conhecer uma DomainException esta neste escopo e não justifica a criação de engenhosidades para contornar tal conhecimento, que não afeta nem modifica o domínio.
Emerson_Macedo
Já discuti isso (e muito) com o Gustavo pessoalmente nesta semana, então não vou me repetir textualmente.
O ponto que eu acho que a maioria defende é o fato de não fazer BDUF e a filosofia de YAGNI. Não faz muito sentido fazer implementações na base da suposição, como por exemplo: Vou interfaciar usando DTOs, pois estou prevendo acesso remoto.
Muita coisa fica no campo da preferência, mas o que a maioria dos profissionais tem percebido é que simplicidade no design com um mínimo de organização, na maioria dos casos é melhor. Por isso que eu gosto mais da opção de só usar DTOs se eu tiver certeza absoluta do acesso remoto, e mesmo assim, só usaria este para atender a essa interface remota em específico.
sergiotaborda
Regras de negócio seriam executadas fora da camada de negócio, ou seja, exceções de negócio poderiam ser disparadas na camada de apresentação.
Tecnicamente a execução da regra de negocio está no objeto Funcionário que pertence à camada de negocio.
Ou seja, o método executa no objeto da camada de negocio. logo, independentemente de onde o método é invocado as regras sempre seriam executadas na camada de negocio. As exceções seriam disparads por esses mesmos métodos, logo, seriam disparadas pela camada de negocio. Não a de apresentação.
A camada de apresentação poderia tratar as exeções em forma de apresentação ( mensagens ao usuario): mas isso é normal nessa camada. Ela poderia ainda invocar os métodos do objeto funcionário. Embora isso possa não ser certo não implica que a camada de apresentação tem qualquer conhecimento sobre as regras de negocio.
Por outro lado, o desenho do exemplo de funcionário não contém métodos que alteram o estado do sistema, logo, não ha nenhum perigo em invocar esses métodos de qualquer outra camada.
Gustavo_Serafim
sergiotaborda:
Por outro lado, o desenho do exemplo de funcionário não contém métodos que alteram o estado do sistema, logo, não ha nenhum perigo em invocar esses métodos de qualquer outra camada.
Alterar um atributo de instância de um objeto de negócio não é alterar o estado do sistema? Se você esta falando de base, esses objetos podem ser gerenciados por um mapeamento objeto relacional como, por exemplo, o Hibernate.
Gustavo_Serafim
emerleite:
Já discuti isso (e muito) com o Gustavo pessoalmente nesta semana, então não vou me repetir textualmente.
O ponto que eu acho que a maioria defende é o fato de não fazer BDUF e a filosofia de YAGNI. Não faz muito sentido fazer implementações na base da suposição, como por exemplo: Vou interfaciar usando DTOs, pois estou prevendo acesso remoto.
Mas sempre concordamos, o simples é melhor.
Alessandro_Lazarotti
Gustavo Serafim:
sergiotaborda:
Por outro lado, o desenho do exemplo de funcionário não contém métodos que alteram o estado do sistema, logo, não ha nenhum perigo em invocar esses métodos de qualquer outra camada.
Alterar um atributo de instância de um objeto de negócio não é alterar o estado do sistema? Se você esta falando de base, esses objetos podem ser gerenciados por um mapeamento objeto relacional como, por exemplo, o Hibernate.
É discutível.
1)Gostando ou não de getters and setters, eles mantém o encapsulamento na camada de domínio. Você não mudou o estado em outra camada, você sugeriu para o setter(que esta no domínio) assim o fazer … Dependendo da implementação deste útlimo, ele altera o estado do objeto (de forma persistível ou não).
2)Mesmo se assim não fosse (suponhamos que o atributo fosse público), o objeto de negócio poderia ter seu estado de forma transitória, já que a classificação de alterado poderia ser somente quando este atinge o status de ‘pronto’, através de alguma implementação de sustentação deste estado (persistindo ou serializando por exemplo). Nestes casos, alterar um atributo pode não significar mudar seu estado, já q ele não esta ‘pronto’ (se alguém solicitar pelo seu identificador, atraves de um repositório este mesmo objeto, ele estaria com outro estado, diferente que o seu).
O ponto 2 que coloquei é verdade dependendo de implementacoes de cache e proxies utilizadas no sistema.
sergiotaborda
Gustavo Serafim:
sergiotaborda:
Por outro lado, o desenho do exemplo de funcionário não contém métodos que alteram o estado do sistema, logo, não ha nenhum perigo em invocar esses métodos de qualquer outra camada.
Alterar um atributo de instância de um objeto de negócio não é alterar o estado do sistema?
Não. É apenas alterar o estado do objeto.
O estado do sistema é o conjunto de todos os objetos consistentes e válidos. Mesmo que invocar o set não dê erro, ainda têm que ser tomadas outras providencias para que esse objeto passe a integrar o estado do sistema. Normalmente alterações de estado do sistema são feitas dentro de transações. Invocar set() não tem que ser feito numa transação.
Gustavo_Serafim
Lezinho:
Gustavo Serafim:
sergiotaborda:
Por outro lado, o desenho do exemplo de funcionário não contém métodos que alteram o estado do sistema, logo, não ha nenhum perigo em invocar esses métodos de qualquer outra camada.
Alterar um atributo de instância de um objeto de negócio não é alterar o estado do sistema? Se você esta falando de base, esses objetos podem ser gerenciados por um mapeamento objeto relacional como, por exemplo, o Hibernate.
É discutível.
1)Gostando ou não de getters and setters, eles mantém o encapsulamento na camada de domínio. Você não mudou o estado em outra camada, você sugeriu para o setter(que esta no domínio) assim o fazer … Dependendo da implementação deste útlimo, ele altera o estado do objeto (de forma persistível ou não).
2)Mesmo se assim não fosse (suponhamos que o atributo fosse público), o objeto de negócio poderia ter seu estado de forma transitória, já que a classificação de alterado poderia ser somente quando este atinge o status de ‘pronto’, através de alguma implementação de sustentação deste estado (persistindo ou serializando por exemplo). Nestes casos, alterar um atributo pode não significar mudar seu estado, já q ele não esta ‘pronto’ (se alguém solicitar pelo seu identificador, atraves de um repositório este mesmo objeto, ele estaria com outro estado, diferente que o seu).
O ponto 2 que coloquei é verdade dependendo de implementacoes de cache e proxies utilizadas no sistema.
Acredito que pode ser discutível, depende da abstração.
No caso usei um prefixo set…, mas estou representando um método de negócio.
Alessandro_Lazarotti
Então melhor ainda. Quem tem o método de negócio, como você mesmo descreveu, é o método “set” é ele que pode (mas não necessariamente faz) a alteração de estado. O execute do Command é um delegador para o domínio (entre outras atividades), mas não tem regra quanto a ele.
Gustavo_Serafim
Então melhor ainda. Quem tem o método de negócio, como você mesmo descreveu, é o método “set” é ele que pode (mas não necessariamente faz) a alteração de estado. O execute do Command é um delegador para o domínio (entre outras atividades), mas não tem regra quanto a ele.
Não vejo problema nessa abordagem, mas não tive ainda oportunidade de trabalhar em um sistema tão simples, que não justifica um “Service Layer”
Então, neste caso, fica estranho um método transacional de negócio sendo executado fora da API da aplicação.
Não chamaria o método setSalario na apresentação.
Por isso eu comentei:
pcalcado
Phillip, qual parte? “Proteger a implementação” ajuda diminuir o acoplamento. “Manter objetos sempre em estado consistente” ajuda muito quando temos muitas regras complexas. Quando temos muitas trocas de mensagens para cumprir uma regra complexa, podemos inserir erros de lógica de negocio mais facilmente quando os objetos ficam inconsistentes em algum momento.
Eu perguntei o que se ganha com objetos burros comparados à simplesmente ter interfaces.
São úteis e possuem aplicação, mas interfaces não vão representar uma hierarquia paralela nem requerer código de mapeamento. Se você for pagar o preço de ter que mudar UsuarioDTO e CoisaQueTransformaUsuarioEmUsuarioDTO toda vez que Usuario mudar é bom ter uma razão para isso ou é simplesmente desperdício.
Alessandro_Lazarotti
Lezinho:
Invocação não significa implementação do domínio… o código continuara na camada adjacente. O que obviamente não seria interessante é o domínio conhecer algo da application, o que não é o caso.
PS: Não estou entrando no mérito de façades pq acho que não é o ponto.
O ponto onde você atacou era duplicar os objetos Gustavo, e não criar uma façade de serviço, por isso minha observação acima.
Utilizar ServiceLayer ou não, não diz coisa alguma quanto a isso.
[color=olive] [outro-assunto-que-vc-tocou][/color]Além de tudo,existem muitas outras formas de se fazer controle transacional do que utilizar Service Layer, se você ja utilizou controle transacional otimista + Open Session In View, sabe do que estou falando. [color=olive] [/outro-assunto-que-vc-tocou][/color]
Gustavo_Serafim
Comentamos varias coisas, mas tem duas questões principais:
1 - Melhor forma de proteger a implementação de um componente de negócio - para controlar o acoplamento - que acaba influenciando como/se objeto de negócio vai parar na camada de apresentação. (soluções discutidas: interfaces para objetos de negócio ou objetos burros).
2 - Operações de negócio devem ser chamadas apenas atrás de uma API “Service Layer”, considerando uma aplicação complexa ou CBD.
Alessandro_Lazarotti
Desculpe, mas o que tenho postado até aqui não tem nada haver com ServiceLayer, tem haver com sua solução na duplicação de objetos como solução para não vazer “regras”. Se vc discutia outra coisa, que só ficou clara no ultimo post, não era comigo.
Gustavo_Serafim
Estávamos no mesmo assunto, duplicação de objetos (objetos burros) como solução para não vazar “regras”, mas em contextos diferentes. Na próxima vez vou especificar melhor, desculpa.
R
rob1980a
alguma solucao pratica para o problema? Mapear com interfaces quando necessario? Como mapearia o meu MB?
pcalcado
Acho que não entendi esse comentário.
As soluções apresentadas neste tópico são bem práticas. Receita de bolo não existe, você ode procurar as referências dadas aqui e descobrir o que é melhor no seu caso.
R
rob1980a
mas ainda terá duplicidades dos campos no mapeamento no MB
pcalcado
O que tera (qual estrategia) e por quê?
R
rob1980a
um cadastro de Cliente por exemplo…
Classe de Dominio anotada como uma Entidade JPA
@EntitypublicclassCliente{privateintcodigo;privateStringnome;// gets e setspublicintgeraPedido(Pedido){// Regras}}
Na tela teria um cadastro de cliente, como mapearia isso no meu MB?
alerodrigues
eu crio um atributo cliente no managed bean e uso os atributos da propria classe nas páginas.
ex:
public class ClienteBean {
private Cliente cliente;
não sei se é a maneira mais correta e gostaria de opiniões tb!
R
rob1980a
legal a ideia!!!
mas no jsp eu poderia chamar o meu metodo geraPedido (ai concordo que a discuções das 5 páginas completam a ideia) Nesse caso seria melhor uma interface ou outra classe?
Emerson_Macedo
rob1980a:
legal a ideia!!!
mas no jsp eu poderia chamar o meu metodo geraPedido (ai concordo que a discuções das 5 páginas completam a ideia) Nesse caso seria melhor uma interface ou outra classe?
A pergunta é: Por que você chamaria esse método? A não ser que sejam pessoas diferentes que codificam Dominio e Apresentação e essas pessoas estejam distantes, não vejo nem muita necessidade em criar uma interface. Na realidade mais comum todos podem mecher em qualquer parte do código e vão saber que esse tal método (que eu nem sei o que ele faz) pode ou não ser chamado na apresentação.
No caso de você precisar estabelecer uma API (como já foi dito por outras pessoas aqui nessa thread) com algum cliente, ai sim pode-se pensar em interfaces, DTOs (em caso de acessos remotos), etc. Considerando que seu Domínio é daquele sistema apenas, você não terá muita necessidade disso.
R
rob1980a
Emerson Macedo:
rob1980a:
legal a ideia!!!
mas no jsp eu poderia chamar o meu metodo geraPedido (ai concordo que a discuções das 5 páginas completam a ideia) Nesse caso seria melhor uma interface ou outra classe?
A pergunta é: Por que você chamaria esse método? A não ser que sejam pessoas diferentes que codificam Dominio e Apresentação e essas pessoas estejam distantes, não vejo nem muita necessidade em criar uma interface. Na realidade mais comum todos podem mecher em qualquer parte do código e vão saber que esse tal método (que eu nem sei o que ele faz) pode ou não ser chamado na apresentação.
No caso de você precisar estabelecer uma API (como já foi dito por outras pessoas aqui nessa thread) com algum cliente, ai sim pode-se pensar em interfaces, DTOs (em caso de acessos remotos), etc. Considerando que seu Domínio é daquele sistema apenas, você não terá muita necessidade disso.