Domain na Camada de Apresentação (Preciosismo?)

79 respostas
R

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!

79 Respostas

S

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)

Das duas uma:

  1. 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)
  2. 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.

E

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:

  1. 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 …

S

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

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?

L

Também prefiro a utilização de interfaces mais restritivas nos casos onde eu preciso garantir que alguns métodos não sejam invocados.

S

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

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?

S

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.

P

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.

[/quote]

Particular? A Sun, O Fowler e todos os lugares que voce encontrar a descricao, voce vai ver que fala que é para evitar o acumulo de chamadas remotas de granularidade fina:
http://java.sun.com/blueprints/patterns/TransferObject.html
http://www.martinfowler.com/eaaCatalog/dataTransferObject.html

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).

E

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”.

sergiotaborda:

Isso é o que eles querem que vc acredite.


Não. Isso é a definição e o propósito do padrão.
http://www.martinfowler.com/eaaCatalog/dataTransferObject.html
http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html
http://java.sun.com/blueprints/patterns/TransferObject.html
http://www.corej2eepatterns.com/Patterns2ndEd/TransferObject.htm

sergiotaborda:

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 :slight_smile: Mas ta valendo[/EDITED]

A

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.

A

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 …

E

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.

A

Concordo Emerson, se for para replicar objetos volto para os ActionForms do Struts 1.x e continuo a matar bebês focas :slight_smile:

(ta, a piada dos bebês focas hoje é sem graça, mas em 2004 no GUJ isso fazia sentido… )

L

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?

E

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.

E

@lezinho
Esse negócio da foca realmente era engraçado. Tinha um monte de gente com isso na assinatura do GUJ :smiley: . E tinha também uma mais ou menos assim: “Depois que usei o spring, nunca mais usei struts”. Acho que é mais ou menos isso :smiley: :smiley: :smiley:

P

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.

E esse artigo é ótimo: http://martinfowler.com/bliki/LocalDTO.html:

E

Ontem a noite quando eu estava postando sobre esse assunto eu aproveitei pra ler esse texto sobre LocalDTO. Realmente explica tudo.

S

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.

Particular? A Sun, O Fowler e todos os lugares que voce encontrar a descricao, voce vai ver que fala que é para evitar o acumulo de chamadas remotas de granularidade fina:
http://java.sun.com/blueprints/patterns/TransferObject.html
http://www.martinfowler.com/eaaCatalog/dataTransferObject.html

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 :

metodo ( String a, String b, int c);

E rápidamente entenderam que seria melhor assim

class X {
String a; String b; int c;
}

class Bean {
metodo (X x );
}

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.

S

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

class Pessoa {
    private String name;
    private Date birthday;
 
     // get/set
 
    public int idade ( Date day ){
   // calcula idade baseado em birthday e day
 // este não é um método danoso
   } 
  
}

class Pedido {

     public void addItem(Item item){
          // adiciona o item ao pedido
             // este não é um metodo danoso
     }
}

class DAO{

   updateObject o);
}

// com métodos danosos e interfaces “mascara”

interface ActiveRecord {

     public save();
}

class AbstractActiveRecord {
@Inject DAO dao;

     public void save(){
        dao.update(this);
     }

}
interface Pessoa {
    // get/set
    int idade(Date day);
}

class PessoaImpl extends AbstractActiveRecord implements Pessoa {
    private String name;
    private Date birthday;
 
     // get/set
 
    public int idade ( Date day ){
   // calcula idade baseado em birthday e day
 // este não é um método danoso
   } 
  
}

interface Pedido{
   //getset
   addItem(Item item);
}
class PedidoImpl extends AbstractActiveRecord implements Pedido{

     public void addItem(Item item){
          // adiciona o item ao pedido
             // este não é um metodo danoso
     }
}

class DAO{

   updateObject o);
}

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:

class Pedido {

@Inject DAO dao;

     public void addItem(Item item){
          // adiciona o item ao pedido
             dao.update(item);
             dao.update(this);
     }
}

Vantagens do uso de entidades seguras:

  1. menos codigo é necessário
  2. Não ha necessiade de criar objetos especiais que traduzem entre o dominio e o resto
  3. garantia que o utilizador da classe não faz m!@#@#
    Desvantagem:
  4. Expõe os objetos de entidade ao mundo.

Vantagens do uso de entidades não seguras:

  1. Não expõe os objetos de entidade ao mundo.
  2. 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:
  3. Mais codigo é necessário
  4. 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…)

A

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

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

Como não pertencentes ao domínio.

C

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.

A

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.

S

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 :cry:

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

Boa pergunta Lezinho eu estou com essa dúvida tb…

C

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.

S

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 é:

  1. Prefixos e Sufixos não fazem padrões.
  2. 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

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?

P

Design Patterns, em sua maioria, costumam ser remendos que a linguagem ou a tecnologia nao conseguem suprir… É assim mesmo…

C

Foi assim, por “instinto”, que concluiu isso? :stuck_out_tongue:

P

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.

P

cmoscoso:

Foi assim, por “instinto”, que concluiu isso? :stuck_out_tongue:

É, o Sergio entendeu voce ao contrario denovo ai.

A

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.

S

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”…

P

ah, isso me lembra velhas discussões

:wink:

T+

E
sergiotaborda:
O pessoa do EJB começou a usar TO porque eles definiam chamadas assim :
metodo ( String a, String b, int c);
E rápidamente entenderam que seria melhor assim
class X {
String a; String b; int c;
}

class Bean {
metodo (X x );
}
Mais uma vez isso nada tem a ver com o padrão TO/DTO. O que você citou é um Refactoring Pattern chamado Introduce Parameter Object, que nada tem a ver com TO/DTO. http://www.refactoring.com/catalog/introduceParameterObject.html
sergiotaborda:
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.
E

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.

De acordo com o PEAA Pag. 350, esses objetos são Helpers (e.g. UsuarioHelper), atendendo ao padrão Template View.
http://martinfowler.com/eaaCatalog/templateView.html

ISSO NÃO É TO/DTO. REPITA COMIGO: NÃO É TO/DTO. MAIS UMA VEZ: NÃO É TO/DTO.

R

Valeu pelos posts pessoal, :slight_smile:
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!

S

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:

G

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.

E esse artigo é ótimo: http://martinfowler.com/bliki/LocalDTO.html:

Martin Fowler’s Bliki:

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?

A

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.

P

Gustavo,

Como falei uma APi como a exposta por um componente e serviço requer mais cuidado mas:

  1. 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.

  2. 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 apresentacao
class CriaCoisaAction{
public void execute(){
// 'coisas' é um servico provido pela camada de negocios
Coisa novaCoisa = coisas.criaCoisa(parametroX);
//..forward pra pagina pra mostrar a coisa
}}
R

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!

G

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.

Segue um artigo do seu bliki

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)

G

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;
	}

}
public class Setor {
	private List<Funcionario> funcionarios = new ArrayList<Funcionario>();

	public void criarFuncionario(...){
		// validaRegraDois() se necessário dispara exceção de negocio
		funcionarios.add(new Funcionario(...));
	}
}
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...
P

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.

A

Neste seu exemplo Gustavo, o que de mal aconteceria se setSalario fosse acessado na camada de apresentação?

G

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.

A

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?

G

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.

G

Regra 1 - salário de um funcionário deve ser maior que o salário mínimo para seu cargo.

Alessandro, tenho certeza que qualquer justificativa tecnológica ou prática como, por exemplo, Lazy Load você mostraria uma solução elegante. (Para resolver algumas regras de negócio é necessário acessar outros objetos, por isso comentei do Lazy Load)

Na verdade, esse exemplo é muito simples e não vai justificar uma abordagem mais complexa como decomposição em camadas. ([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 ). 

Em alguns casos, como subsystem,  é possível justificar a abordagem se pensamos corporativamente e no efeito acumulativo, não em um projeto especifico. Por isso, esta é uma questão de padronização e talvez de reuso.
G

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… :slight_smile:

A

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.

E

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.

S

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.

G

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.

G

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.

A

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.

S

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.

G

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.

A

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.

G

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:

P

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.

A

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]

G

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.

A

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.

G

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

alguma solucao pratica para o problema? Mapear com interfaces quando necessario? Como mapearia o meu MB?

P

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

mas ainda terá duplicidades dos campos no mapeamento no MB

P

O que tera (qual estrategia) e por quê?

R

um cadastro de Cliente por exemplo…

Classe de Dominio anotada como uma Entidade JPA

@Entity
public class Cliente {
      private int codigo;
      private String nome;
      // gets e sets
      public int geraPedido(Pedido) {
       // Regras
      }

}

Na tela teria um cadastro de cliente, como mapearia isso no meu MB?

A

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;

// gets e sets

}

jsp:

<h:inputText value="#{clienteBean.cliente.nome}"/>

não sei se é a maneira mais correta e gostaria de opiniões tb!

R

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?

E

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

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.

legal, interessante a ideia…vlw

Criado 29 de abril de 2008
Ultima resposta 5 de mai. de 2008
Respostas 79
Participantes 13