domingo, 22 de febrero de 2009

DDD - Parte 1: Poniendo el Modelo de Dominio a Trabajar

En un post anterior, titulado El Dominio Es Lo Único Importante hice una pequeña introducción al libro Domain-Driven Design: Tackling Complexity in the Heart of Software (ISBN: 0-321-12521-5), donde Eric Evans expone conceptos tan fuertes como los de dominio, modelo de dominio y lenguaje ubicuo.

Evans asegura que, por lo general, los dominios de software no tienen casi relación con las computadoras, los lenguajes de programación o cualquier otro aspecto técnico. En la mayoría de los proyectos de software, la parte más crítica y compleja del desarrollo es comprender el dominio del negocio. Para representar un dominio, los especialistas en sistemas podemos usar lo que Evans llama Modelo de Dominio, que es una abstracción rigurosamente organizada y selectiva del conocimiento. Un Modelo de Dominio puse ser comunicado a través de un diagrama, un fragmento de código fuente (bien escrito, de forma trasparente y explícita) o una oración en español, inglés o el idioma que sea.

Masticando el Conocimiento

Evans propone que la construcción de un modelo de dominio es un proceso iterativo. El modelo debe irse construyendo de a poco entre el equipo de desarrollo y el experto de dominio, a través de:
  • Brainstorming y refinamiendo: DDD es una filosofía basada en las metodologías ágiles y, como éstas, propone que la conversación sea el medio de comunicación para compartir información de la forma más rápida y eficiente. Evans propone que, en lo posible, todo el equipo de desarrollo tenga acceso a los expertos de dominio, incluso los programadores, ya que son, en definitiva, los que van a poner el modelo de dominio a trabajar.
  • Un Modelo de Dominio borrador: En base a la conversación se puede ir construyendo un esbozo de lo que será el modelo de dominio. El experto irá corrigiendo lo que a él le parezca que no está correcto y desarrollador y experto llegarán a un acuerdo.
  • Un Diagrama de Clases temprano: Con este modelo de dominio borrador, podemos construir una versión early de un diagrama de clases.
  • Un Prototipo muy simple guiado por un framework de automatización de pruebas: Esto es, sentarse y, con el esbozo del diagrama de clases y el modelo de dominio, construir un prototipo bien simple del dominio. Evans aconseja evitar todo tipo de código de presentación o infraestructura. La idea es probar si el negocio fue bien modelizado, no si los objetos se persisten correctamente o si la aplicación se ve bien en determinado navegador. No queremos perder tiempo en ninguna otra cosa que no sea el dominio. Y si el prototipo es una ejecutable en consola, adelante.
  • Feedback del Prototipo: El experto de dominio interactuará con el prototipo, revisando si las reglas de negocio son correctas, si el sistema hace lo que debe hacer y, en base al feedback recibido, el equipo corregirá el modelo de dominio, lo mejorará y lo refinará. Así, volverá a corregir el prototipo y también el modelo de dominio.
Este proceso se repetirá hasta que el modelo, el diagrama y el prototipo sean correctos.


El modelo, el código y el diseño deben evolucionar juntos, de la mano, y de ninguna forma se debe permitir que se desincronicen. Cuando un concepto se actualice en el modelo, se deberá reflejar automáticamente en el código y en el diseño; y lo mismo al revés. El conocimiento es un proceso de aprendizaje continuo.

Pero entonces, ¿para qué están los analistas? ¿Por qué no dejar que el experto de dominio construya el modelo de su negocio y nosotros, los programadores, lo codifiquemos? La respuesta es simple: porque el experto de dominio casi nunca es conciente de la complejidad de sus procesos mentales en el día a día de su trabajo. El experto de dominio da por sabidas un montón de reglas, pasa por alto un montón de contradicciones y llena muchos baches con sentido común. El software no puede hacer eso. Por eso, una de las tareas más difíciles de un analista de sistemas es construir un modelo de dominio que refleje el negocio de la manera más fiel posible.

Un modelo es un sistema de abstracción que describe aspectos selectivos de un dominio y puede ser usado para solucionar problemas relacionados con ese dominio. Un modelo debe servir para un uso particular, por eso no es necesario (ni útil) que el modelo sea lo más realista posible (fiel no es lo mismo que realista). El modelo debe permitir al software ingresar en el dominio. Una porción de modelo que no se ve reflejada en el código fuente final es irrelevante y debe ser descartada.

En un modelo hay cuestiones de negocio y cuestiones de diseño (que conciernen pura y exclusivamente a la mantenibilidad y claridad del código). El uso de patrones de diseño, por ejemplo, es algo fundamental a la hora de construir un modelo saludable. La buena práctica de exponer de forma explícita las reglas de negocio es otra; exponerlas y aislarlas, para que sean fáciles de encontrar y modificar, en caso de que no sean correctas o hayan cambiado.

Masticar el conocimiento es un proceso lento, iterativo y de exploración, y uno nunca sabe cuándo puede terminar.

Comunicación y el Uso del Lenguaje

El modelo de dominio es la base de un lenguaje común para un projecto de software. A este lenguaje común, Domain-Driven Design lo llama lenguaje ubicuo.

El lenguaje ubicuo de un proyecto debe incluir:
  • Nombres de clases y sus operaciones destacadas (sobre todo las relacionadas estrechamente con el negocio)
  • Términos para discutir reglas de negocio que se han hecho explícitas en el modelo
  • Nombres de patrones de análisis y de diseño que se aplican al modelo de dominio
El lenguaje ubicuo debe ser utilizado por todas las personas involucradas en el proyecto, inclusive programadores y expertos de dominio. Los programadores deben poder describir en todo momento no sólo los artefactos del sistema, sino también las tareas y funcionalidades, en función del lenguaje (inclusive cuando se trata de una charla informal entre programadores).

El modelo de dominio es la columna vertebral del lenguaje ubicuo. El lenguaje debe ser usado en todas las conversaciones y artefactos que se construyan dentro del contexto del proyecto, incluyendo diagramas, documentos y, por supuesto, reuniones. Claro que el lenguaje ubicuo no es un artefacto que surje con una sola iteración. Construir un lenguaje común para todo el proyecto implica un proceso iterativo, de continuo refactoreo, en el que se deben mantener sincronizados modelo, lenguaje y código, ya que el código fuente también debe ser escrito respetando el lenguaje ubicuo. Si los programadores descubren, por ejemplo, que una clase de dominio debe llamarse de otra forma, no pueden refactorear el nombre de la clase sin refactorear también el nombre del concepto en el modelo de dominio y en el lenguaje ubicuo. Un cambio en el lenguaje ubicuo implica un cambio en el modelo y en el código; los tres artefactos deben evolucionar juntos, como un único bloque de conocimiento.


Una de las técnicas que según Evans ayuda mucho a la construcción de diagramas y de un modelo de dominio es la de modelar en voz alta. Evans sugiere que hablemos del modelo como si fuera del código, combinemos conceptos con las reglas permitidas por el modelo. Debemos encontrar una forma fácil de contar la historia del dominio y los nuevos términos e ideas reflejarlas en los diagramas y en el código.

Creo que una de las ideas más polémicas de DDD es ésta de que todo el equipo utilice el mismo lenguaje, incluido el experto de dominio. En general, la gente que viene del mundo técnico desecha esta idea, pensando que el experto de dominio en cierta forma es un chico, al cual hay que proteger mediante un escudo de ciertos conceptos que le resultarían demasiado abstractos o que no entenderían (por no comprender la teoría de la orientación a objetos). Estos analistas y/o desarrolladores tienen como principio recolectar los requerimientos en la terminología del entrevistado. Sin embargo, DDD obliga a olvidar este fundamento. DDD dice que si un experto de dominio no entiende el modelo, entonces hay algo mal con el modelo.

El experto de dominio debe usar el lenguaje ubicuo, el lenguaje del modelo, en los requerimientos, user stories y/o casos de uso. Así, conociendo y manejando la terminología podrá trabajar directamente con el modelo a través de los UAT o similares, sin intermediarios que funcionen como traductores.


El modelo de dominio puede contener diagramas, pero Evans sugiere que el modelo no sean diagramas. Esto significa que, los diagramas por sí solos no dicen nada. Es conveniente que haya más textos que diagramas (aunque los diagramas también son necesarios, y mucho). La mayoría de los diagramas utilizarán la notación UML (quizá en algunos casos convendrá relajar un poco la convención en favor de la claridad) y quizá algunos que otros diagramas explicativos, que no sigan ninguna convención establecida. Muchas veces un dibujo informal o un diagrama ad-hoc puede ayudar a los miembros del equipo a entender ciertos aspectos complicados del diagrama de clases o de otro diagrama o concepto del modelo.

Los diagramas no deben incluir demasiado detalle. Como nos recuerda Evans, nadie puede ver el bosque a través de los árboles. Para un exhaustivo nivel de detalle, tenemos el código, que si logramos que quede prolijo, claro, transparente y en función del lenguaje ubicuo, puede servir para soportar a la documentación. Los diagramas deben servir para enfocar la atención de las personas en los puntos centrales. No siempre UML es capaz de transmitir los dos aspectos más importantes de un modelo: el significado de los conceptos que se representan y el significado de lo que los objetos deben hacer. Por eso es importante no oscurecer la idea que se quiere transmitir con detalles de implementación. Por eso es importante mezclar los diagramas UML y los diagramas explicativos con texto. Evans dice que prefiere escribir los documentos con párrafos escritos, ilustrados con diagramas simples y selectivos. El modelo no es el diagrama.

En caso de utilizar una tecnología de alto nivel que permita generar ejecutables a partir de diagramas UML, entonces el UML es el lenguaje de programación. En este caso el UML es el código, el UML contiene todos o casi todos los detalles. El UML se ha convertido en el programa y el verdadero significado del modelo no se encuentra realmente ahí.

La documentación debe complementar el código y las conversaciones.

El mayor valor de un documento de diseño es explicar los conceptos del modelo, servir como guía de navegación a través de los detalles del código y quizá introducirnos en la filosofía, las convenciones y la forma de uso del modelo. Un documento debe estar implicado en las actividades del proyecto. Si el documento no tiene impacto en el lenguaje ubicuo, entonces algo en la metodología de trabajo está funcionando mal. Los documentos que quedan desactualizados y no tiene sentido perder tiempo para ponerlos al día, deben ser archivados como historial para que no creen confusión en el lenguaje y la filosofía del dominio y del proyecto. Mantenerlo en el mismo repositorio de los documentos actualizados, puede herir profundamente al lenguaje ubicuo, al modelo de dominio y al código; en resumen, al proyecto.

El lenguaje ubicuo permite que una especificación de requerimientos, por ejemplo, sea más concisa y menos ambigua. Lo ideal es usar al lenguaje ubicuo, y su evolución, como guía para decidir qué documentos se mantienen vivos en el proyecto y qué documentos deben archivarse en el historial.

Uniendo el Modelo y la Implementación

Todo programador sabe que un modelo funcional no puede servir como guía de implementación. Todo aquel que se haya sentado al menos una vez a escribir código sabe que, como cualquier dominio, el dominio de los lenguajes de máquina también tiene sus baches que llenar, sus contradicciones, sus caminos sinuosos, sus trucos, en resumen: sus detalles técnicos. Bajo ningún modo podemos pretender que un modelo de dominio funcional sirva como guía para que los programadores escriban el código.

DDD, como muchas otras metodologías ágiles, no apoya la distinción marcada de roles dentro del equipo de trabajo de un proyecto. Sin bien se necesitan las funciones de analistas, diseñadores, desarrolladores, testers, líderes, Evans cree en un equipo multidisciplinario, en el que cualquiera puede cumplir cualquier tarea en cualquier momento. Las personas que van a meter mano en el código (llamémoslos programadores, desarrolladores, técnicos o lo que sea) tienen que tener contacto con el experto de dominio y deben participar en las reuniones donde se define el modelo de dominio y se discute acerca de las reglas de negocio y de las palabras que deben o no ir en el lenguaje ubicuo. En otras palabras: Evans no cree en una estructura jerárquica dentro del proyecto, sino en miembros de un mismo equipo, que comparten las mismas funciones, el mismo lenguaje y, lo más importante, los mismos objetivos.

Muchos proyectos se ven afectados por una falta de conexión entre el modelo y el código. Esto suele suceder por una separación marcada, a veces artificial, entre análisis y diseño. Los analistas construyen un modelo de análisis sin contemplar aspectos de diseño, para que el modelo sirva sólo para fines de entendimiento del negocio. Pero, si los desarrolladores encuentran que para implementar cierta funcionalidad, deben cambiar o ignorar ciertos aspectos del modelo, que francamente no se adaptan a la tecnología, y si para colmo a eso le sumamos que los programadores no tengan acceso al experto de dominio para hacerle preguntas, el equipo de desarrollo se verá obligado a no contemplar el modelo, implementar de la forma que a ellos les parece y así, al poco tiempo, el modelo de dominio quedará tan desactualizado que no servirá para nada, el código no responderá a las exigencias del usuario y el proyecto terminará en los atrasos, presiones, tensiones y fracasos habituales.

El modelo es una proyección del dominio. Una proyección de Domain-Driven Design en un proyecto sería Model-Driven Design. Model-Driven Design descarta la dicotomía entre el análisis y el diseño en favor de un modelo único que sirva para los dos propósitos. Este enfoque demanda un modelo que funcione correctamente tanto para el análisis como para el diseño. Cuando el modelo no muestra ser práctico para la implementación, se debe refactorear hasta conseguir uno nuevo; cuando un modelo no muestra ser práctico para expresar los conceptos claves del dominio, se debe refactrorear hasta conseguir uno nuevo. Esto acarrea un modelo más difícil de crear, un análisis y un diseño más difíciles de construir (nadie dijo que DDD es fácil; nadie dijo que desarrollar software fuera fácil), pero como recompensa tendremos un modelo relevante y ejecutable a la vez, un modelo que podremos poner a trabajar.

Así, DDD ha convertido el desarrollo de software en un proceso iterativo de refinamiento del modelo, refinamiento del diseño y refinamiento del código, como una sola actividad indivisible.


Para asegurarnos de mantener esta dependencia entre modelo y diseño lo más fuerte posible, es importante trabajar sobre un paradigma que nos ayude con este trabajo. El paradigma de los lenguajes imperativos estructurados, por ejemplo, no ayuda para nada. Podemos hacer un modelo de dominio muy limitado con un lenguaje del estilo C, ya que la condición de mantener la sincronía con el código es demasiado restrictiva. Un lenguaje procedural no está para nada alineado con el paradigma del modelado. En cambio, el paradigma de la orientación a objetos (Java podría ser un ejemplo) o el paradigma lógico (al estilo Prolog, donde un programa es un conjunto de reglas lógicas y hechos que operan sobre esas reglas), encaja perfecto en la filosofía de Model-Driven Design.

El desarrollo de software es todo diseño. La diferenciación de roles entre los miembros de un equipo, la separación entre análisis, diseño y programación interfiere directamente con la filosofía de DDD. Si las personas que escriben el código no se sienten responsables por el modelo, o no entienden cómo el modelo puede funcionar en una aplicación, entonces el modelo no sirve para nada. Si los desarrolladores no mantienen sincronizados el modelo y el lenguaje con el código, el modelo deja de servir. Con Model-Driven Design, una porción del código es una expresión del modelo, así como una porción del modelo es una expresión del dominio con DDD. Los programadores son modeladores. Cada programador debe estar involucrado en las discusiones sobre el modelo y debe tener contacto con el experto de dominio, y conocer, manejar y actualizar el lenguaje ubicuo.

Eric Evans asegura que el resultado de esta rigurosa práctica, tan fácil de evangelizar pero tan difícil de implementar, es un sistema con funcionalidades ricas, correctas y exactas basadas en un entendimiento profundo del dominio.

Links Relevantes: