Consegui evitar os VOs e BOs ?  XML
Índice dos Fóruns » Arquitetura de Sistemas
Autor Mensagem
ronildobraga
JavaEvangelist

Membro desde: 29/03/2006 10:06:51
Mensagens: 443
Localização: sao paulo - sp
Offline

Thiago Senna wrote:Então.. no meu exemplo o Person é uma entidade. Não vejo problemas caso o controle conheça as classes de domínio. Ao meu ver o que não seria certo era o domínio conhecer camadas acima dele (classes que são da view ou controle).


Entao... ate onde eu li, eu so achei isso relacionado ao assunto, a minha tradução é pessima.

É necessário um complexo particionamento do programa em camadas. Desenvolver uma concepção dentro de cada camada que é coerente e que depende apenas das camadas inferiores. seguir padrões arquitectónico padrão para fornecer um engate avulso para as camadas acima. Concentrar todo o código relacionado ao modelo do domínio em uma camada e isolá-lo da relação de usuário, da aplicação, e do código da infraestrutura. Objetos de domínio, sem resposabilidade de se mostrar, armazenando neles mesmos, administrando tarefas de aplicativos e assim por diante, podem estar focados em expressar o modelo do domínio. Isso permite o modelo envolvido ser rico e claro o bastante para capturar a essencia do conhecimento do negócio e colocoar isso para trabalhar

Segue abaixo o texto original

Therefore, partition a complex program into LAYERS. Develop a design within each LAYER that is cohesive and that depends only on the layers below. Follow standard architectural patterns to provide loose coupling to the layers above. Concentrate all the code related to the domain model in one layer and isolate it from the user interface, application, and infrastructure code. The domain objects, free of the responsibility of displaying themselves, storing themselves, managing application tasks, and so forth, can be focused on expressing the domain model. This allows a model to evolve to be rich enough and clear enough to capture essential business knowledge and put it to work


Portanto, o que vc falou parece ser correto, mas eu sinceramente tenho duvidas quanto a isso, o mais importante é que se essa abordagem estiver correta talves nao precisamos chamar o servico da forma que eu demonstrei.

Eu fiz uma pergunta no site aonde o livro esta disponivel para download para ver se eles deixam publicar as partes mais importantes do livro. Eu tenho varias anotações para publicar, mas vou esperar a resposta deles.

Observações:
Eu acho educado não so mostrar o texto original mas tb o que eu entendi do texto e por isso coloquei a tradução, eu espero que isso seja uma pratica comum pois esse é um forum em portugues e existem pessoas que lem esses textos e que as vezes nao sabem ler em ingles ou entende o texto de uma outra forma.

Ronildo da Rocha Braga Jr.
Programador, nada mais.

blog: http://www.iprogramming.blogspot.com/
[Email] [WWW] [MSN]
Thiago Senna
GUJ Master
[Avatar]

Membro desde: 11/02/2005 08:08:02
Mensagens: 1595
Offline

ronildobraga wrote:Portanto, o que vc falou parece ser correto, mas eu sinceramente tenho duvidas quanto a isso, o mais importante é que se essa abordagem estiver correta talves nao precisamos chamar o servico da forma que eu demonstrei.


Quanto aos services concordo com você. Eu entendi o service no DDD como algo diferente do que tenho visto por aí. Tenho visto o pessoal dar o nome de Service para as fachadas que separam controle e domínio. Sinceramente entendo que não seja este o objetivo do service. Pelo que entendi usamos o service para agrupar operações mais complexas que exigem uma manipulação de entidades não relacionadas entre si, por exemplo. Acho que colocamos no service aqueles métodos que não combinariam se ficassem em uma entidade... Será que é isso mesmo?

Exemplificando com código... usando os exemplos que postei anteriormente o controle ficaria assim:



e o service que eu tinha postado:


O método storeOwner() tem só uma linha! Não seria melhor eu apagar o método storeOwner() do meu service e chamar direto o owner.save() no meu controle?


O que eu não sei é se fazendo owner.save() dentro do meu controle quebraria alguma regra do DDD ou se o DDD espera isso mesmo!
[Email]
pcalcado
Moderador
[Avatar]

Membro desde: 08/03/2004 17:19:35
Mensagens: 5174
Localização: Sydney - Australia
Offline

Thiago Senna wrote:
Quanto aos services concordo com você. Eu entendi o service no DDD como algo diferente do que tenho visto por aí. Tenho visto o pessoal dar o nome de Service para as fachadas que separam controle e domínio. Sinceramente entendo que não seja este o objetivo do service. Pelo que entendi usamos o service para agrupar operações mais complexas que exigem uma manipulação de entidades não relacionadas entre si, por exemplo. Acho que colocamos no service aqueles métodos que não combinariam se ficassem em uma entidade... Será que é isso mesmo?


Aí que está: existem Services em diversos níveis mas a maioria reside nessa borda.

Services são Façades de negócio, eles encapsulam lógica de negócio que envolve interações complexas. A únida diferença entre um Service e um Façade é que como tudo em DDD um Service tem que ter uma ligação de 1-para-1 com um conceito de negócios.

DDD pag. 106 wrote:
Many domain or application SERVICES are built on top of the populations of ENTITIES and VALUES, behaving like scripts that organize the potential of the domain to actually get something done. ENTITIES and VALUE OBJECTS are often too fine-grained to provide a convenient access to the capabilities of the domain layer. Here we encounter a very fine line between the domain layer and the application layer.



Thiago Senna wrote:
O que eu não sei é se fazendo owner.save() dentro do meu controle quebraria alguma regra do DDD ou se o DDD espera isso mesmo!


Em Java eu diria que sim porque não há um meio feliz de se ter este método sem implementá-lo diretamente no objeto de negócio ou fazê-lo parte de alguma infra-estrutura (deixandod e ser um POJO). Em plataformas mais dinâmicas como Ruby não, já que Persistência é um conceito a parte e se vai ser implementado via AR ou DataMapper não interfere no design da classe de negócios (já que o framework ou engine AOP poderia colcoar o método save() dinamicamente no objeto em runtime).

O que você tem que rpestar atenção é que um objeto de negócios chamar um método save(), seja em que plataforma for, não é DDD visto que eles (objetos de negócio) só se preocupam com o que faz parte do domínio (logo seu Service tem problemas).

Phillip Calçado "Shoes"
http://fragmental.tw/
http://blog.fragmental.com.br/
"It is unfortunate that much of what is called 'object-oriented programming today is simply old style programming with fancier constructs." - Alan Kay
[Email] [WWW] [Yahoo!] [MSN]
ronildobraga
JavaEvangelist

Membro desde: 29/03/2006 10:06:51
Mensagens: 443
Localização: sao paulo - sp
Offline

Thiago Senna wrote:
O que eu não sei é se fazendo owner.save() dentro do meu controle quebraria alguma regra do DDD ou se o DDD espera isso mesmo!

Muitas duvidas, a imagem da a enteder que vc pode invocar.

Quick DDD pag 31
Um exemplo típico de interação da aplicação, domínio e infraestrutura podiam funcionar dessa forma: O usuário deseja uma rotas de vôo, e pergunta ao serviço na camada de aplicação como fazer isso. Uma parte da aplicação busca os objetos relevantes do domínio da infraestrutura e invoca métodos relevantes para fazer isso ao verificar margens de segurança a outros vôos já registrados. Uma vez que os objetos do domínio fizeram todas as verificações e atualizaram seu status para ?decidido?, o serviço da aplicação persiste os objetos para a infraestrutura.


Observações:
É muito importante ter um linguajar comum, eu entendo que o que vc chama de controle seja a segunda camada(application).
[Thumb - camadas.JPG]
 Nome do arquivo camadas.JPG [Disk] Download
 Descrição
 Tamanho 38 Kbytes
 Baixado:  104 vez(es)


Ronildo da Rocha Braga Jr.
Programador, nada mais.

blog: http://www.iprogramming.blogspot.com/
[Email] [WWW] [MSN]
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline

ronildobraga wrote:
Thiago Senna wrote:Então.. no meu exemplo o Person é uma entidade. Não vejo problemas caso o controle conheça as classes de domínio. Ao meu ver o que não seria certo era o domínio conhecer camadas acima dele (classes que são da view ou controle).



(...) Concentrate all the code related to the domain model in one layer and isolate it from the user interface, application, and infrastructure code. The domain objects, free of the responsibility of displaying themselves, storing themselves, managing application tasks, and so forth, can be focused on expressing the domain model. This allows a model to evolve to be rich enough and clear enough to capture essential business knowledge and put it to work


Portanto, o que vc falou parece ser correto, mas eu sinceramente tenho duvidas quanto a isso, o mais importante é que se essa abordagem estiver correta talves nao precisamos chamar o servico da forma que eu demonstrei.


Destaco a seguinte frase da citação

The domain objects, free of the responsibility of displaying themselves, storing themselves, managing application tasks, and so forth, can be focused on expressing the domain model.


Os objetos de domínio , livres da responsabilidade de se apresentarem a si próprios , guardar a si próprios, gerenciar tarefas da aplicação, e assim por diante, podem se focar em expressar o modelo do domínio.



Para mim esta frase é muito clara e significa que:
1) Objectos de dominio não podem ter funções que dependam ou se destinem a UI ou IO. ("displaying themselves")
2) Objetos de domínio não podem seguir o padrão ActiveRecord ("save themselves") , nem nada semelhante. A responsabilidade de guardar e reobter os objetos é exclusivamente do repositório (por isso ele existe).
3) Serviços de domínio (digo de dominio para diferenciar dos de aplicação e outros) não podem depender de tecnologias (" managing application tasks"). E por isso não devem ser implementados dentro de um servlet ou coisas semelhante.

Os controladores (a aplicação) podem enxergar os objetos de domínio, mas as regras (lógicas) de dominio não podem ficar nos controladores.
Se a regra é muito complexa e um só objeto de dominio não é suficiente, precisamos de um serviço. Respondendo ao Thiago, sim, é para isto que servem os serviços de dominio.

Ai entra a questão de diferenciar "logica de dominio" de "logica de negocio" . Se o objeto pessoa me permite saber a data de nascimento da pessoa, a camada de aplicação pode ter um mecanismo que use essa capacidade , algo do tipo



Ora , isto é o uso do dominio pela aplicação. É um exemplo muito simples, e tlv isso atrapalhe. A questão é que consultar se a pessoa nasceu hoje é um coisa que a aplicação faz, mas a logica que responde a isso , está no objeto do dominio.
Moral da historia , se a logica pertence ao domínio, ela deve apenas existir nos objectos de dominio (VO, Entidades, Serviços) e nunca em outras camadas. Se a logica é de uso do domínio ela fica fora do dominio, em qq outra camada (espera-se que na de aplicação, mas pode ser usada na de apresentação eventualmente)

O entrave fundamental que parece permear este tópico é dar exemplos de DDD usando persistência. Embora persistencia seja um dominio também, ele é muito especial. Se misturarmos as duas coisas vamos acabando resolvendo que a entidades podem ser ActiveRecords e que o Repositorio não serve para nada (exatamente o contrário do que é afirmado pela DDD e frase citada deixa bem claro). Um bom exemplo para entender a diferença é dar uma olhada na TimeAndMoney API. Embora a Joda Time seja tecnicamente superior, a TimeAndMoney demonstra melhor os conceitos de DDD. Não vão ver la código de persistência.






Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
Thiago Senna
GUJ Master
[Avatar]

Membro desde: 11/02/2005 08:08:02
Mensagens: 1595
Offline

Shoes wrote:Em Java eu diria que sim porque não há um meio feliz de se ter este método sem implementá-lo diretamente no objeto de negócio ou fazê-lo parte de alguma infra-estrutura (deixandod e ser um POJO).

E quando as dependências das entidades (a implementação do repositório por exemplo) são injetadas via ID usando AOP? Neste caso, mesmo sendo uma aplicação java as suas entidades deixariam de ser um POJO? Posso estar errado, mas vejo esta solução como algo parecido com o que acontece com linguagens dinâmicas, só não tão bonito! rsrs...

Shoes wrote:O que você tem que rpestar atenção é que um objeto de negócios chamar um método save(), seja em que plataforma for, não é DDD visto que eles (objetos de negócio) só se preocupam com o que faz parte do domínio (logo seu Service tem problemas).

Essa parte me deixou confuso. Se eu quero que após uma determinada operação o estado da entidade seja persistido não posso chamar o método entidade.save() e sim o repository.add(entidade)? Ou melhor ainda, a camada de negócios manipula o estado da entidade e no final a camada de aplicação se responsabiliza por delegar a persistência da entidade para a camada de infraestrutura (chamando entidade.save(), por exemplo)?

ronildobraga wrote:Observações:
É muito importante ter um linguajar comum, eu entendo que o que vc chama de controle seja a segunda camada(application).

Sim sim! O que chamo de controle seria a camada de aplicação. Valeu!

ronildobraga wrote:Muitas duvidas, a imagem da a enteder que vc pode invocar.

Ótimo! Também penso isso por que vejo muito isso no Grails. Agora o que pega é o detalhe que o Shoes citou sobre java x linguagens dinâmicas. Mas acho que hoje vale a pena (dependendo da aplicação) utilizar uma infraestrutura similar ao que vemos nas linguagens dinâmicas.
[Email]
Thiago Senna
GUJ Master
[Avatar]

Membro desde: 11/02/2005 08:08:02
Mensagens: 1595
Offline

sergiotaborda wrote:O entrave fundamental que parece permear este tópico é dar exemplos de DDD usando persistência. Embora persistencia seja um dominio também, ele é muito especial. Se misturarmos as duas coisas vamos acabando resolvendo que a entidades podem ser ActiveRecords e que o Repositorio não serve para nada (exatamente o contrário do que é afirmado pela DDD e frase citada deixa bem claro)

Não só persistência, mas os CRUD's em especial complicam nossa vida. Tomara que este tópico não se transforme em ActiveRecord X Repositório. Este trecho que você argumentou deixou claro que DDD != Active Record!

sergiotaborda wrote:Destaco a seguinte frase da citação


The domain objects, free of the responsibility of displaying themselves, storing themselves, managing application tasks, and so forth, can be focused on expressing the domain model.


Os objetos de domínio , livres da responsabilidade de se apresentarem a si próprios , guardar a si próprios, gerenciar tarefas da aplicação, e assim por diante, podem se focar em expressar o modelo do domínio.

Para mim esta frase é muito clara e significa que:
1) Objectos de dominio não podem ter funções que dependam ou se destinem a UI ou IO. ("displaying themselves")
2) Objetos de domínio não podem seguir o padrão ActiveRecord ("save themselves") , nem nada semelhante. A responsabilidade de guardar e reobter os objetos é exclusivamente do repositório (por isso ele existe).
3) Serviços de domínio (digo de dominio para diferenciar dos de aplicação e outros) não podem depender de tecnologias (" managing application tasks"). E por isso não devem ser implementados dentro de um servlet ou coisas semelhante.


Vou tentar exemplificar com código o que seria um uso adequado de repositório e entidade na camada de aplicação:

Um exemplo (só o C do CRUD) para salvar um aluno:


Agora um exemplo que possui lógica de negócio e esta reside na entidade Turma. Ela deve retornar os alunos com nota abaixo da média:

na camada de aplicação


A entidade turma por sua vez consulta o repositório:


Resumindo: Em geral na camada de aplicação usamos o repository para operações do tipo CRUD (ou outras operações muito simples), no entanto, quando conveniente para isolar a lógica de negócio na entidade podemos acessar o repositorio de dentro da entidade. Estamos avançando?



[Email]
ronildobraga
JavaEvangelist

Membro desde: 29/03/2006 10:06:51
Mensagens: 443
Localização: sao paulo - sp
Offline

Thiago Senna wrote:Estamos avançando?

Isso depende muito da interpretação de cada pessoa, eu particularmente acho que sim, mesmo que as vezes a gente entre em contradição eu espero que no final todos tenham entendido alguma coisa.

Porem algumas pessoas acham que isso aqui é tudo desentendimento e que so falamos besteira, e ainda escreve artigos http://blog.fragmental.com.br/2007/06/22/cuidado-com-domain-driven-design/ falando sobre mim com relação a esse post e depois tem a coragem de vir aqui e tb dar a sua propria opiniao como se esse fosse outro post e ainda ignora tudo que eu falo.

Como eu tinha dito, eu traduzo os texto nao so por educação, mas tb para estabeler um linguagem comum entre a gente assim como o proprio livro do DDD aconselha

Ronildo da Rocha Braga Jr.
Programador, nada mais.

blog: http://www.iprogramming.blogspot.com/
[Email] [WWW] [MSN]
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline

Thiago Senna wrote:
sergiotaborda wrote:O entrave fundamental que parece permear este tópico é dar exemplos de DDD usando persistência. Embora persistencia seja um dominio também, ele é muito especial. Se misturarmos as duas coisas vamos acabando resolvendo que a entidades podem ser ActiveRecords e que o Repositorio não serve para nada (exatamente o contrário do que é afirmado pela DDD e frase citada deixa bem claro)

Não só persistência, mas os CRUD's em especial complicam nossa vida.(...)


Se entendermos que CRUD é uma operação de manutenção/população do repositorio, então CRUD é apenas uma camada em cima do repositório.
Mais ou menos assim



O objeto Query serve para isolar a pesquisa da tecnlogia de persistencia subjacente.

Este serviço é um objeto da camada de aplicação que fica acima da de dominio. O principal detalhe que falta aqui é a validação antes de guardar. A qual deveria , a principio , ser responsabilidade do dominio e podemos pensar que está no repositorio (só para simplificar)

Quanto a mim o código seria mais independente (não necessáriamene melhor) desta forma:



No fim, o repositorio usa um DAO interno para persistir as alterações.
Poderiamos penar que o façade de crud trabalha directamente sobre o DAO sem passar pelo repositorio. É como se a carga das instancias das entidades fosse "exterior" ao repositório. Assim poderiamos usar JPA em cima dos TO e deixar as entidades puras, sem referencia a nenhuma tecnologia. Por outro lado teriamos que encontrar forma de validar esses TO durante a pesistencia. Aqui, poderiamos entender que a validação fica em outras classes do dominio (que eu chamo de validadores, mas a DDD chama de Specification ... e no fim não é bem a mesma coisa) - os validadores. Os validadores seriam chamados pela aplicação antes do .CRUD algo como




Quanto mais independente a camada de dominio for da camada de aplicação e ambas da de persistencia mais transformações serão necessárias e mais objetos serão necessários (como Query).
Isto é um bocado chato. No fim das contas poderiamos usar as entidades anotadas com JPA. Só que, isso violaria o purismo de DDD e é uma escolha de implementação. Entendido isso, o bom é ter independência total para diminuir o acoplamento das camadas, mas isso implica em uma infraestrutura maior.


O meu ponto é que não se deveria confundir o serviço de CRUD com o Repositório. Eles serão tão mais confundiveis quanto mais acopladas tiverem as camadas. Por exemplo, sem TO, as ppr entidades navegam entre as camadas. Se não ha TO não ha Assembler e portanto o papel do seriço CRUD é futil. Mas se fizermos isso estamos usando um pseudo-DDD. No frigir dos ovos isso pode ser suficiente para alguma aplicação, mas concerteza não é recomendado acoplar as camadas assim.

Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
 
Índice dos Fóruns » Arquitetura de Sistemas
Ir para:   
Powered by JForum 2.1.8 © JForum Team