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

Como não pertencentes ao domínio.[/quote]

[quote=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. [/quote]

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.

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!

[quote=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:

[quote=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:

[quote=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.”[/quote][/quote]

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?

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.

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

[quote=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?[/quote]

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

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!

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)

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. (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. ([url=http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)]GRASP[/url])
Ainda, uma classe Setor deveria ser responsável por criar um Funcionário ([url=http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)]GRSP[/url]). Para garantir a pré-condição (Regra 2). 
Assim não existiriam funcionários com estado inconsistente.

[code]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;
}

}
[/code]

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

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.

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

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.

[quote=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. [/quote]

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?

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.

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, só é 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.

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:

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.

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.

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.
[/quote]

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.

[quote=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. [/quote]

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.