
Serie DDD: introducción
Posts en esta serie:
-
Introducción
Domain Driven Design (diseño dirigido por el dominio) o DDD es una filosofía de desarrollo de software creada por Eric Evans en su libro Domain-Driven Design: Tackling Complexity in the Heart of Software (también conocido como el "blue book").
Permite a los equipos manejar de forma efectiva la construcción y mantenimiento de software para dominios de problema complejos.
La forma de arquitectura más común por lejos en aplicaciones de negocio es la Big Ball of Mud (BBoM) o Gran bola de lodo. Este tipo de arquitectura se define como una jungla de código spaghetti, estructurada al azar, descuidada, unida con cinta adhesiva y alambre.
Crédito: Imagen de GarryKillian en Freepik
Una de las principales razones que llevan a caer en este tipo de arquitectura es que se mezclan las complejidades propias del dominio (la complejidad esencial) con las complejidades técnicas (la complejidad accidental).
Los proyectos de software suelen fallar cuando no se entiende suficientemente bien el dominio de negocio en el cual se está trabajando.
Sacando los requerimientos no-funcionales (performance, seguridad, etc.) la parte difícil es el modelado de un dominio que pueda cumplir con los casos de uso del negocio.
Domain Driven Design hace que los programadores y los expertos de negocio trabajen en conjunto para construir el software.
Además, DDD le permite al negocio aprender más sobre sí mismo. Ningún experto de negocio suele conocer todo acerca del mismo. Con DDD todos aprenden porque genera un proceso continuo de descubrimiento.
El conocimiento se centraliza y todos tienen acceso al mismo, no hay conocimiento parcial que solo tengan los programadores o que esté aislado en cada departamento o grupos de la empresa.
No existen traducciones de términos entre los expertos de negocio, los programadores y el software. Se construye un lenguaje compartido que todos hablan.
DDD nos provee patrones para entender correctamente el dominio y poder construir una solución de software que es útil para resolver problemas dentro del mismo.
Los patrones de DDD se clasifican principalmente en dos grupos:
- Estratégicos: Nos permiten descomponer el dominio y darle forma a la arquitectura.
- Tácticos: Son los elementos que nos permiten crear un modelo efectivo para dominios complejos. Muchos de estos patrones ya existían previamente en la comunidad y en libros como Design Patterns: Elements of Reusable Object-Oriented Software (conocido como el GoF) y Patterns of Enterprise Application Architecture.
Destilar el dominio del problema
El dominio es lo que hace una organización y el mundo en el cual lo hace.
Cada organización tiene su propio know-how y su forma de hacer las cosas. Ese conocimiento y sus métodos particulares para llevar a cabo sus operaciones es lo que conocemos como el dominio del problema.
Es importante destilar este dominio para poder determinar qué es importante y qué no. Cuando tenemos un software grande no todo tiene que estar diseñado de forma perfecta, es una pérdida de tiempo y de costos.
Los equipos de desarrollo y los expertos de negocio destilan en conjunto dominios grandes y complejos y los descomponen en subdominios más pequeños y manejables.
Por ejemplo, una empresa que vende productos online podría identificar los siguientes subdominios:
- Catálogo de productos
- Órdenes de compra
- Facturación
- Cobranza
- Delivery de los productos
- Inventario y gestión de stock
- Soporte

Para poder descubrir y entender el dominio entero se suelen organizar workshops y utilizar prácticas como ser:
- Event Storming
- Impact Mapping
- Business Model Canvas
- Descubrimiento Deliberado
- Model Exploration Whirlpool
Un negocio contiene una gran cantidad de información, no toda sirve para resolver los problemas que se quieren resolver. Se necesita destilar esta información para poder construir un modelo que sea efectivo para resolver los casos de uso del negocio. A esta actividad se la conoce como Knowledge Crunching.
Crédito: Robert Laszczak
Descomponer el dominio de problema
Como dijimos, la destilación nos revela que el dominio está compuesto por distintos subdominios. No todos son igualmente importantes para el negocio. Todos son esenciales para que el sistema entero funcione pero algunos son más valiosos que otros.
No se debe poner el mismo esfuerzo y calidad en todo el sistema. Esto nos va a llevar a perder el foco de aquellas áreas donde es esencial que un negocio se focalice.
Podemos identificar tres tipos de subdominios.
Subdominios core
Estos subdominios son los más importantes. Son la razón por la cual estamos construyendo un software en vez de comprarlo.
Los subdominios core le dan al negocio la principal ventaja competitiva. Es donde el negocio debe sobresalir.
¿Qué hace a nuestro sistema de e-commerce distinto de la competencia? Quizás tenemos un sistema de delivery muy eficiente que entrega los productos en el día o quizás los reviews de usuarios de los productos.
En este tipo de subdominios debemos poner el mayor esfuerzo y los mejores programadores.
Subdominios genéricos
Son subdominios que suelen estar presentes en varios negocios y sistemas. Por ejemplo un servicio de envío de emails, de reportes, de facturación, etc.
Estos subdominios no tienen ninguna especialización sino que son problemas comunes de varias empresas.
Si bien no son centrales (no son core), son necesarios para el funcionamiento de la empresa.
No tiene mucho sentido invertir mucho esfuerzo en estos subdominios porque no nos van a dar una ventaja competitiva. Podemos buscar comprar software o desarrollar soluciones con menos foco y con programadores juniors.
Subdominios de soporte (Supporting)
Estos subdominios no son core pero tampoco son soluciones genéricas. Son problemas donde la empresa tiene alguna especialización que la distingue de otras empresas.
Por ejemplo puede ser que el control de inventario no sea algo central pero tiene muchas particularidades respecto a cómo lo hacen otras empresas.
En este tipo de subdominios tampoco conviene invertir mucho esfuerzo. Conviene buscar soluciones que se puedan customizar.
A veces se pueden resolver sin necesidad de hacer un desarrollo de software sino con procesos manuales (liberando a los programadores para trabajar en los subdominios core).

Crear modelos efectivos
Para acercarnos a resolver los problemas con software vamos a enfocarnos primero en los modelos que debemos crear. Modelos que representaremos luego en software.
En vez de hacer un gran modelo de nuestro dominio de problema (lo cual nos llevaría a tener un modelo muy complejo), hacemos un modelo por cada subdominio.
Un modelo es una abstracción que creamos con el fin de poder satisfacer los requerimientos del negocio.Para evitar la complejidad accidental (la complejidad técnica) aislamos los modelos de los aspectos técnicos y de infraestructura.
No todos los modelos se crean igual. Se eligen los patrones de diseño más apropiados de acuerdo a la complejidad y las necesidades de cada subdominio. Los modelos genéricos o de soporte pueden no necesitar un diseño rico orientado a objetos y pueden tener arquitecturas más procedurales u orientadas a datos.
Un error común es buscar que los modelos se correspondan con la realidad. Un modelo es una abstracción útil diseñada para nuestro contexto particular. Un mapa geográfico y uno político son dos modelos con fines totalmente distintos. Y son abstracciones, no son la realidad del terreno.
Un modelo debe incluir aspectos que ayuden a resolver problemas de negocio y debe evitar detalles irrelevantes.

Si vemos el mapa de subtes de Londres este modelo está diseñado para mostrar las estaciones y las combinaciones. Pero este modelo no incluye las distancias reales. Su utilidad es para que podamos saber qué subte tomamos y poder llegar a destino, no para entender a nivel geográfico la exactitud de cuán lejos está una estación de otra.
Resumiendo entonces:
- Los negocios suelen ser grandes y complejos, no hay que intentar modelar todo.
- Los modelos deben ser abstracciones útiles y deben ser refinados constantemente.
- No hay que modelar todas las relaciones que existen entre los conceptos de la vida real.
Otra cuestión con la que debemos tener cuidado es el uso de las abstracciones. Cuando modelamos los conceptos en objetos seguramente vamos a diseñar objetos más concretos y objetos más abstractos.
Hay que tener cuidado con el uso de las abstracciones, siempre tienen un precio y por ende deben limitarse.
Es mejor ser explícito y repetirse que intentar juntar conceptos levemente relacionados u ocultar un concepto de negocio importante bajo capas de abstracciones.

Lenguaje ubicuo
El verdadero valor de DDD está en la colaboración entre los desarrolladores y los expertos de negocio para producir un mejor entendimiento del negocio.Para llegar a un buen entendimiento se deben poder comunicar de forma efectiva. Esto se logra creando un lenguaje compartido donde todos hablan utilizando los mismos términos sin necesidad de traducciones. Este lenguaje se denomina lenguaje ubicuo.
La creación de un lenguaje ubicuo permite a los equipos organizar el modelo mental y el modelo del código fácilmente. Da claridad y consistencia.
Este lenguaje debe utilizar los conceptos de negocio y se expresa en todos lados: conversaciones, diagramas, documentación y en el código fuente.
Por la rigurosidad que se requiere al momento de programar muchas veces se descubren nuevos conceptos que deben incorporarse al lenguaje ubicuo. Estos conceptos se discuten en conjunto con la gente de negocio y se acuerdan nuevas definiciones para desambiguar. Un lenguaje ubicuo está en constante evolución, se van refinando términos e incorporando nuevos.
Este aspecto de DDD es clave para que los desarrolladores y los expertos de negocio puedan crear y evolucionar el modelo en colaboración.
El código expresando el modelo en este lenguaje le permite a cualquier persona poder entender con claridad los procesos de negocio, los conceptos y cómo se relacionan entre sí. Si por ejemplo estamos haciendo un software de contabilidad, cualquier persona que lea el código fuente aprendería de contabilidad.
Próximo post
Hablamos en este post sobre la importancia de poder entender el dominio de problema y descomponerlo en subdominios menos complejos. Hablamos sobre cómo categorizar estos subdominios para poder entender dónde conviene poner el foco, vimos que por cada uno vamos a construir un modelo (que luego representaremos en software) y la importancia de que este modelo esté expresado en un lenguaje ubicuo que desarrolladores y expertos de negocio puedan evolucionar en conjunto.
En el próximo post de esta serie vamos a hablar sobre cómo proteger la integridad de estos modelos para que no se contaminen entre sí (algo que inevitablemente llevaría a incrementar la complejidad nuevamente). Vamos a introducir el concepto de Bounded Contexts.