Lenguaje Ubicuo

El diseño dirigido por el dominio (DDD) no es un tema nuevo (Eric Evans formalizó el concepto hace más de una década). Sin embargo, es curioso cómo, hasta hoy, los conceptos básicos sobre el tema despiertan interés, especialmente en las comunidades .NET. Más extraño aún es cómo estos mismos conceptos son malinterpretados.

El fundamento de DDD radica en el concepto de lenguaje ubicuo. No está en determinar qué es una entidad, un objeto de valor, un agregado, un servicio o un repositorio.

La impresión que tenemos es que cualquiera que empieza a estudiar DDD lee las primeras páginas del libro de Evans o del libro de Vernon y salta rápidamente a las páginas que describen los patrones.

A menudo hablamos con informáticos que piensan que tener un lenguaje ubicuo definido significa que el nombre de las clases y las propiedades, escritas por los programadores, se ajusta al vocabulario de los expertos del dominio. Sin embargo, esto es una burda simplificación.

Para entender la importancia del lenguaje ubicuo, empecemos con la «entidad» que aparece a continuación:

public class Employee{ public string Id { get; set; } public string Name { get; set; } public string Cpf { get; set; } public decimal Salary { get; set; }}

¡Aquí hay un excelente ejemplo de implementación anémica! Pero antes de seguir leyendo, intenta averiguar por qué.

En nuestro trabajo diario, cuando utilizamos este ejemplo, escuchamos sugerencias de que esta clase carece de comportamientos (¡lo cual es correcto!). Sin embargo, cuando preguntamos cuáles serían esos «comportamientos», nos encontramos con que la gente repite argumentos genéricos (de gente que tampoco ha «pillado» la idea) y no puede identificar qué es lo que falla.

Uno de los argumentos más frecuentes es que los setters de las propiedades deberían ser privados. En su lugar, deberíamos tener métodos «DefineXXX» que implementaran validaciones. Esta idea no tiene sentido porque el propósito de los setters es precisamente establecer valores para las propiedades, y no habría ningún problema en implementar la lógica de validación en ellos.

Los métodos de una entidad deben explicar las motivaciones de sus cambios de estado. Además, debe haber al menos un constructor capaz de instanciar la entidad desde el principio, en un estado válido.

No es raro encontrar implementaciones de clases con propiedades que comprueban, por ejemplo, si el valor que se intenta establecer es no nulo, incluso cuando estas mismas propiedades tienen null como valor por defecto. ¿Cuál es la lógica aquí?

Vea otro ejemplo de una clase anémica:

public class Customer { public string Name { get; private set; } public string Email { get; private set; } public DateTime BirthDate { get; private set; } public Customer(Guid id, string name, string email, DateTime birthDate) { Id = id; Name = name; Email = email; BirthDate = birthDate; } }

En la clase anterior, tenemos un «registro» típico para una implementación funcional. Pero en un lenguaje orientado a objetos, esto no es una entidad.

La idea tendría incluso sentido en un lenguaje puramente funcional donde la «entidad» está conceptualmente repartida en varias funciones que definen el comportamiento, pero en C#, no tiene ningún sentido.

Intentemos una segunda versión para la clase Empleado:

public class Employee{ public string Id { get; private set; } public string Name { get; private set; } public string Cpf { get; private set; } public decimal Salary { get; private set; } public Employee(string name, string cpf) { //.. } public void RaiseSalary(decimal amount) { //.. }}

Esta vez la entidad es menos anémica. Después de todo, las motivaciones que impulsan el cambio de valor de las propiedades son evidentes. Observe cómo incluso el valor de la escritura de la prueba se hace más explícito.

De todos modos, todavía tenemos problemas. Hemos llamado al método «RaiseSalary», sin embargo, esta no es la forma en que los expertos del dominio describen esta operación. La única manera de definir las razones reales para cambiar los valores de las propiedades es hablando con estos expertos.

Pensar en…

Identificar e implementar el lenguaje ubicuo no es sólo para definir nombres de clases o propiedades. El lenguaje ubicuo debe revelarse principalmente en las motivaciones de los cambios de estado de nuestras entidades de forma explícita.

Entender el lenguaje ubicuo es mucho más importante que aprender los estándares. Sin un conocimiento real del dominio, el valor de los patrones de diseño es nulo.

Preocúpate primero de aprender lo más importante. Tómese el tiempo y el esfuerzo para entender bien el dominio y deletrear su lenguaje omnipresente. Entonces puede incluso tener sentido pensar en asociar DDD con conceptos técnicos más avanzados.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.