¿Qué es el dominio? Área temática o campo a la que un usuario aplica un software.
¿Qué es el modelo de dominio? Representa la terminología y los conceptos clave del dominio del problema. Identifica las relaciones entre las entidades incluidas dentro del ámbito del dominio del problema, identifica sus atributos y proporciona una visión estructural del dominio.
Domain driven design es un enfoque para el desarrollo de software definido por Eric Evans en su libro Domain-driven design: Tackling Complexity in the Heart of Software, que se centra en un modelo rico, expresivo y en constante evolución para resolver problemas del dominio de una forma semántica.
Lenguaje común (Ubiquitous language)
Uno de los mayores problemas que surgen durante el desarrollo de proyectos software es la comunicación entre los desarrolladores y los expertos del dominio.
Los expertos del dominio tienen un amplio conocimiento sobre el dominio, por el contrario, su conocimiento de la terminología técnica utilizada en el desarrollo de software es bastante limitada. Por otro lado, los desarrolladores entendemos y manejamos la terminología técnica, sin embargo, habitualmente nuestro conocimiento sobre el dominio del problema es bastante limitado. ya sea porque nunca nos hayamos enfrentado a un problema dentro de ese dominio o en caso de que si lo hayamos hecho, muy probablemente fuera desde una perspectiva o entorno distinto, ya que empresas de un mismo sector pueden enfocan sus problemas de manera totalmente distinta. Esta diferencia de lenguajes y conocimientos normalmente da lugar a situaciones en las que los expertos del dominio describen de manera confusa y ambigua qué esperan del sistema. A su misma vez los desarrolladores tenemos muchos problemas para entender el dominio del problema, y por lo tanto para entender lo que los expertos del dominio requieren del sistema.
En proyectos donde no existe un lenguaje común nos vemos obligados a realizar un proceso de traducción para poder comunicarnos con los expertos del dominio. A su vez, los expertos del dominio tienen que realizar un proceso de traducción en sentido opuesto para comunicarse con los desarrolladores. A menudo los mismos desarrolladores nos vemos obligados a realizar traducciones cuando nos comunicamos con otros desarrolladores.
Cada vez que se realiza una traducción se malinterpretan y confunden conceptos, provocando que diferentes miembros del equipo entiendan conceptos de manera diferente, y lo que es aún peor, sin ser conscientes de ello. Estas malas interpretaciones hacen que el software contenga incoherencias, y contradicciones dentro del código que provocarán errores en el sistema.
Todos estos problemas durante el proceso de comunicación entre los miembros del equipo hacen que, por un lado perdamos oportunidades de obtener un conocimiento más profundo del dominio y por otro lado, siendo aún más importante, la terminología utilizada para la comunicación no se ve reflejada en el software.
Para ser capaces de generar un lenguaje común, los desarrolladores tenemos que obtener el conocimiento necesario del dominio, mientras que los expertos del dominio deben formar parte activa en el desarrollo del software. De manera que tanto el dominio del problema, como los elementos del diseño del software (clases, relaciones, etc…) formen parte del lenguaje común y sean entendidas por los desarrolladores y los expertos del dominio. Ya que los expertos conocen en detalle el dominio, deben oponerse a cambios en el modelo que no sean adecuados para una correcta transmisión del conocimiento incluido en el dominio, siendo los desarrolladores los que deberíamos controlar posibles ambigüedades e inconsistencias que pongan trabas al diseño del sistema.
El proceso para llegar a un lenguaje común es iterativo, de tal manera que deberemos ejercitar el lenguaje y pulirlo mediante su utilización tanto en diagramas, como en escrito, y especialmente en la comunicación verbal. Esto hará que el lenguaje vaya evolucionando y cambiando. Dichos cambios deben verse reflejados en el código, por lo que deberemos ir refactorizando dicho código para que refleje los cambios que se producen en el lenguaje.
Para llevar a cabo la tarea de vincular el conocimiento del dominio a la implementación del modelo disponemos de diferentes elementos. Describiremos los elementos que son utilizados para modelar operaciones que pertenecen a un objeto concreto (entidades y value objects), y los elementos que representan actividades o acciones que pertenecen conceptualmente a más de un objeto.
Entities
Las entidades son objetos del modelo que se caracterizan por tener identidad en el sistema, los atributos que contienen no son su principal característica. Representan conceptos con una identidad que se mantienen en el tiempo, y que con frecuencia también se mantienen bajo distintas representaciones de la entidad. Deben poder ser distinguidas de otros objetos aunque tengan los mismos atributos. Tienen que poder ser consideradas iguales a otros objetos aún cuando sus atributos difieren.
Por ejemplo, imaginemos un objeto Persona con nombre y apellidos como atributos de una clase en un sistema donde dos objetos que representan a dos personas diferentes con los mismos nombres y apellidos deberían ser considerados diferentes.
Como vemos, en este caso no podemos describir el objeto persona primariamente por sus atributos, si no que debemos de asignarle una identidad que se mantenga para cualquier representación de esa persona. Si nuestro sistema trabaja únicamente con personas de nacionalidad españolas podríamos considerar como identidad el DNI, en cambio si manejamos personas de cualquier nacionalidad quizás debamos de autogenerar este ID dentro de nuestro sistema (Muchos países no tiene documento nacional de identidad). Cabe destacar que en un sistema, Persona puede ser considerado una entidad, mientras que en otro sistema donde no necesitemos identificar a una persona por su identidad podría no serlo.
La identidad tiene que ser declarada de tal manera que podemos rastrear la entidad de manera eficaz. Los atributos, responsabilidades y relaciones deben ser definidas en relación a la identidad que representa la entidad más que en los atributos que la componen.
Como podemos observar, el hecho de que necesitemos identificar y distinguir distintos objetos a lo largo de su ciclo de vida hace que la complejidad para manejarlos y diseñarlos sea bastante mayor que la de los que no la necesitan. Por este motivo debemos usar entidades únicamente para objetos que realmente lo requieran, lo cual tiene dos ventajas importantes. Por un lado, no incluiremos complejidad innecesaria en objetos que no requieran ser identificados, por otro lado al reducir el número de entidades en el sistema seremos capaces de identificarlas rápidamente.
Value objects
Al contrario que las entidades los value objects representan conceptos que no tienen identidad. Simplemente describen características. Por lo tanto solo nos interesan sus atributos.
Los value object representan elementos del modelo que se describen por el QUÉ son, y no por QUIÉN o CUÁL son.
Pongamos por ejemplo, un objeto Color representado por su composición RGB(Red, Green, Blue). Si tuviéramos dos objetos representando el mismo color podríamos usar cualquiera de ellos, ya que nos interesa qué color es por sus atributos, no por cuál instancia estamos usando. Otros ejemplos de value objects podrían ser String o Integer, ya que no nos importa que ¨C¨ o que ¨3¨ estamos usando. Aunque estos ejemplos son simples los value objects no tienen porque serlo.
Esto conlleva una serie de diferencias a la hora de modelar value objects respecto a las entidades. Los value objects suelen ser modelados como inmutables y son menos complejos de diseñar, ya que podremos usarlos y descartarlos según nos interese, pues no tenemos que preocuparnos por la instancia que estemos utilizando (siempre y cuando sus atributos sean los correctos).
Tanto las entidades como los value objects representan conceptos, por tanto suelen ser nombrados con sustantivos.
En el próximo post pasaremos a describir en detalle en qué consiste otra de las partes fundamentales de domain-driven design, los services, y cómo aislar los detalles de la capa de dominio del resto del sistema, !estad atentos!