Patrón de Desarrollo Essence
El documento "Essence Pattern" de Andy Carlson, con fecha de 4 de julio de 1998, describe un patrón de diseño que aborda un problema específico en la creación de objetos. No confundir con el metamodelo de procesos del mismo nombre definido como estándar de la OMG.
Este patrón se ha establecido como pilar base para la creación de modelos de dominio en el proyecto actual en el que me encuentro colaborando. No sin polémicas y debates sobre su uso, zanjados por dirección de proyecto. De esta manera no he podido resistir la tentación de redactar estas líneas.
Problema que busca resolver el patrón Essence
Muchas clases, especialmente las persistentes, tienen un subconjunto de propiedades (atributos y/o relaciones) que deben ser válidas antes de que una instancia del objeto pueda considerarse válida. El desafío surge en entornos distribuidos o basados en componentes, donde el cliente que crea las instancias puede estar fuera del control de diseño. Se desea forzar a los clientes a especificar estas propiedades al crear nuevas instancias, y a veces, asegurar que no puedan ser alteradas después de la creación.
La Solución propuesta por el patrón Essence
Este patrón propone utilizar un objeto separado, llamado "Essence object", para recibir las propiedades obligatorias del objeto que se está creando (llamado "CreationTarget").- Creación del Objeto Essence: La creación del objeto Essence es irrestricta.
- Especificación de Propiedades: Se asigna un método separado en la clase Essence para cada propiedad obligatoria. Estos métodos almacenan el valor del parámetro en el objeto Essence. Para propiedades que no deben cambiarse después de la creación, los métodos setter solo se proporcionan en la clase Essence.
- Creación del Objeto Destino: Se fuerza a los clientes a obtener nuevas instancias de la clase CreationTarget a través de un método de la clase Essence (típicamente createTarget() o fromEssence()).
- Validación y Construcción: Este método en el objeto Essence valida las propiedades suministradas. Si son válidas, el Essence crea la nueva instancia del CreationTarget, pasándose a sí mismo al constructor del CreationTarget para que este recupere los valores de los parámetros e inicialice sus propias propiedades. Si la validación falla, se informa al cliente (por ejemplo, devolviendo un valor nulo o lanzando una excepción).
Beneficios:
- El objeto se crea sólo si los valores de las propiedades son válidos.
- No es necesario proporcionar métodos setter para propiedades inmutables en el objeto final.
- Permite flexibilidad en la especificación de diferentes permutaciones de parámetros sin sobrecargar el constructor
- Un solo objeto Essence puede crear múltiples instancias del CreationTarget si los parámetros difieren ligeramente.
Inconvenientes:
- Introduce una clase adicional al diseño, lo que puede causar confusión a los desarrolladores.
- La responsabilidad de la validación de atributos se divide entre dos lugares.
- Requiere una dependencia circular entre las clases Essence y CreationTarget.
Desafío de Implementación:
Este objetivo se puede lograr con constructores privados y clases "friend" (C++), o constructores protegidos y paquetes (Java), con Extensiones (Dart), con factorías, builder y algunos otros mecanismos.
Uso del Patrón Essence en Aplicaciones Basadas en DDD + Arquitectura Hexagonal Actuales
Dicho esto, su uso en aplicaciones actuales basadas en DDD (Domain-Driven Design) y Arquitectura Hexagonal es posible pero no es una práctica dominante ni particularmente común.
En el contexto DDD:
En el contexto Arquitectura Hexagonal:
¿Es recomendable su uso en Aplicaciones Flutter?
- Directamente en la UI/Gestión de Estado: El patrón Essence no es directamente aplicable a la construcción de la UI de Flutter (widgets, diseño) o a los patrones de gestión de estado (Provider, BLoC, Riverpod, GetX, etc.). Estos se centran en cómo se construye y actualiza la interfaz de usuario y cómo se maneja el estado de la aplicación.
- Para la creación de modelos de datos/objetos de dominio en Flutter (si aplica DDD): Si estás aplicando DDD en tu aplicación Flutter (lo cual es muy recomendable para aplicaciones complejas con lógica de negocio rica), podrías considerar usar el patrón Essence para la creación de tus objetos de dominio inmutables o con propiedades obligatorias.
- Para casos simples: Probablemente sea una sobre-ingeniería. Un constructor simple con validaciones o una Factoría estática en la propia clase es a menudo suficiente y más legible.
- Para la creación de objetos de dominio complejos: Si la creación de un objeto de dominio implica:
- Múltiples propiedades obligatorias.
- Varias formas válidas de especificar esas propiedades (ej. por ID o por nombre).
- Necesidad de una validación progresiva o retroalimentación al usuario antes de la creación final.
- La necesidad de que algunas propiedades sean inmutables después de la creación.
- Clientes (por ejemplo, el código de la capa de aplicación o presentación) que no puedes controlar completamente (menos común en una app de un solo monolito Flutter, pero posible si tienes módulos de equipo separados).
Comentarios