DDD - ¿Es el modelo de dominio anémico un antipatrón? ¿Deberíamos usar modelos de dominio ricos? [cerrado]

11

Evans y Fowler criticaron hace mucho tiempo el modelo de dominio anémico , ya que aparentemente va en contra de los principios orientados a objetos, etc. La comunidad DDD está claramente alineada con estas afirmaciones.

Sin embargo, en los últimos años ha habido voces en desacuerdo que afirman que no es un antipatrón en absoluto y que es un ejemplo de seguir los principios SÓLIDOS.

He estado trabajando durante muchos años usando Spring Framework. Cada proyecto en cada empresa siempre ha tenido una capa de servicio que contiene la lógica empresarial, utilizando repositorios que operan en modelos anémicos (entidades JPA). Además, la mayoría de las muestras, incluso las oficiales de los chicos de Spring, muestran esta forma de trabajar.

Mis preguntas son: ¿todavía se considera que el modelo de dominio anémico es un antipatrón? ¿Todos hemos estado haciendo cosas (con respecto a DDD) mal? ¿No crees que tener modelos Rich Domain viola los principios SOLID?

codependiente
fuente
2
" ¿El modelo de dominio anémico todavía se considera un antipatrón? ". Por algunos, sí. Otros, incluido yo mismo, lo veo como la forma preferible de escribir código la mayor parte del tiempo, pero si el RDM le conviene, úselo. Entonces, votar para cerrar esto es puramente basado en la opinión.
David Arno
1
Esta sería una pregunta fantástica para un foro de discusión / debate; pero actualmente no hay una respuesta autorizada. Preferimos preguntas que puedan responderse, no solo discutirse.
VoiceOfUnreason el

Respuestas:

9

ADM es un buen patrón para una solución de servicios distribuidos como microservicios. Se adapta a muchos de los casos comerciales actuales basados ​​en la web.

Considere si tenemos un objeto Order Domain. Con un enfoque OOP, agregaríamos Order.Purchase () Order.Cancel (), etc. Funcionaría bien en una aplicación de escritorio, donde guardamos pedidos en la memoria y hacemos varias cosas en la misma instancia.

Pero si tenemos un sistema distribuido, con programas que solo tienen una cosa, es decir, acceder a una lista de pedidos y comprar cada uno por turno, u obtener una lista de pedidos y cancelarlos por turno, entonces tener ambos métodos en el mismo objeto no hace sentido. Tendríamos que tener dos dominios o contextos limitados:

PurchaseSystemOrder.Purchase()

y

CancelSystemOrder.Cancel();

Lo único que compartirían estos objetos sería la estructura de datos de las propiedades.

A medida que agrega más y más microservicios, termina con docenas de tipos de Orden. Ya no tiene sentido hablar de una Orden como un objeto de Dominio, a pesar de que es el mismo orden conceptual que están procesando todos estos sistemas.

Tiene mucho más sentido tener un modelo anémico, Order, que encapsula solo los datos y cambia el nombre de sus servicios en consecuencia:

PurchaseService.Purchase(Order order)

Ahora podemos hablar sobre Order nuevamente y podemos agregar cualquier servicio nuevo que pensemos para procesar, sin afectar los otros servicios implementados actualmente.

Fowler y Co provienen de un entorno de sistema monolítico, en su mundo, un enfoque ADM significaría una sola aplicación con todos estos servicios separados instanciados en la memoria y el OrderDTO se pasa y muta. Esto sería mucho peor que poner los métodos en un modelo de Orden rico.

Pero en un sistema distribuido, hay muchos programas, cada uno solo requiere un único método de Pedido y lo ejecuta en múltiples pedidos, carga cada uno, ejecuta el método y luego lo descarta. Solo requiere un único Servicio y una secuencia de objetos de datos.

Rellenar un modelo rico por completo, preocuparse por los requisitos y dependencias de todos los métodos solo para llamar a uno solo y luego descartar el objeto casi de inmediato no tiene sentido.

Además, un cambio a uno solo de los métodos requeriría actualizar todos los componentes distribuidos, ya que todos dependen del Modelo Rico para su lógica.

No tengo espacio en mi (s) base (s) de código para cosas que no necesitan

Ewan
fuente
44
Voté en contra porque creo que DDD es particularmente adecuado para microservicios precisamente debido al concepto de contexto acotado. Creo que el problema con su respuesta es que el concepto de pedido y la clase serían los mismos en cada microservicio, pero creo que eso no es necesario ni preciso.
RibaldEddie
No estoy en desacuerdo, ADM puede ser DDD si llama a su PurchaseService CashRegister y lo hace parte de su idioma de dominio
Ewan
¿puedes elaborar? Siempre pensé que YMMV cuando ADM y DDD estaban en una base de código SOLID J2EE o .NET C # MVC EF.
RibaldEddie
Lo que quiero decir es que el orden de contexto acotado, PurchaseSystemOrder.Purchase () será un código bastante idéntico a CashRegister.Purchase (orden de pedido) es solo un cambio de nombre en el idioma de su dominio. Un modelo de dominio rico significa tener los métodos Comprar y Cancelar en la misma clase.
Ewan
1
@RibaldEddie, En la línea del grosor del libro "javaScript, las partes buenas", ofrezco esta imagen como un argumento (no completamente serio) contra el uso de DDD para implementar microservicios;)
David Arno
3

SOLID y DDD son ortogonales entre sí, lo que significa que realmente van en direcciones diferentes entre sí. No debe decir que uno está acostumbrado a excluir al otro, ya que pueden y probablemente existan juntos en la misma base de código.

Los modelos de dominio anémico solo se convierten en un antipatrón una vez que su dominio problemático tiene mucho comportamiento y tiene cientos de métodos de servicio con muchas lógicas o dependencias pegadas por copia donde los métodos de capa de servicio tienen que llamar a otros métodos de capa de servicio para hacer algo.

DDD es un excelente paradigma para los microservicios debido al concepto de contexto acotado .

Tenga cuidado con la tentación de ver el código de infraestructura como parte de su dominio. El código de infraestructura es cualquier cosa que no haya escrito usted mismo o cualquier cosa que esté acoplada a un marco o biblioteca que interactúa con un sistema de terceros. Conexiones de bases de datos, correos SMTP, bibliotecas ORM, tiempos de ejecución del servidor de aplicaciones, todo eso es infraestructura y no debe incluirlo ni depender de él en su dominio si puede evitarlo.

Los principios SÓLIDOS son un conjunto de conceptos OOP de propósito general que puede usar para crear un mejor código OOP. Puede escribir una buena base de código DDD con ellos.

RibaldEddie
fuente
En cuanto a la separación del código de infraestructura del dominio. Hasta ahora había considerado las Entidades JPA como mi dominio, teniendo las siguientes capas de aplicación: controlador -> servicio -> repositorio -> dominio (Entidades JPA). ¿Cuáles serían las formas correctas (o una de las correctas) de modelarlo según su punto? Algo así como: controlador -> modelo rico -> x? ¿Cómo y dónde trataría con la transaccionalidad? ¿Y qué hay del mapeo JPA? ¿No tendríamos que duplicar nuestro modelo rico con entidades JPA separadas?
codependiente
Una entidad JPA es un objeto Java antiguo simple. El mapeo es parte de la infraestructura, pero la clase en sí no tiene que serlo. Si elige tratarlo como parte de la infraestructura, debe considerarlo como un objeto de transferencia de datos que se utiliza en la Fábrica o el Repositorio para crear una Entidad de dominio.
RibaldEddie
1

Un dominio rico es bueno cuando se hace bien. Una pesadilla cuando no. Un dominio anémico siempre es malo. Pero es un tipo de mal familiar y cómodo.

Si un dominio anémico es todo lo que siempre desea, elige el idioma equivocado cuando elige un idioma de propósito general. Los lenguajes de cuarta generación se especializan en torno a un uso específico. Si anémico es lo suficientemente bueno, usarlos habría hecho su vida más fácil.

Muchos frameworks se abren paso en el espacio del lenguaje hasta que ya no puede anunciar el trabajo como un trabajo de Java. Es un trabajo de Java / Spring. Lo que están haciendo, además de hacerte depender de ellos, es convertir un lenguaje de propósito general en una forma bastarda de un lenguaje de cuarta generación.

¿Es esa una mejor práctica o un anti patrón? Bueno, su jefe se preocupa principalmente por si puede contratar personas para trabajar en la base del código. Entonces, si tenemos que fingir que estamos usando un lenguaje de propósito general para contratar personas, lo haremos.

Si estás de acuerdo con eso, entonces está bien. Ciertamente no eres el único.

Pero no me digas que así es como tiene que ser. No me digas que está haciendo algo por mí más de lo que es. Sé vivir sin eso. Sé cómo sacarlo, así que solo unas pocas cosas dependen de ello. Si me estás pidiendo que me rinda y deje que se haga cargo de todo solo porque luchar es muy difícil, entonces sí, creo que es malo.

No tengo espacio en mi base de código para cosas que no necesita.

En cuanto a SOLID y los otros principios de diseño, puedo seguirlos en gran medida incluso en un dominio anémico. No seguirlos causa un tipo diferente de problema.

naranja confitada
fuente
Agradezco su respuesta y estoy totalmente de acuerdo en que algunos marcos como Spring o JPA-Hibernate han conquistado el paisaje de Java. Sin embargo, también es innegable que han proporcionado un montón de buenas prácticas y simplificaciones que Java (JEE) no abordó en absoluto o hizo mal. Estoy realmente entusiasmado con DDD y me gustaría entender todos los principios que dicen. experiencia, ¿cuáles son las mejores plataformas / idiomas / marcos para trabajar con aplicaciones DDD puras (con modelos de dominio enriquecido)? ¿Alguna buena muestra de Github que conozcas? Como dices, quiero hacer las cosas bien, no conformarme con las malas prácticas.
codependiente
No hacemos recomendaciones de recursos aquí. Pero creo que una capa de infraestructura adecuada que se ocupa de los marcos significa que puede usar el tipo que desee. Solo trátalos como una biblioteca. Mantenga el conocimiento de ellos fuera del dominio. Además, no confíes en la magia. Resista el impulso de usar cosas que no podría hacer usted mismo. Porque algún día puede que necesites hacerlo.
candied_orange
Volviendo al punto original. ¿Qué pasa con los principios SÓLIDOS? Los modelos de dominio rico asumen muchas responsabilidades, persistencia (JPA), lógica empresarial (tener que lidiar con la transaccionalidad), etc. Los modelos anémicos, por otro lado, solo se preocupan por la persistencia de tener servicios separados que se ocupan de la lógica empresarial. Suena también más fácil de probar. ¿Qué tiene de malo entonces?
codependiente
Lo principal es comenzar a tomar decisiones de diseño basadas en las necesidades del sistema en lugar de las necesidades semánticas. Es sutil, fácil de ignorar, el costo no es obvio y difícil de justificar. En resumen, es como argumentar que las líneas eléctricas deben estar enterradas en lugar de en las encuestas. Una vez que las personas se acostumbren a la alternativa barata, no es probable que cambie. Incluso cuando los huracanes noquean el poder.
candied_orange
1
Iba a darle el beneficio de la duda sobre su afirmación de que "Un dominio rico es bueno cuando se hace bien. Una pesadilla cuando no". Tal vez nunca lo he visto bien, pero luego haces la afirmación absurda de que "un dominio anémico siempre es malo". Tonterías de opinión que hacen que su respuesta sea inútil. -1
David Arno