Pensei um pouco e acho que entendi o que você está tentando dizer, Alessandro, me corrije se eu estiver errado.
O que você está tentando dizer é que denro de uma arquitetura de Camadas isso é válido, certo?
Se for isso você está correto, é válido sim, mas foge completamente da filosofia de Domain-Driven Design -assunto da discussão- e do Domain Model em si. Layered Architecture é uma premissa para um bom domínio mas não é porque você tem camadas que tem um domínio bem definido -e DDD é sobre domínios bem definidos.
Um framework pode lhe garantir a abstração necessária para a fotografia. Como no que acabei de exemplificar, na página eu tenho uma expressionLanguage que possui como alvo um DAO implementado pelo framework (não por mim nem por qualquer outra abstração). Nesta discussão você mencionou que o ideal para um repositório era ele não ser obrigado a persistir dados, isso é possível com 2 linhas de xml.
Como se trata de uma EL na página, se precisar alterar/refatorar o alvo para uma façade, não tenho problema algum. Se não precisar, eu não faço nada e uma configuração declarativa faz isso… como configuração por convenção. Para o código, para os desenvolvedores, para o domínio, simplesmente os dados estão lá, disponíveis para o consumo.
[quote=emerleite][quote=Lezinho]Dependendo da infraestrutura do projeto, a página pode adicionar no meio persistente registros… sem passar por domain layers, repositórios nem nada … isso sem precisar codificar coisa alguma (ver EntityHome do Seam).
Em outras palavras, um dao, implementado pelo framework, acessa da página a infra. O domínio… continua isolado.[/quote]
Desculpe mas isso já saiu da argumentação para defesa a qualquer custo. Não faz o menor sentido o que você está falando. Para que ter todo o trabalho de organizar as coisas se você vai direto na fonte de dados passando por cima de tudo?
Com esses argumentos não faz mais sentido continuar essa discussão, IMO.[/quote]
E persistência de dados é responsabilidade do domínio?
[quote=pcalcado]Pensei um pouco e acho que entendi o que você está tentando dizer, Alessandro, me corrije se eu estiver errado.
O que você está tentando dizer é que denro de uma arquitetura de Camadas isso é válido, certo?
Se for isso você está correto, é válido sim, mas foge completamente da filosofia de Domain-Driven Design -assunto da discussão- e do Domain Model em si. Layered Architecture é uma premissa para um bom domínio mas não é porque você tem camadas que tem um domínio bem definido -e DDD é sobre domínios bem definidos. [/quote]
É isso Shoes. Domain é sobre domínio, e não sobre infra. O assunto decorreu sobre uma observaçao sua em relação a existencia ou não de uma camada de aplicação, o que pode ser útil muitas vezes e em outras não tão necessária, contudo isso tem mais haver com camadas do que DDD propriamente disso.
Inclusive, um tópico sobre isso para continuarmos sobre essa linha (menos DDD e mais camada) pode ser interessante para quem ainda não entendeu sobre a observação que fiz.
[quote=Lezinho][quote=emerleite][quote=Lezinho]Dependendo da infraestrutura do projeto, a página pode adicionar no meio persistente registros… sem passar por domain layers, repositórios nem nada … isso sem precisar codificar coisa alguma (ver EntityHome do Seam).
Em outras palavras, um dao, implementado pelo framework, acessa da página a infra. O domínio… continua isolado.[/quote]
Desculpe mas isso já saiu da argumentação para defesa a qualquer custo. Não faz o menor sentido o que você está falando. Para que ter todo o trabalho de organizar as coisas se você vai direto na fonte de dados passando por cima de tudo?
Com esses argumentos não faz mais sentido continuar essa discussão, IMO.[/quote]
E persistência de dados é responsabilidade do domínio?[/quote]
Não é esse o ponto. Como já foi dito diversas vezes nessa thread, os dados persistentes são um acidente, portanto, não deveriam ser acessados da forma que você disse num Design OO bem definido, seguindo os princípios de Domain-Driven-Design.
Agora, como também foi dito, ser válido em Layered Architecture é uma coisa, ser um Domínio bem definido é outra. Eu tinha entendido desde o começo e que o foco dessa discussão eram práticas de Dominios bem definidos. Anyway …
… anyway CRUD não tem haver com domínio (tanto que aqui ele foi chamado de acidente, não é mesmo).
Se alguém(ferramenta ou framework que for) faz isso (sem escrever nada de código), sem intervir na modelagem, sem intervir nas idéias e conceitos e ainda por cima é produtivo pra caramba… com certeza é bem vindo.
Correto. Mas só pra lembrar que seu exemplo do Seam direto no repositório, e este acumulando regras de negócio, não teve nada a ver com isso e não se encaixa nesse caso. Foi isso que se questionou
Seam direto no repositório? Do que você esta falando?
Uma discussão é sobre ter regras ou não no repositorio, outra coisa foi o questionamento sobre a UI acessar a infra (o que exemplifiquei).
Ao meu ver camada de aplicação é opcional e não afeta o domínio. Se a execução do domínio depende de um flow de sub-instruções, isto deveria estar em um Service e não em uma app-layer.
Ambos já foram discutidos. No caso do acesso ditero ao repositório por parte da UI, na opinião da maioria não foi uma alternativa legal, mas se você gostou, vá em frente.
Em nenhum momento questionou-se a escolha entre Service/App Layer/Colocar tudo no controller, em fim. O que se questionou foi a sua UI não ter uma fronteira bem definida com o restante do sistema.
Falei de Seam no ‘DAO’ mesmo (infra), repositorio não entra na jogada. Uma página acessando via EL um mecanismo de persistencia criado pelo framework… isso é muito útil para CRUD. Toquei no assunto mediante ao questionamento de via UI acessar DAO.
Outra coisa foi o assunto abordado de repositorios (não DAO) serem disponibilizados na UI. Assim como acesso entidades de domínio e Services, não encontrei motivos para não acessar os repositórios (nakeds? pode ser).
A não ser que você utilize SessionFaçade, não vejo pq fazer isso sempre.
[quote=Lezinho]Falei de Seam no ‘DAO’ mesmo (infra), repositorio não entra na jogada. Uma página acessando via EL um mecanismo de persistencia criado pelo framework… isso é muito útil para CRUD. Toquei no assunto mediante ao questionamento de via UI acessar DAO.
Outra coisa foi o assunto abordado de repositorios (não DAO) serem disponibilizados na UI. Assim como acesso entidades de domínio e Services, não encontrei motivos para não acessar os repositórios (nakeds? pode ser). [/quote]
Se achou bom pra vc, então toca o barco.
A não ser que você utilize SessionFaçade, não vejo pq fazer isso sempre.[/quote]
Ninguém disse sempre. O fato é que no seu exemplo, vc teve problemas pois seu repositório passou a ter responsabilidades demais. O fato aqui é que no seu caso, veja bem “seu caso e exemplo que você mesmo escreveu”, a opção adotada trouxe problemas, e IMO tende a acontecer mais vezes. De qualquer forma, seu exemplo também não era um simples CRUD, tanto que seu cliente pediu uma funcionalidade antes da gravação do registro. Portanto, não misturemos as coisas.
Ao meu ver não pela falta de uma application layer. Mesmo se ela existisse, eu teria que garantir que todo acesso ao repositório.add daquele objeto, deveria ser feito por aquela façade da aplicação. Eu mesmo disse que uma solução para aquele exemplo ela delegar a responsabilidade para um Service (nao App-L.), mas citei tbm o problema que pode causar. Contudo uma refatoração do modelo como o Shoes descreveu fica bom, com isso eu concordei.
Mas isso foi sobre camadas, nem tinha nada haver com o exemplo. Teve mais haver com afirmaçoes como essa:
CRUD faz arte do domínio, CRUD é como são persistidos, obtidos, atualizados e removidos objetos, poucas coisas têm tanta importância. Qulquer lógica de negócio (e CRUD, por mais simples que seja, é lógica de negócio) deve passar pelo domínio.
Como são persitidos e removidos o objeto? Estas não são aquelas questões de que isso é algo incomum para o objeto em sí (o que foi classificado como acidente)? Para o domínio, não seria interessante apenas que eles existissem … pronto para eventuais buscas?
Embora factories ofereçam capacidade para montar entre outras coisas objetos mais complexos, como Aggregaties, isso pode ser feito (na maioria das vezes) de maneira transparente pelos frameworks de persistências, assim dispensando em algumas vezes um intermédio necessário (no caso de repositórios que possuem sua implementação plugada em um DataMapper). Acredito que o mesmo valha para situações de persistência, atualização ou exclusão, onde alguma convenção no código pode tratar de forma natural estas atividades onde for cabível.
Se algum dia eu mudar a abstração do Repository, de maneira que não se utilize mais DataMapper mas qualquer outro meio persistente, eu crio mecanismos para montar de forma eficiente os objetos para aquela abstração, mas isso apenas se precisar, de forma incremental. O uso para operações de CRUD faço a mesma coisa, se um framework que me ajuda na tarefa de forma transparente (como AR do Rails em sua forma mais simples, ou o Seam em java) não interessar mais ou não servir, crio uma façade que delegue para o domínio a tarefa.
[quote=Lezinho]Como são persitidos e removidos o objeto? Estas não são aquelas questões de que isso é algo incomum para o objeto em sí (o que foi classificado como acidente)? Para o domínio, não seria interessante apenas que eles existissem … pronto para eventuais buscas?
Embora factories ofereçam capacidade para montar entre outras coisas objetos mais complexos, como Aggregaties, isso pode ser feito (na maioria das vezes) de maneira transparente pelos frameworks de persistências, assim dispensando em algumas vezes um intermédio necessário (no caso de repositórios que possuem sua implementação plugada em um DataMapper). Acredito que o mesmo valha para situações de persistência, atualização ou exclusão, onde alguma convenção no código pode tratar de forma natural estas atividades onde for cabível.
[/quote]
A única ocasião onde você precisa persistir seu objeto é quando ele muda de estado e onde ele muda de estado é no domínio. Se seu objeto não muda de estado na interface não há porque ele ser persistido na interface, se muda de estado na interface isso é um SmartUI e não um Domain Model.
Como disse antes, acredito que a ênfase que você deu em “não alterar muitas linhas de código” algumas mensagens atrás pode ser decorrente deste tipo de design. O ponto todo em ter uma Camada de Negócios é abstrair estas mudanças, como elas estão vazando para a interface qualquer mudança (como introduzir o observer mencionado antes) causa um problema para alterar todos os lugares.
Note que você pode considerar seu repositório como bom candidato para ser levado até à Camada de Apresentação e aind assim ter Domain-Driven Design, mas como falei seus problemas em implementar lógica de neócio fora do Repository e em ter que alterar muito código para mudanças simples podem ser decorrentes disso.
O Rails é um péssimo exemplo para este tópico, não há nenhuma preocupação com Domain-Driven Design nele, a lógica de persistência fica dentro das classes de negócio. Se voê quiser algo parecido tudo bem mas você está abrindo ão de Domain Model e consequentemente de Domain-Driven Design.
Phillip, você exibe formulários para o usuário inputar dados e estes estarem disponíveis para manipulação do sistema, certo? Quase sempre (não necessariamente) estes dados serão os mesmos que irão compor as informações dos objetos de domínio - sendo assim você não realiza binding dos campos do formulário diretamente nos objetos de domínio para que seu estado não seja alterado diretamente pela UI ? (durante o request, seu objeto receberá os dados da UI, seu estado estará alterado ou inicializado). Como você lida com isso?
Evans chama de SmartUI aquelas aplicações feitas no maior estilo “ASP-PHP” do começo deste século, onde na página se abarrotava lógica de negócio:
… ou o estilo VB6/Delphi:
Nas desvantagens do modelo, ele cita dificuldades para integrar a aplicação, falta de reaproveitamento de código entre outros. Mas o que sugeri não foi colocar as regras e lógicas de negócio na UI e estas desvantagens citadas não se aplicam neste caso, a camada de negócio existe. O que a UI tem é a invocação dos serviços da próxima camada, assim como ele disponibiliza os dados dos objetos que estão nesta outra camada adjacente. Da mesma forma que a UI faz entidade.getAtributo() em ${entidade.atributo} nos seus campos de um formulário, ela faz #{entidade.executaComportamento} no botão. o comportamento continua na entidade e pode ser utilizado em outras parte do sistema, (ele não esta na UI como Evans cita no anti-pattern).
Pois é, eu utilizo eles na camada de apresentação. A questão da dificuldade do refactoring Shoes, é mais atrelada a modelagem prévia do que com a interação com o resto do sistema. No seu segundo exemplo com Observer, caso fosse remover do Repository a lógica e adiciona-la a um Service, eu poderia remover a chamada antiga referenciada para o repository da UI e atribui-la agora para o novo Service. Caso tivesse a app-layer, o que mudaria é que o ponto de mudança ficaria na classe por detras da página, e não nela própriamente dita (o que pode ser interessante caso ela for reaproveitável).
Embora eu não citei explícitamente Rails na primeira página desta thread, eu estava pensando nele no começo desta thread, vide a primeira página:
… ainda que saiba que uma coisa é Activerecord e outra é como Rails se vale disso.
O que quis dizer quando citei o rails e o seam nas ultimas mensagens é fazer valer de algumas facilidades em relação as tecnologias sem ferir necessariamente a arquitetura do domínio. A maioria do sistema é repleta de cadastrinhos necessário do tipo “Id” e “Descrição” (entidades fracas na maioria das vezes anêmicas e sem comportamento algum). Se algo produtivo que não me force escrever código intrusivo da tecnologia no domínio e que resolva um problema de forma simples (sem codificar SmartUI), pq não usar? Se algo mudar e o simples “cadastro mágico”, sem código algum, ter um valor agregado maior para a aplicação, então neste momento eu refatoro aquele ponto para aplicar os padrões do domain.
Faça a analogia a uma entrega de funcionalidade em um sprint Scrum… você faz uma carga de dados em scripts para o cliente e ele utiliza uma tela mesmo sem possuir uma outra tela de cadastros (já q vc disponibilizou os dados pra ele), em outro momento (sprint) vc entrega o cadastro. Se um framework disponibiliza os dados de forma satisfatória, trasnparente e eu não preciso naquele momento de qualquer outro recurso extra do domínio para executar algo, então eu deixo para montar o que falta quando precisar e se precisar.
Não entendi o problema, meus formulários lidam com objetos do modelo, não com classes da inra-estrutura.
Se você chama a persistência diretamente da interface você tem que ter processamento de regras de negócio em algum lugar, se não é no Domain Model é na interface, logo qual a diferença pra Delphi/VB?
Eu discordo, mas já falei muito sobre isso e, sinceramente, não tenho mais o que acrescentar.
Você está msiturando conceitos completamente diferentes aqui. Uma coisa é o design ideal, que é o que se tenta fazer com Domain-Driven Design, outra coisa é como se chega nele. Se você colocou o repositório ali porque não tem tempo de consertar agora é uma coisa completamente diferente, eu estou falando sobre o design ideal da aplicação.
[quote=pcalcado][quote=Lezinho]
Evans chama de SmartUI aquelas aplicações feitas no maior estilo “ASP-PHP” do começo deste século, onde na página se abarrotava lógica de negócio:
… ou o estilo VB6/Delphi:
Nas desvantagens do modelo, ele cita dificuldades para integrar a aplicação, falta de reaproveitamento de código entre outros. Mas o que sugeri não foi colocar as regras e lógicas de negócio na UI e estas desvantagens citadas não se aplicam neste caso, a camada de negócio existe. O que a UI tem é a invocação dos serviços da próxima camada, assim como ele disponibiliza os dados dos objetos que estão nesta outra camada adjacente. Da mesma forma que a UI faz entidade.getAtributo() em ${entidade.atributo} nos seus campos de um formulário, ela faz #{entidade.executaComportamento} no botão. o comportamento continua na entidade e pode ser utilizado em outras parte do sistema, (ele não esta na UI como Evans cita no anti-pattern).
[/quote]
Se você chama a persistência diretamente da interface você tem que ter processamento de regras de negócio em algum lugar, se não é no Domain Model é na interface, logo qual a diferença pra Delphi/VB?[/quote]
Acho que ele está fazendo um sistema tão simples, sem nenhuma regra de negócio, que apenas realiza cadastros e nunca vai ter necessidade de ter um Domain Model de verdade. Portanto, pode fazer em ASP|PHP que vai sair muito mais rápido. Ou até mesmo em .Net usando Visual Studio e o recurso de Table Module que já é nativo da plataforma. Ficará pronto em segundos.
Shoes, seu formulário lida com objetos de modelo na camada de apresentação, ele recebe e exibe dados por essa camada. Ao receber os dados pelo formulário e este ser submetido, o próprio binding dos campos atualiza o estado de seu objeto em qualquer ferramenta MVC. A camada de negócio já recebe este objeto em novo estado atualizado, é sobre isso que postei.
Processamento de regra de negócio eu tenho e esta na camada de negócio:
A persistencia nas RAds é tratada sobre um componente pouco reutilizável que muitas vezes é colocado escancarado sobre a própria UI. Ja nas páginas não existe componente associado, uma EL que pode ser qualquer coisa que faz as invocações.