DDD - O modelo de domínio anêmico é um antipadrão? Devemos usar modelos de domínio sofisticados? [fechadas]

11

O modelo de domínio anêmico foi criticado há muito tempo por Evans e Fowler , uma vez que aparentemente contraria princípios orientados a objetos etc. A comunidade DDD está claramente alinhada com essas afirmações.

No entanto, nos últimos anos, houve vozes discordantes alegando que não é um antipadrão e que é um exemplo de seguir os princípios do SOLID.

Trabalho há muitos anos usando o Spring Framework. Todo projeto em toda empresa sempre teve uma camada de serviço contendo a lógica de negócios, usando repositórios que operam em modelos anêmicos (entidades JPA). Além disso, a maioria das amostras, mesmo as oficiais dos caras da Spring, mostra esse modo de trabalhar.

Minhas perguntas são: o modelo de domínio anêmico ainda é considerado um antipadrão? Todos nós fizemos coisas erradas (em relação ao DDD)? Você não acha que ter modelos Rich Domain viola os princípios do SOLID?

co-dependente
fonte
2
"o modelo de domínio anêmico ainda é considerado um antipadrão? ". Por alguns, sim. Outras pessoas, inclusive eu, o veem como a maneira preferível de escrever código na maioria das vezes, mas se o RDM lhe convier, use-o. Então, votando para encerrar isso como puramente baseado em opiniões.
David Arno
11
Essa seria uma pergunta fantástica para um fórum de discussão / debate; mas atualmente não há uma resposta oficial. Preferimos perguntas que possam ser respondidas, não apenas discutidas.
VoiceOfUnreason

Respostas:

9

O ADM é um bom padrão para uma solução de serviços distribuídos, como microsserviços. Ele se encaixa em muitos dos casos de negócios baseados na Web de hoje.

Considere se temos um objeto Domínio do Pedido. Com uma abordagem OOP, adicionaríamos Order.Purchase () Order.Cancel () etc. Funcionaria bem em um aplicativo de desktop, onde mantemos pedidos na memória e fazemos várias coisas na mesma instância.

Mas se tivermos um sistema distribuído, com programas que apenas uma coisa, ou seja, acessar uma lista de pedidos e comprar cada um por vez, ou obter uma lista de pedidos e cancelar cada um por vez, ter os dois Métodos no mesmo objeto não fará com que sentido. Teríamos que ter dois domínios ou contextos vinculados:

PurchaseSystemOrder.Purchase()

e

CancelSystemOrder.Cancel();

A única coisa que esses objetos compartilhariam seria a estrutura de dados das propriedades.

À medida que você adiciona mais e mais microsserviços, você acaba com dezenas de tipos de pedidos. Não faz mais sentido falar sobre uma Ordem como um objeto de Domínio, mesmo que seja a mesma ordem conceitual que está sendo processada por todos esses sistemas.

Faz muito mais sentido ter um modelo anêmico, Order, que apenas encapsula apenas os dados e renomeia seus serviços de acordo:

PurchaseService.Purchase(Order order)

Agora podemos falar sobre o Order novamente e podemos adicionar quaisquer novos serviços que pensamos em processar, sem afetar os outros serviços atualmente implantados.

Fowler e Co vêm de um sistema monolítico, em seu mundo uma abordagem ADM significaria um único aplicativo com todos esses serviços separados instanciados na memória e o OrderDTO sendo repassado e mutado. Isso seria muito pior do que colocar os métodos em um modelo rico de pedidos.

Porém, em um sistema distribuído, existem muitos programas, cada um requer apenas um método Order e o executa em vários pedidos, carregando cada um, executando o método e depois descartando-o. Requer apenas um único serviço e um fluxo de objetos de dados.

Preencher um modelo completo por completo, preocupar-se com os requisitos e dependências de todos os Métodos apenas para chamar um único e depois descartar o objeto quase imediatamente é inútil.

Além disso, uma alteração em um único método exigiria a atualização de todos os componentes distribuídos, pois todos eles dependem do Modelo Rico para sua lógica.

Não tenho espaço na (s) minha (s) base (s) de código para itens que não precisam

Ewan
fonte
4
Eu diminuí a votação porque acho que o DDD é particularmente adequado para microsserviços precisamente devido ao conceito de contexto limitado. Acho que o problema com sua resposta é que você solicita o conceito e a classe em todos os microsserviços, mas acho que isso não é necessário nem preciso.
RibaldEddie
Eu não discordo, a ADM pode ser DDD se você chamar seu PurchaseService CashRegister e torná-lo parte de sua linguagem de domínio
Ewan
Você pode elaborar? Eu sempre pensei que o YMMV quando ADM e DDD estavam em uma base de código EF SOLID J2EE ou .NET C # MVC EF.
RibaldEddie
O que quero dizer é que o contexto limitado Order, PurchaseSystemOrder.Purchase () será um código praticamente idêntico ao CashRegister.Purchase (Order order) é apenas uma alteração de nome no idioma do seu domínio. Um modelo de domínio avançado significa ter os métodos Purchase e Cancel na mesma classe.
Ewan
11
@RibaldEddie, Na veia da espessura do "JavaScript, as partes boas" livro, ofereço esta imagem como um argumento (não completamente sério) contra o uso de DDD para a implementação microservices;)
David Arno
3

O SOLID e o DDD são ortogonais entre si, o que significa que eles estão realmente indo em direções diferentes um do outro. Você não deve dizer que um está acostumado à exclusão do outro, pois eles podem e provavelmente devem existir juntos na mesma base de código.

Os modelos de domínio anêmico só se tornam um antipadrão quando o domínio do problema tem muito comportamento e você tem centenas de métodos de serviço com muitas lógicas ou dependências de cópia colada, onde os métodos da camada de serviço precisam chamar outros métodos da camada de serviço para fazer qualquer coisa.

O DDD é um excelente paradigma para microsserviços devido ao conceito de contexto limitado .

Cuidado com a tentação de ver o código de infraestrutura como parte do seu domínio. Código de infraestrutura é qualquer coisa que você não tenha escrito ou que esteja acoplado a uma estrutura ou biblioteca que interaja com um sistema de terceiros. Conexões com banco de dados, mala direta SMTP, bibliotecas ORM, tempos de execução do servidor de aplicativos, tudo isso é infraestrutura e você não deve incluir ou depender dela em seu domínio, se puder evitá-la.

Os princípios do SOLID são um conjunto de conceitos de OOP de uso geral que você pode usar para criar um melhor código de OOP. Você pode escrever uma boa base de código DDD usando-as.

RibaldEddie
fonte
Em relação à separação do código de infraestrutura do domínio. Até agora, eu havia considerado as entidades JPA meu domínio, com as seguintes camadas de aplicativos: controller -> service -> repository -> domain (entidades JPA). Quais seriam as maneiras corretas (ou uma das corretas) de modelá-lo de acordo com o seu argumento? Algo como: controller -> rich model -> x? Como e onde eu lidaria com a transacionalidade? E o mapeamento JPA? Não teríamos que duplicar nosso rico modelo com entidades JPA separadas?
co-dependente
Uma entidade JPA é um objeto Java antigo simples. O mapeamento faz parte da infraestrutura, mas a própria classe não precisa ser. Se você optar por tratá-lo como parte da infraestrutura, considere-o como um objeto de transferência de dados usado no Factory ou no Repository para criar uma Entidade de domínio.
RibaldEddie
1

Um domínio rico é bom quando bem executado. Um pesadelo quando não. Um domínio anêmico é sempre ruim. Mas é um tipo familiar e confortável de ruim.

Se um domínio anêmico é tudo o que você deseja, escolheu o idioma errado quando escolheu um idioma de uso geral. Os idiomas de quarta geração se especializam em um uso específico. Se a anemia for boa o suficiente, sua vida teria facilitado sua vida.

Muitas estruturas abrem caminho no espaço da linguagem até que você não possa mais anunciar o trabalho como um trabalho em java. É um trabalho Java / Spring. O que eles estão fazendo, além de fazer você depender deles, é transformar uma linguagem de propósito geral em uma forma bastarda de uma linguagem de quarta geração.

Essa é uma prática recomendada ou antipadrão? Bem, seu chefe se preocupa principalmente se você pode contratar pessoas para trabalhar na base de código. Portanto, se tivermos que fingir que estamos usando uma linguagem de uso geral para contratar pessoas, o faremos.

Se você está bem com isso, tudo bem. Você certamente não é o único.

Mas não me diga que é assim que deve ser. Não me diga que está fazendo algo por mim mais do que está. Eu sei viver sem isso. Eu sei como empurrar para fora, então apenas algumas coisas dependem disso. Se você está me pedindo para desistir e deixar que tudo assuma tudo, porque lutar é difícil demais, sim, acho que isso é ruim.

Não tenho espaço na minha base de código para coisas que não precisam.

Quanto ao SOLID e aos outros princípios de design, posso seguir em grande parte aqueles mesmo em um domínio anêmico. Não segui-los causa um tipo diferente de problema.

candied_orange
fonte
Agradeço sua resposta e concordo absolutamente que algumas estruturas, como Spring ou JPA-Hibernate, conquistaram o cenário Java. No entanto, também é inegável que eles forneceram um monte de boas práticas e simplificações que o Java (JEE) não abordou de maneira alguma ou fez de maneira errada. experiência, quais são as melhores plataformas / idiomas / estruturas para trabalhar com aplicativos DDD puros (com modelos de domínio rico)? Alguma boa amostra do Github que você conhece? Como você diz, quero fazer bem as coisas, não me conformar com as más práticas.
co-dependente
Não fazemos recomendações de recursos aqui. Mas acredito que uma camada de infraestrutura adequada que lide com estruturas significa que você pode usar qualquer tipo que desejar. Apenas trate-os como uma biblioteca. Mantenha o conhecimento deles fora do domínio. Além disso, não confie na mágica. Resista ao desejo de usar coisas que você não poderia fazer. Porque algum dia você pode precisar.
candied_orange
Voltando ao ponto original. E os princípios do SOLID? Os modelos de domínio avançado assumem muitas responsabilidades, persistência (JPA), lógica de negócios (tendo que lidar com transacionalidade) etc. Os modelos anêmicos, por outro lado, se preocupam apenas com a persistência de ter serviços separados lidando com a lógica de negócios. Parece também mais fácil de testar. O que há de tão errado nisso então?
co-dependente
O principal é que você comece a fazer escolhas de design com base nas necessidades do sistema e não nas necessidades semânticas. É sutil, fácil de ignorar, o custo não é óbvio e difícil de justificar a correção. Em resumo, é como argumentar que as linhas de energia devem ser enterradas, e não nas pesquisas. Uma vez que as pessoas se acostumam com a alternativa, não é provável que mude. Mesmo quando os furacões derrubam o poder.
candied_orange
11
Eu daria a você o benefício da dúvida sobre sua afirmação de que "um domínio rico é bom quando bem feito. Um pesadelo quando não." Talvez eu nunca tenha visto isso bem, mas você faz o absurdo afirmar que "um domínio anêmico é sempre ruim". Bobagem opinativa tornando sua resposta inútil. -1
David Arno