tutorial que por libro impulsado driven dominio domain diseño development ddd design-patterns architecture domain-driven-design presentation-layer data-transfer-objects

design-patterns - que - libro ddd



¿Por qué debería aislar las entidades de mi dominio de mi capa de presentación? (14)

Aquí hay un ejemplo real de por qué me parece una buena práctica separar entidades de dominio de la vista.

Hace unos meses, creé una IU simple para mostrar los valores de Nitrógeno, Fósforo y Potasio en una muestra de suelo a través de una serie de 3 medidores. Cada indicador tenía una sección roja, verde y roja, es decir, podía tener muy poco o demasiado de cada componente, pero había un nivel verde seguro en el medio.

Sin pensar mucho, modelé mi lógica comercial para suministrar datos para estos 3 componentes químicos y una hoja de datos separada, que contenía datos sobre los niveles aceptados en cada uno de los 3 casos (incluida la unidad de medida que se estaba utilizando, es decir, moles o porcentaje). Luego modelé mi interfaz de usuario para usar un modelo muy diferente, este modelo estaba preocupado por las etiquetas, valores, valores límite y colores.

Esto significaba que cuando más tarde tenía que mostrar 12 componentes, simplemente asignaba los datos adicionales en 12 nuevos modelos de vista de medidor y aparecían en la pantalla. También significaba que podía reutilizar el control del indicador fácilmente y hacer que mostraran otros conjuntos de datos.

Si hubiera acoplado estos medidores directamente a las entidades de mi dominio, no tendría ninguna de las anteriores flexibilidad y cualquier modificación futura sería un dolor de cabeza. He encontrado problemas muy similares al modelar calendarios en la interfaz de usuario. Si hay un requisito para que una cita del calendario se vuelva roja cuando hay más de 10 asistentes, entonces la lógica comercial para manejar esto debe permanecer en la capa empresarial y todo el calendario en la UI necesita saber, es que se le ha instruido a se pone rojo, no debería necesitar saber por qué.

Una parte del diseño impulsado por dominio en el que no parece haber muchos detalles es cómo y por qué debe aislar su modelo de dominio de su interfaz. Intento convencer a mis colegas de que esta es una buena práctica, pero parece que no avanzo mucho ...

Usan entidades de dominio donde quieran en las capas de presentación e interfaz. Cuando les digo que deberían usar modelos de visualización o DTO para aislar la capa de dominio de la capa de interfaz, contrarrestan que no ven el valor de negocio al hacer algo como eso, porque ahora tienen un objeto de interfaz de usuario para mantener así como el objeto de dominio original.

Así que estoy buscando algunas razones concretas que pueda utilizar para respaldar esto. Específicamente:

  1. ¿Por qué no deberíamos usar objetos de dominio en nuestra capa de presentación?
    (Si la respuesta es obvia, ''desacoplamiento'', entonces explique por qué esto es importante en este contexto)
  2. ¿Deberíamos usar objetos o construcciones adicionales para aislar nuestros objetos de dominio de la interfaz?

Con la ayuda de herramientas como '' Value Injecter '' y el concepto de ''Mappers'' en la capa de presentación mientras se trabaja con vistas, es mucho más fácil entender cada fragmento de código. Si tiene un poco de código, no verá las ventajas de inmediato, pero cuando su proyecto crecerá cada vez más, estará muy contento trabajando con las vistas para no tener que entrar en la lógica de los servicios, repositorios para comprender el modelo de vista. View Model es otra protección en el vasto mundo de la capa anticorrupción y vale su peso en oro en un proyecto a largo plazo.

La única razón por la que no veo ninguna ventaja de usar el modelo de vista es si su proyecto es pequeño y lo suficientemente simple como para tener vistas vinculadas directamente a cada propiedad de su modelo. Pero si en el futuro, el requisito cambia y algunos controles en las vistas no se vincularán al modelo y usted no tiene un concepto de modelo de vista, comenzará a agregar parches en muchos lugares y comenzará a tener un código heredado que no lo apreciarás Claro, puedes hacer algunas refactorizaciones para transformar tu modelo de vista en view-viewmodel y seguir el principio de YAGNI sin agregar código si no lo necesitas pero para mí mismo, es mucho más una buena práctica que debo seguir para agregar un capa de presentación que expone solo objetos del modelo de visualización.



Estamos usando el mismo modelo en el servidor y en la interfaz de usuario. Y es un dolor. Tenemos que refactorizarlo algún día.

Los problemas se deben principalmente a que el modelo de dominio debe cortarse en trozos más pequeños para poder serializarlo sin tener toda la base de datos referenciada. Esto hace que sea más difícil de usar en el servidor. Los enlaces importantes faltan. Algunos tipos tampoco son serializables y no se pueden enviar al cliente. Por ejemplo, ''Tipo'' o cualquier clase genérica. Deben ser no genéricos y el Tipo debe transferirse como cadena. Esto genera propiedades adicionales para la serialización, son redundantes y confusas.

Otro problema es que las entidades en la interfaz de usuario realmente no encajan. Estamos utilizando enlaces de datos y muchas entidades tienen muchas propiedades redundantes solo para fines de la interfaz de usuario. Además, hay muchos ''BrowsableAttribute'' y otros en el modelo de entidad. Esto es realmente malo

Al final, creo que es solo cuestión de qué camino es más fácil. Puede haber proyectos donde simplemente funciona bien y donde no es necesario escribir otro modelo de DTO.


Estoy en desacuerdo.

Creo que la mejor manera de hacerlo es comenzar con objetos de dominio en su capa de presentación HASTA QUE TENGA SENTIDO DE HACER LO CONTRARIO.

Contrariamente a la creencia popular, "objetos de dominio" y "objetos de valor" pueden coexistir felizmente en la capa de presentación. Y esta es la mejor manera de hacerlo: obtienes el beneficio de ambos mundos, duplicación reducida (y código repetitivo) con los objetos del dominio; y la personalización y simplificación conceptual del uso de objetos de valor en las solicitudes.


He luchado con esto yo mismo. Hay casos donde tiene sentido usar DTO en presentación. Digamos que quiero mostrar un menú desplegable de Empresas en mi sistema y necesito su identificación para vincular el valor.

Bien, en lugar de cargar un CompanyObject que podría tener referencias a suscripciones o quién sabe qué más, podría enviar de vuelta un DTO con el nombre y el ID. Este es un buen uso en mi humilde opinión.

Ahora toma otro ejemplo. Tengo un objeto que representa una Estimación, esta estimación puede estar compuesta por mano de obra, equipo, etc., podría tener muchos cálculos definidos por el usuario que toman todos estos elementos y los resumen (cada estimación podría ser diferente con diferentes tipos de cálculos). ¿Por qué debería tener que modelar este objeto dos veces? ¿Por qué no puedo simplemente enumerar mi IU sobre los cálculos y mostrarlos?

Generalmente no uso DTO para aislar mi capa de dominio de mi UI. Los uso para aislar mi capa de dominio de un límite que está fuera de mi control. La idea de que alguien coloque información de navegación en su objeto comercial es ridícula, no contamine su objeto comercial.

¿La idea de que alguien ponga la validación en su objeto comercial? Bueno, yo digo que esto es algo bueno. Su interfaz de usuario no debe ser la única responsable de validar sus objetos comerciales. Su capa de negocios DEBE hacer su propia validación.

¿Por qué pondrías el código de generación de UI en un objeto busienss? En mi caso, tengo objetos separados que generan el código de UI separado de la interfaz de usuario. He analizado objetos que convierten mis objetos comerciales en Xml, la idea de separar las capas para evitar este tipo de contaminación es tan extraña para mí, porque ¿por qué incluso colocar código HTML de generación en un objeto comercial ...?

Editar Como creo un poco más, hay casos en que la información de UI podría pertenecer a la capa de dominio. Y esto podría nublar lo que usted llama una capa de dominio, pero trabajé en una aplicación multi-tenant, que tenía un comportamiento muy diferente tanto en el aspecto de la interfaz de usuario como en el flujo de trabajo funcional. Dependiendo de varios factores. En este caso, teníamos un modelo de dominio que representaba a los inquilinos y su configuración. Su configuración pasó a incluir información de UI (etiquetas para campos genéricos, por ejemplo).

Si tuviera que diseñar mis objetos para que sean persistentes, ¿debería también duplicar los objetos? Tenga en cuenta que si desea agregar un nuevo campo ahora tiene dos lugares para agregarlo. Tal vez esto plantea otra pregunta si el uso de DDD, ¿son todos objetos de dominio de entidades persistentes? Sé que en mi ejemplo lo fueron.


La única razón sensata para agregar mapeo adicional entre semántica generalizada y específica de dominio es que tiene (acceso) a un cuerpo existente de código (y herramientas) que se basan en una semántica generalizada (pero mapeable) distinta de la semántica de su dominio.

Los diseños controlados por dominio funcionan mejor cuando se usan junto con un conjunto ortogonal de marcos de dominio funcional (como ORM, GUI, Workflow, etc.). Recuerde siempre que la semántica del dominio debe exponerse solo en las adyacencias de la capa externa. Normalmente, este es el front-end (GUI) y el back-end persistente (RDBM, ORM). Cualquier capa intermedia efectivamente diseñada puede y debe ser invariante de dominio.


La respuesta depende de la escala de su aplicación.

Aplicación simple CRUD (Crear, Leer, Actualizar, Eliminar)

Para aplicaciones básicas de crud no tienes ninguna funcionalidad. Agregar DTO en la parte superior de las entidades sería una pérdida de tiempo. Aumentaría la complejidad sin aumentar la escalabilidad.

Moderadamente complicado Aplicación no CRUD

En este tamaño de aplicación, tendrá pocas entidades que tengan un ciclo de vida verdadero y una lógica de negocios asociada a ellas.

Agregar DTOs en este caso es una buena idea por dos razones:

  • La capa de presentación solo puede ver el subconjunto de campos que tiene la entidad. Encapsulas Entidades
  • Sin acoplamiento entre el back-end y el frontend
  • Si tiene métodos comerciales dentro de las entidades, pero no en DTO, entonces agregar DTO significa que el código externo no puede arruinar el estado de su entidad.

Aplicación empresarial complicada

Una sola entidad puede necesitar múltiples formas de presentación. Cada uno de ellos necesitará diferentes conjuntos de campos. En este caso, encontrará los mismos problemas que en el ejemplo anterior más la necesidad de controlar la cantidad de campos visibles para cada cliente. Tener DTO por separado para cada cliente lo ayudará a elegir lo que debería ser visible.


Lo haces por el mismo motivo por el que mantienes SQL fuera de tus páginas ASP / JSP.

Si solo conserva un objeto de dominio, para usar en la capa de dominio AND de presentación, entonces ese único objeto pronto se volverá monolítico. Comienza a incluir el código de validación UI, el código de navegación UI y el código de generación UI. Luego, pronto agrega todos los métodos de la capa de negocios además de eso. Ahora su capa de negocios y su IU están mezclados, y todos ellos están jugando en la capa de entidades de dominio.

¿Desea reutilizar ese nítido widget UI en otra aplicación? Bueno, tienes que crear una base de datos con este nombre, estos dos esquemas y estas 18 tablas. También debe configurar Hibernate y Spring (o sus marcos de trabajo de elección) para realizar la validación comercial. Ah, también debe incluir estas otras 85 clases no relacionadas porque están referenciadas en la capa empresarial, que simplemente está en el mismo archivo.


Maldita sea, juro que dijo persistencia.

De todos modos, es una instancia más de lo mismo: la ley de Parnas dice que un módulo debe mantener un secreto, y el secreto es un requisito que puede cambiar. (Bob Martin tiene una regla que es otra versión de esto.) En un sistema como este, la presentación puede cambiar independientemente del dominio . Como, por ejemplo, una empresa que mantiene los precios en euros y usa el francés en las oficinas de la empresa, pero quiere presentar los precios en dólares con texto en mandarín. El dominio es el mismo; la presentación puede cambiar Entonces, para minimizar la fragilidad del sistema, es decir, la cantidad de cosas que se deben cambiar para implementar un cambio en los requisitos, separe las preocupaciones.


Se trata de dependencias en su mayor parte. La estructura funcional central de la organización tiene sus propios requisitos funcionales, y la IU debería permitir a las personas modificar y ver el núcleo; pero el núcleo en sí no debería ser requerido para acomodar la UI. (Si es necesario que suceda, generalmente es una indicación de que el núcleo no está diseñado para la propiedad).

Mi sistema de contabilidad tiene una estructura y contenido (y datos) que se supone que deben modelar el funcionamiento de mi empresa. Esa estructura es real y existe independientemente de qué software de contabilidad use. (Inevitablemente, un paquete de software dado contiene estructura y contenido por sí mismo, pero parte del desafío es minimizar esta sobrecarga).

Básicamente, una persona tiene un trabajo que hacer. El DDD debe coincidir con el flujo y el contenido del trabajo. DDD consiste en hacer explícitos todos los trabajos que deben realizarse de forma completa e independiente como sea posible. Entonces, la interfaz de usuario, con suerte, facilita el hacer el trabajo de la manera más transparente posible, de la manera más productiva posible.

Las interfaces son sobre las entradas y vistas proporcionadas para el núcleo funcional invariante y modelado adecuadamente.


Simplemente, la razón es la implementación y la deriva. Sí, su capa de presentación necesita conocer sus objetos comerciales para poder representarlos correctamente. Sí, inicialmente parece que hay mucha superposición entre la implementación de los dos tipos de objetos. El problema es que, a medida que pasa el tiempo, las cosas se agregan en ambos lados. Los cambios de presentación y las necesidades de la capa de presentación evolucionan para incluir elementos que son completamente independientes de la capa de su empresa (color, por ejemplo). Mientras tanto, los objetos de tu dominio cambian con el tiempo, y si no tienes un desacoplamiento adecuado de tu interfaz, corres el riesgo de arruinar tu capa de interfaz haciendo cambios aparentemente benignos en los objetos de tu negocio.

Personalmente, creo que la mejor manera de abordar las cosas es a través del paradigma de interfaz estrictamente impuesto; es decir, la capa de objeto de negocio expone una interfaz que es la única forma en que se puede comunicar; no se exponen detalles de implementación (es decir, objetos de dominio) sobre la interfaz. Sí, esto significa que debe implementar sus objetos de dominio en dos ubicaciones; su capa de interfaz y en su capa BO. Pero esa reimplementación, si bien inicialmente puede parecer un trabajo extra, ayuda a aplicar el desacoplamiento que ahorrará TONELADAS de trabajo en algún momento en el futuro.


Su presentación puede hacer referencia a su capa de dominio, pero no debe haber ningún enlace directo desde su interfaz de usuario a sus objetos de dominio. Los objetos de dominio no están destinados al uso de la IU, ya que a menudo, si se diseñan correctamente, se basan en comportamientos y no en representaciones de datos. Debería haber una capa de mapeo entre la UI y el Dominio. MVVM, o MVP, es un buen patrón para esto. Si intenta vincular directamente su interfaz de usuario al dominio, probablemente creará muchos dolores de cabeza. Ellos tienen dos propósitos diferentes.


Tal vez no esté conceptualizando la capa de interfaz de usuario en términos suficientemente amplios. Piense en términos de múltiples formas de respuesta (páginas web, respuesta de voz, cartas impresas, etc.) y en términos de múltiples idiomas (inglés, francés, etc.).

Supongamos ahora que el motor de voz para el sistema de llamada telefónica se ejecuta en un tipo de computadora completamente diferente (Mac, por ejemplo) de la computadora que ejecuta el sitio web (tal vez Windows).

Por supuesto, es fácil caer en la trampa "Bueno, en mi compañía solo nos importa el inglés, ejecutamos nuestro sitio web en LAMP (Linux, Apache, MySQL y PHP) y todos usan la misma versión de Firefox". Pero ¿qué pasa en 5 o 10 años?