Diseño guiado por el dominio

Una aplicación puede estar perfectamente programada y, sin embargo, representar mal el negocio para el que fue construida. Puede tener una arquitectura ordenada, pruebas automatizadas, una base de datos bien diseñada y un código limpio, pero utilizar conceptos que no coinciden con la realidad que sus usuarios necesitan gestionar. Cuando esto ocurre, el problema no suele encontrarse en una función concreta, sino en algo más profundo: el software y el negocio están utilizando modelos mentales diferentes para describir la misma realidad.

Esta tensión es especialmente visible en sistemas empresariales. Una aplicación para gestionar estudios clínicos, por ejemplo, puede hablar de centros, promotores, estudios, contratos o intermediaciones. Pero que esas palabras aparezcan en las tablas de una base de datos o en las clases de una aplicación no significa necesariamente que el sistema haya comprendido qué representan. ¿Qué hace que algo sea realmente un centro? ¿Puede cambiar su identidad? ¿Qué información forma parte del centro y cuál pertenece a una relación concreta con un estudio? ¿Quién puede modificarla? ¿Qué reglas deben cumplirse cuando cambia su estado?

El diseño guiado por el dominio, conocido habitualmente como Domain-Driven Design o DDD, parte precisamente de esta preocupación. Su propuesta fundamental no consiste en utilizar determinadas clases, patrones o estructuras de carpetas, sino en hacer que el diseño del software nazca de una comprensión profunda del dominio empresarial que el sistema intenta representar.

Del código al problema que queremos resolver

Cuando comenzamos un proyecto de software es tentador empezar pensando en tecnología. ¿Qué lenguaje utilizaremos? ¿Qué framework? ¿Qué base de datos? ¿Será una API REST? ¿Utilizaremos microservicios? Son preguntas legítimas, pero existe una pregunta anterior que puede resultar mucho más importante: ¿cómo funciona realmente el negocio?

Imaginemos una empresa que necesita gestionar la relación entre estudios clínicos y centros en los que se realizan determinadas actividades. Desde una perspectiva puramente técnica podríamos empezar diseñando tablas llamadas Study, Center y Contract, crear algunas relaciones entre ellas y posteriormente construir una API.

El problema es que crear estructuras de software a partir de nombres del negocio no significa necesariamente que hayamos modelado el negocio. El verdadero trabajo comienza cuando intentamos comprender qué significan esos conceptos, qué reglas los relacionan y qué comportamientos debe preservar el sistema.

Por ejemplo, un centro puede estar activo o inactivo. Un centro puede participar en determinados estudios, pero no necesariamente en todos. Una relación entre un centro y un estudio puede tener su propio estado y unas fechas determinadas. Un contrato puede condicionar qué operaciones son posibles. El significado de cada concepto aparece cuando empezamos a comprender las reglas que lo rodean.

DDD propone precisamente dedicar una atención especial a esa comprensión. El software deja de ser una traducción directa de tablas o pantallas y pasa a convertirse en una representación explícita de los conceptos y reglas importantes del negocio.

Un lenguaje común para entender el dominio

Para poder construir ese modelo necesitamos primero hablar sobre el problema. Y aquí aparece una de las ideas más importantes de DDD: el lenguaje ubicuo (ubiquitous language).

En cualquier organización existen palabras que tienen un significado concreto para las personas que trabajan en ella. El problema aparece cuando los desarrolladores utilizan unas palabras, los responsables de negocio otras y el sistema termina utilizando una tercera interpretación.

Si un usuario habla de una “intermediación”, por ejemplo, no deberíamos asumir que sabemos exactamente qué significa. Tendríamos que descubrir qué representa, cuándo comienza, cuándo termina, qué estados puede tener y qué condiciones determinan que una intermediación sea válida.

El lenguaje utilizado por el negocio debería convertirse progresivamente en parte del lenguaje utilizado para diseñar y construir el software.

Esto tiene una consecuencia práctica importante. Si durante una conversación con los expertos del dominio aparece una palabra que describe algo importante, esa palabra puede terminar apareciendo en el código. Una clase, un método o una operación pueden utilizar el mismo concepto que utilizan los usuarios.

No se trata de introducir términos empresariales en el código de forma artificial. Se trata de evitar que el código tenga que traducir constantemente entre dos modelos diferentes de la realidad.

El dominio no es necesariamente uno solo

A medida que profundizamos en un negocio aparece otro problema. Una misma palabra puede significar cosas diferentes dependiendo del contexto en el que se utilice.

Pensemos, por ejemplo, en una empresa que trabaja con clientes. Para el departamento comercial, un cliente puede ser una organización con determinados datos fiscales y comerciales. Para facturación, ese mismo cliente puede tener condiciones de pago, facturas y saldos. Para soporte, puede representar una cuenta con incidencias, contactos y acuerdos de servicio.

Todos están hablando de un “cliente”, pero no necesariamente están hablando del mismo concepto.

Aquí aparece el concepto de contexto delimitado, o bounded context. Un contexto delimitado establece el límite dentro del cual un determinado modelo del dominio tiene un significado coherente.

Esto significa que no siempre debemos intentar construir un único modelo empresarial universal que represente toda la organización. Puede ser más útil reconocer que diferentes partes del negocio necesitan modelos diferentes.

Un cliente en el contexto comercial puede no tener exactamente las mismas propiedades, reglas o responsabilidades que un cliente en el contexto de facturación. Aunque ambos conceptos puedan estar relacionados, cada contexto puede tener su propio modelo y su propio lenguaje.

Esta idea resulta especialmente importante cuando los sistemas crecen. DDD no intenta eliminar la complejidad del negocio haciendo que todo comparta el mismo modelo, sino controlar esa complejidad estableciendo límites dentro de los cuales cada modelo puede mantenerse coherente.

Modelar significa decidir qué importa

Una vez delimitado un contexto podemos empezar a construir un modelo. Pero modelar no significa intentar representar absolutamente todo lo que existe en el mundo real.

Un modelo es una simplificación. Selecciona determinados aspectos de la realidad porque son relevantes para el problema que queremos resolver.

Si estamos construyendo un sistema para gestionar centros de estudios clínicos, probablemente no necesitemos representar todo lo que sabemos sobre un centro. Quizá nos interesen su identificador, nombre, ubicación, estado y determinadas capacidades. En otro sistema podrían ser relevantes otros aspectos completamente diferentes.

El modelo de dominio no pretende ser una copia completa de la realidad, sino una representación de aquella parte de la realidad que importa para el problema que estamos resolviendo.

Esta distinción ayuda a entender por qué DDD no consiste simplemente en convertir cada sustantivo del negocio en una clase. Una clase Center no constituye por sí misma un modelo de dominio. El modelo aparece cuando esa estructura expresa conceptos, relaciones, comportamientos y reglas que realmente tienen significado dentro del negocio.

Entidades: objetos cuya identidad importa

Algunos conceptos del dominio necesitan mantener una identidad a lo largo del tiempo. Para ellos DDD utiliza el concepto de entidad.

Imaginemos un centro identificado por C123. Podemos modificar su nombre, dirección o estado, pero seguimos hablando del mismo centro. Sus atributos han cambiado; su identidad permanece.

Esto es lo que diferencia a una entidad de un simple conjunto de datos. Una entidad se reconoce principalmente por quién es, no únicamente por los valores que contiene en un momento determinado.

Esta característica tiene consecuencias en el diseño. Si cambiamos el nombre de un centro, no queremos que el sistema interprete que hemos eliminado un centro y creado otro. La identidad permite comprender que se trata del mismo elemento del dominio a lo largo de su ciclo de vida.

Las entidades, además, suelen tener comportamiento. Si un centro no puede pasar directamente de “inactivo” a determinados estados sin cumplir ciertas condiciones, esa regla pertenece al dominio y puede formar parte del comportamiento de la entidad o de otros elementos del modelo.

La cuestión importante es evitar convertir una entidad en una simple estructura de datos con getters y setters. Una entidad de dominio resulta valiosa cuando ayuda a proteger las reglas que determinan qué estados y comportamientos son válidos.

Objetos de valor: cuando importa el significado, no la identidad

No todo concepto necesita una identidad propia. Hay valores cuyo significado depende exclusivamente de sus propiedades.

Pensemos en una dirección, una cantidad monetaria o un intervalo de fechas. Si dos direcciones contienen exactamente los mismos datos relevantes, normalmente no necesitamos distinguirlas porque sean “la misma dirección” con un identificador independiente.

Estos conceptos pueden representarse mediante objetos de valor, o value objects.

Un objeto de valor se define por los valores que contiene y no por una identidad propia. Una dirección podría estar formada por calle, número, código postal y ciudad. Una cantidad monetaria podría combinar importe y moneda.

Esta distinción parece sencilla, pero puede cambiar considerablemente la calidad de un modelo. En lugar de trabajar con cadenas y números sin significado, podemos representar explícitamente conceptos del dominio.

Por ejemplo, una propiedad llamada PostalCode como simple string permite almacenar cualquier texto. Un objeto de valor CodigoPostal puede encapsular las reglas que determinan qué constituye un código postal válido.

Los objetos de valor permiten que conceptos aparentemente simples adquieran significado dentro del modelo y concentren las reglas que les corresponden.

Además, suelen ser inmutables: en lugar de modificar internamente un objeto de valor, se crea otro que representa el nuevo valor. Esta característica facilita razonar sobre ellos y reduce determinados problemas derivados de compartir estados mutables.

Agregados: establecer límites de consistencia

A medida que nuestro modelo crece aparece una nueva pregunta: si tenemos muchas entidades relacionadas, ¿debemos tratarlas todas como una única unidad?

Supongamos que un estudio tiene varios centros asociados y que cada relación entre estudio y centro posee información y reglas propias. Podríamos crear un modelo en el que todas las entidades estén directamente conectadas entre sí. Pero cuanto más grande sea esa red, más difícil será determinar qué podemos modificar conjuntamente y qué reglas deben cumplirse en cada operación.

Aquí aparece el concepto de agregado, uno de los elementos más importantes del diseño táctico de DDD.

Un agregado es un conjunto de objetos del dominio que se trata como una unidad a efectos de determinadas reglas de consistencia. Dentro de él existe una raíz del agregado (aggregate root) que actúa como punto de entrada para acceder a los elementos que forman parte de esa unidad.

La idea fundamental no es simplemente agrupar clases. Un agregado establece un límite dentro del cual determinadas invariantes del negocio deben mantenerse consistentes.

Imaginemos que un Estudio es la raíz de un agregado que contiene determinada información que debe mantenerse coherente con sus relaciones internas. En lugar de permitir que cualquier parte del sistema modifique directamente cualquiera de sus objetos internos, las operaciones pasan por la raíz del agregado, que puede comprobar las reglas correspondientes.

Esto también ayuda a limitar las transacciones y el acoplamiento. No todo el modelo tiene que cargarse y modificarse como una única estructura gigante.

Un error habitual consiste en interpretar los agregados como simples agrupaciones jerárquicas. Si una entidad contiene otras entidades, eso no significa automáticamente que todas formen un agregado. El límite del agregado debería surgir de las reglas de consistencia que el negocio necesita proteger, no de cómo nos resulte cómodo organizar las clases.

Los intermediarios: coordinar sin convertir todo en una entidad

No todas las operaciones del dominio encajan naturalmente dentro de una entidad o de un objeto de valor.

Imaginemos una operación que necesita coordinar varios conceptos del dominio pero que no representa una propiedad o comportamiento natural de una entidad concreta. Si intentamos introducirla dentro de una entidad únicamente para tener un lugar donde colocarla, podemos terminar creando objetos con responsabilidades que realmente no les pertenecen.

Aquí aparecen los servicios de dominio (domain services), que podemos entender como intermediarios que encapsulan una operación o regla del dominio cuando su responsabilidad no pertenece naturalmente a una única entidad u objeto de valor.

Por ejemplo, podríamos tener una regla que determina si un centro puede ser asociado a un determinado estudio teniendo en cuenta información procedente de varios conceptos. Esa operación podría no pertenecer naturalmente ni al centro ni al estudio.

Un servicio de dominio permite expresar esa regla sin atribuírsela artificialmente a uno de los objetos.

Esto no significa que cualquier lógica de negocio deba convertirse en un servicio. Si una regla pertenece claramente a una entidad, normalmente resulta más coherente mantenerla dentro de ella.

Los servicios de dominio deberían utilizarse cuando existe una operación significativa para el dominio que no encaja naturalmente dentro de una única entidad o un objeto de valor.

La misma idea de intermediación aparece también en otras partes de una arquitectura. Los servicios de aplicación pueden coordinar casos de uso, los repositorios pueden mediar entre el dominio y la persistencia y otros componentes pueden conectar el modelo con sistemas externos. Pero sus responsabilidades no son intercambiables: uno de los objetivos de DDD es mantener claras las fronteras entre el dominio y los mecanismos que lo rodean.

Un ejemplo completo: desde una necesidad de negocio hasta el modelo

Podemos reunir ahora todas estas ideas en un ejemplo completo. Imaginemos una empresa que gestiona estudios clínicos y necesita una aplicación para coordinar qué centros participan en cada estudio. El objetivo inicial parece sencillo: registrar estudios, registrar centros y permitir que un usuario establezca una relación entre ambos. Si empezáramos directamente por la base de datos, probablemente acabaríamos rápidamente con tablas como Study, Center y StudyCenter, pero todavía no sabríamos si esas estructuras representan realmente las reglas del negocio.

El primer paso sería hablar con las personas que conocen el proceso. Durante esas conversaciones descubrimos que un estudio tiene un ciclo de vida, que un centro puede estar activo o inactivo y que un centro no puede participar en un estudio si no cumple determinadas condiciones. También descubrimos que la relación entre estudio y centro no es una simple relación técnica: representa una intermediación, tiene su propio estado, puede comenzar en una fecha determinada y puede finalizar por diferentes motivos. Ya no estamos simplemente recopilando nombres para crear tablas; estamos descubriendo el lenguaje y las reglas del dominio.

A partir de esas conversaciones podemos comenzar a construir un lenguaje común. Decidimos que utilizaremos términos como Estudio, Centro, Intermediación y Estado de la intermediación tanto en las conversaciones como en el diseño del software. Si aparece una palabra ambigua, no la convertimos automáticamente en una clase: primero preguntamos qué significa, quién utiliza ese concepto y qué reglas lo acompañan. De esta forma, el lenguaje empieza a convertirse en una herramienta para descubrir el modelo y no simplemente en una lista de nombres que después trasladaremos al código.

A continuación analizamos los contextos en los que aparecen esos conceptos. El área encargada de gestionar estudios necesita saber qué estudios existen, su estado y qué centros participan en ellos. Sin embargo, otro contexto de la organización puede gestionar la información maestra de los centros, donde un centro representa una organización con identidad, dirección, estado y otros datos generales. El mismo centro puede ser utilizado por ambos contextos sin que eso obligue a que ambos tengan exactamente el mismo modelo de centro. En el contexto de estudios nos interesa aquello que necesitamos para gestionar la participación; en el contexto de datos maestros puede interesarnos la identidad y administración general del centro.

Dentro del contexto de gestión de estudios podemos entonces empezar a decidir qué conceptos necesitan identidad. Un Estudio tiene claramente una identidad: aunque cambien su nombre o determinadas propiedades, sigue siendo el mismo estudio. La Intermediación también necesita identidad porque representa una relación concreta que tiene un ciclo de vida propio. Un Centro puede ser identificado mediante un CenterId, aunque en este contexto no necesariamente seamos responsables de toda su información.

También encontramos conceptos que no necesitan identidad propia. El estado de una intermediación puede representarse como un concepto explícito, pero otros valores como un intervalo de fechas o determinados datos de configuración pueden modelarse como objetos de valor. Por ejemplo, podríamos representar el periodo de participación mediante un PeriodoParticipacion formado por FechaInicio y FechaFin, encapsulando la regla de que la fecha final no puede ser anterior a la inicial. La ventaja no está en crear una clase por cada par de propiedades, sino en convertir en conceptos explícitos aquellos valores que tienen significado y reglas propias.

Después debemos decidir dónde colocar las reglas. Supongamos que una intermediación solo puede pasar de Propuesta a Aceptada si el centro está habilitado y el estudio se encuentra en un estado que permite incorporar nuevos centros. No tendría demasiado sentido permitir que cualquier controlador o servicio de aplicación cambie directamente el estado de la intermediación. La operación debería pasar por el modelo de dominio para que las reglas que determinan una transición válida queden protegidas.

Podríamos tener entonces una entidad Intermediacion con operaciones como Aceptar() o Cancelar(). La propia entidad puede comprobar las reglas que dependen de su estado y de la información que le pertenece. Si para determinar si puede aceptarse necesita coordinar información que no pertenece naturalmente a la entidad, podemos utilizar un servicio de dominio, por ejemplo ValidadorDeIntermediacion, que reúna esa regla sin convertir a Intermediacion en responsable de todo el dominio.

Ahora aparece la cuestión de los agregados. Supongamos que una Intermediacion debe mantener internamente consistente su estado, sus fechas y determinada información propia. Podemos decidir que Intermediacion sea la raíz de un agregado. El resto del sistema no modificaría directamente sus propiedades internas, sino que utilizaría operaciones de la raíz para ejecutar acciones significativas como aceptar, rechazar o cancelar la intermediación.

El agregado no tendría por qué contener todo el estudio, todos sus centros ni toda la información relacionada. Precisamente una de sus funciones es establecer hasta dónde necesitamos consistencia inmediata. Si modificar una intermediación no requiere cargar y modificar simultáneamente todo el estudio, no tendría sentido convertir el estudio y todas sus intermediaciones en una única estructura transaccional gigantesca.

Con el modelo definido podemos pasar a la aplicación. Imaginemos que un usuario pulsa el botón “Aceptar intermediación”. La interfaz envía una solicitud a la aplicación. La capa de aplicación recupera la Intermediacion, obtiene la información necesaria para ejecutar la operación y solicita al dominio que realice la aceptación. El dominio comprueba las reglas correspondientes y, si son válidas, cambia el estado. Finalmente, la aplicación persiste el agregado y devuelve el resultado al usuario.

El flujo conceptual podría representarse así:

Usuario
Aplicación de gestión de estudios
   │  "Aceptar intermediación"
Servicio de aplicación
Intermediación
   ├── comprueba su estado
   ├── valida sus reglas
   └── cambia a "Aceptada"
Repositorio de Intermediaciones
Base de datos

Pero el proceso no termina necesariamente ahí. Supongamos que, cuando una intermediación es aceptada, otro sistema necesita saberlo para continuar el proceso. En lugar de introducir directamente esa responsabilidad dentro de la entidad, podemos hacer que la aplicación publique un evento como IntermediacionAceptada. Otro componente puede reaccionar ante ese hecho sin que el modelo de dominio tenga que conocer quién lo consumirá.

El resultado final es muy diferente de nuestro diseño inicial basado simplemente en tres tablas. Hemos pasado de una estructura técnica formada por Study, Center y StudyCenter a un modelo en el que existen conceptos con significado propio, reglas explícitas, límites de consistencia y responsabilidades diferenciadas. El código no se ha limitado a almacenar información sobre el negocio: está expresando decisiones sobre cómo funciona el negocio.

Y, sobre todo, el ejemplo muestra que DDD no consiste en aplicar todos sus patrones desde el principio. Primero descubrimos el lenguaje, después delimitamos el contexto, posteriormente identificamos los conceptos y sus reglas y finalmente decidimos qué entidades, objetos de valor, agregados y servicios necesitamos. El modelo surge del problema y de las reglas del dominio; las estructuras técnicas se deciden después para dar soporte a ese modelo.

Cómo encajan todas las piezas

Llegados a este punto podemos ver que los conceptos de DDD no son una colección independiente de patrones.

Primero intentamos comprender el negocio y construir un lenguaje común. Después descubrimos que ese lenguaje puede tener diferentes significados según el contexto y establecemos contextos delimitados. Dentro de cada contexto construimos un modelo que representa los conceptos relevantes.

Algunos de esos conceptos necesitan identidad y se convierten en entidades. Otros se definen únicamente por sus valores y pueden representarse como objetos de valor. Cuando varias entidades y objetos necesitan formar una unidad coherente de consistencia, establecemos un agregado. Y cuando una operación de dominio no pertenece naturalmente a una entidad concreta, podemos expresarla mediante un servicio de dominio.

La verdadera fuerza de estos conceptos aparece cuando se utilizan conjuntamente para construir un modelo coherente del negocio, no cuando se aplican como una colección de patrones de programación.

Podemos imaginarlo como diferentes niveles de decisión. El contexto delimitado establece dónde tiene sentido nuestro modelo. Las entidades y objetos de valor representan los conceptos que contiene. Los agregados determinan determinadas fronteras de consistencia. Los servicios permiten expresar operaciones que atraviesan varios conceptos cuando no pertenecen naturalmente a uno solo.

El resultado debería ser un software en el que leer el código permita reconocer, al menos parcialmente, cómo funciona el negocio.

DDD no significa crear muchas clases

Existe una tentación cuando se descubre DDD: transformar inmediatamente cada concepto empresarial en una clase, añadir entidades, objetos de valor, agregados y servicios, y considerar que ya estamos aplicando diseño guiado por dominio.

Pero eso puede producir exactamente el problema contrario al que DDD intenta solucionar. Podemos terminar con un modelo excesivamente complejo, lleno de abstracciones que no aportan significado real.

DDD no consiste en utilizar muchas clases ni en reproducir literalmente todos sus patrones tácticos. La cuestión fundamental es que las estructuras del software representen de forma útil las reglas y conceptos que realmente importan en el dominio.

Un sistema puede tener muchas entidades y, sin embargo, tener un modelo de dominio pobre. También puede tener un modelo relativamente sencillo y representar extraordinariamente bien un problema concreto.

La complejidad debe aparecer cuando el negocio es complejo, no porque la técnica utilizada para modelarlo lo sea.

DDD y la arquitectura del sistema

DDD tampoco determina por sí solo una arquitectura completa. Un sistema diseñado siguiendo DDD puede utilizar una aplicación monolítica, una arquitectura distribuida o diferentes estilos de integración.

Lo que sí aporta es una forma de decidir dónde deben situarse determinadas responsabilidades y qué partes del sistema pertenecen realmente al dominio.

Esto resulta especialmente interesante cuando se combina con arquitecturas que buscan aislar la lógica empresarial de los mecanismos externos. El dominio puede expresar sus reglas sin depender directamente de una base de datos concreta, de un framework web o de un proveedor externo.

La arquitectura deja entonces de ser únicamente una cuestión de organización técnica y empieza a reflejar también las fronteras conceptuales del negocio.

En sistemas grandes, los contextos delimitados pueden incluso convertirse en una herramienta para decidir cómo dividir aplicaciones o servicios. Pero aquí también conviene evitar una asociación automática: un contexto delimitado no equivale necesariamente a un microservicio, porque el límite conceptual del dominio y el límite físico de un despliegue son decisiones diferentes.

El verdadero trabajo está fuera del código

Quizá la consecuencia más importante de DDD sea que desplaza parte del trabajo esencial del ingeniero de software fuera del editor de código.

Comprender un dominio requiere hablar con las personas que conocen el negocio, observar cómo trabajan, cuestionar términos ambiguos, descubrir excepciones y comprender qué reglas utilizan realmente para tomar decisiones.

Esto puede resultar incómodo para quien está acostumbrado a pensar que desarrollar software consiste principalmente en implementar requisitos ya definidos. En dominios complejos, los requisitos escritos rara vez contienen todo el conocimiento necesario.

El modelo de dominio se construye mediante un proceso de aprendizaje compartido entre las personas que conocen el negocio y las personas que construyen el software.

Por eso DDD tiene una dimensión técnica y otra de comunicación. El código es importante, pero también lo son las conversaciones que permiten descubrir qué debe representar ese código.

Cuándo aporta valor y cuándo puede resultar excesivo

DDD resulta especialmente interesante cuando el dominio contiene reglas complejas, conceptos que evolucionan, diferentes áreas de negocio con significados distintos o decisiones empresariales que deben quedar reflejadas con precisión en el software.

No todos los sistemas tienen ese nivel de complejidad. Una aplicación sencilla de gestión de información puede no necesitar un modelo de dominio sofisticado. Introducir agregados, servicios y múltiples abstracciones donde no existe una complejidad real puede hacer que el sistema sea más difícil de entender.

Por eso el objetivo no debería ser “aplicar DDD” como una obligación metodológica. El objetivo debería ser utilizar las herramientas de DDD cuando ayudan a gestionar la complejidad real del dominio.

Esta perspectiva también evita otro error frecuente: confundir DDD con una arquitectura determinada. DDD es, ante todo, una forma de abordar el diseño del software a partir del conocimiento del dominio. Los patrones y las técnicas son herramientas para conseguirlo, no el objetivo final.

Una forma diferente de pensar el software

La principal aportación de DDD no es un nuevo tipo de clase ni una estructura concreta de proyecto. Es un cambio de perspectiva.

En lugar de comenzar preguntando qué tablas necesitamos, qué endpoints debemos crear o qué clases debemos implementar, comenzamos preguntando cómo funciona el negocio, qué conceptos utiliza, qué reglas lo gobiernan y dónde aparecen diferentes interpretaciones de una misma realidad.

A partir de ahí, el software puede empezar a adquirir una estructura que refleje ese conocimiento.

Los contextos delimitados nos ayudan a controlar dónde tiene sentido cada modelo. Las entidades representan conceptos cuya identidad importa. Los objetos de valor permiten modelar valores con significado propio. Los agregados establecen fronteras de consistencia y los servicios de dominio permiten expresar operaciones que no pertenecen naturalmente a una única entidad.

Pero todos ellos son piezas de una idea más amplia. Diseñar guiado por el dominio significa intentar que el software y el conocimiento del negocio evolucionen juntos, de manera que el modelo utilizado por el sistema sea una expresión útil de cómo funciona realmente el problema que queremos resolver.

Al final, DDD no consiste en hacer que el código se parezca más al negocio simplemente porque utiliza sus palabras. Consiste en conseguir algo más profundo: que las decisiones importantes del software estén fundamentadas en una comprensión explícita del dominio y que esa comprensión pueda mantenerse, discutirse y evolucionar junto con el propio sistema.