Aprender principios sobre la Capa de dominios
Objetivos de aprendizaje
Después de completar esta unidad, podrá:
- Resumir los orígenes del patrón de dominio a partir de los patrones de arquitectura de aplicaciones empresariales.
- Determinar qué tipo de código Apex pertenece a la capa de dominios.
- Explicar en qué lugar de la arquitectura de su aplicación y la plataforma encaja la capa de dominios.
- Diseñar una capa de dominios que cumpla con las mejores prácticas de la plataforma.
Requisitos previos
Le damos la bienvenida. Este módulo desarrolla los principios que aprendió en el módulo Patrones de negocio de Apex: Capa de servicios y los pasos que completó en Trailhead Playground durante los retos prácticos. En ese módulo, tratamos la capa de servicios como un medio para encapsular los procesos de negocio de su aplicación, y nos centramos en cómo se exponen los servicios de manera coherente y significativa a otras partes de su aplicación, como los controladores de Visualforce, Apex por lotes y las API públicas.
Si no completó el módulo Patrones de negocio de Apex: Capa de servicios, hágalo antes de continuar.
Capa de dominios
Dominio (ingeniería de software): “Un dominio es un campo de estudio que define un conjunto de requisitos, terminología y funcionalidades comunes para cualquier programa de software desarrollado para resolver un problema en el área de la programación de computadoras, lo que se denomina ingeniería de dominio”. En Wikipedia, Dominio (ingeniería de software)
Con los patrones de negocio de Salesforce Platform, la capa de dominios se define mediante los objetos personalizados que crea (proyecto, factura, etc.), lo que le permite generar rápidamente el almacenamiento de datos de su aplicación. Pero, ¿qué ocurre con el comportamiento de dichos objetos, tales como la validación, el cálculo y la manipulación compleja de datos? Puede expresar comportamiento en Salesforce de manera tanto declarativa (interactiva) como programática mediante el uso de Apex. El uso efectivo de esta combinación es clave para ser un desarrollador de aplicaciones exitoso en la plataforma. Y, seamos sinceros, ¿acaso no queremos todos ser desarrolladores exitosos en la plataforma?
Patrón de dominio
Si la complejidad de determinados comportamientos para objetos de su aplicación requiere programación de Apex, considere estructurar y factorizar el código mediante el uso de técnicas de programación orientada a objetos (OOP, por sus siglas en inglés) y el patrón de modelo de dominio.
Modelo de dominio: “Un modelo de objeto del dominio que incorpora tanto comportamiento como datos”. “En su peor vertiente, la lógica de negocio puede ser muy compleja. Las reglas y la lógica describen muchos casos y sesgos de comportamiento diferentes; no obstante, los objetos fueron diseñados para trabajar con esta complejidad.” De Fowler, Martin
Al igual que la capa de servicios, el modelo de dominio proporciona un nivel más granular de encapsulación y reutilización de código dentro de su aplicación, como la validación compleja, la aplicación de valores predeterminados y otra lógica relativa al cálculo y la manipulación complejos.
Esta unidad toma una perspectiva de Apex específica sobre el patrón de modelo de dominio. Proporciona directrices para asociar claramente el código de capa de dominios a cada objeto personalizado, lo que le permite gestionar mejor el establecimiento eficaz de capas y la separación de intereses (SOC) dentro de la base de código de su aplicación. Antes de profundizar en lo que constituye una clase de dominio, revisemos dónde se usan.
- Desencadenadores de Apex: las operaciones de creación, lectura, actualización y eliminación (CRUD, por sus siglas en inglés), incluida la recuperación, se realizan en sus objetos personalizados cuando los usuarios o las herramientas interactúan a través de las interfaces de usuario estándares de Salesforce o una de las API de la plataforma. Las operaciones se dirigen al código de clase de dominio apropiado correspondiente a dicho objeto y dicha operación.
- Servicios de Apex: el código de capa de servicios debería ser fácil de identificar y debería facilitar la reutilización de código relativo a uno o más de los objetos con los que interactúa cada una de sus operaciones a través de las clases de dominio. Este enfoque hace que el código de la capa de servicios se centre en dirigir el proceso o la tarea de negocio que esté exponiendo.
La clase de dominio de Apex es consumida por la lógica de controlador de desencadenador de Apex y la llamada de método de servicio de Apex, cuya presentación se realizó en el módulo Patrones de negocio de Apex: Capa de servicios. Esta unidad incluye el modo en el que estas dos áreas pueden compartir la lógica expuesta a través de una clase de dominio, ya sea explícitamente al llamar a sus métodos o indirectamente a través de una lógica de controlador de desencadenador.
Importante: Recuerde que se recomienda que el código relacionado con los controladores del Componente web Lightning y de Visualforce, Apex por lotes y las clases de API que desarrolle use funcionalidades expuestas únicamente a través de las operaciones de la capa de servicios. Así, las clases service tier client siempre invocan indirectamente el código escrito en la capa de dominios. El código de capa de dominios suele ser un aspecto de la lógica de negocio interna de su aplicación.
Consideraciones de diseño
La capa de dominios ofrece a su aplicación el acceso a funciones de programación orientada a objetos en Apex, pero lo hace de un modo que se alinea (principalmente por convenciones de nomenclatura) con los términos y conceptos del dominio de su aplicación y las mejores prácticas propias de la plataforma.
Estas son algunas consideraciones de diseño para tener en cuenta.
Siga el proceso con Trail Together
¿Desea seguir el proceso con un experto a medida que realiza este paso? Mire este video que forma parte de la serie Trail Together.
Uso de clases de dominio de servicios
Echemos un vistazo a OpportunitiesService
, que se presentó en el módulo Patrones de negocio de Apex: Capa de servicios, para refactorizar parte del comportamiento del método applyDiscounts
más abajo en un método de clase de dominio.
El código siguiente muestra una nueva implementación del método de servicio applyDiscounts
. Esta vez está usando la nueva clase Oportunidades que vamos a crear en esta unidad. Esta clase está encapsulando la lógica que realiza los cálculos de descuento mediante su propio método applyDiscount
.
public static void applyDiscounts(Set<Id> opportunityIds, Decimal discountPercentage) { // Unit of Work // …
// Validate parameters // ...
// Construct Opportunities domain class Opportunities opportunities = new Opportunities( [select Id,Amount, (select UnitPrice from OpportunityLineItems) from Opportunity where Id in :opportunityIds]);
// Apply discount via domain class behavior opportunities.applyDiscount(discountPercentage, uow);
// Commit updates to opportunities uow.commitWork(); }
Uso de clases de dominio de desencadenadores
Consideremos también otro punto de entrada. Como se mostró en el diagrama de la sección Patrón de dominio, los usuarios invocan los desencadenadores de Apex a través de las interfaces de usuario de Salesforce o el código; para ello, manipulan los registros mediante DML o las API de Salesforce.
Dada la función de la clase de dominio con respecto a la encapsulación de toda la lógica y el comportamiento de un objeto de dominio determinado, debemos garantizar que las llamadas de desencadenadores de Apex también se dirigen a los métodos de clase apropiados.
Al igual que con muchos patrones emergentes alrededor de los desencadenadores de Apex, recomendamos mantener la lógica al mínimo en el desencadenador. Los desencadenadores de Apex no son clases y tienen un medio limitado para factorizar código o usar principios de POO como la herencia. Ofrecen lugares que resultan insuficientes incluso para una lógica moderadamente compleja.
El siguiente código de desencadenador de Apex es posible gracias al uso de la clase fflib_SObjectDomain que forma parte de la biblioteca de código abierto Patrones de negocio de Apex. Esta clase forma una clase base para todas las clases de dominio de su aplicación. Esto se tratará en mayor profundidad en la siguiente unidad.
El método estático fflib_SObjectDomain.triggerHandler
garantiza que el método aplicable en la clase Oportunidades se llame mediante la lectura de las variables de contexto de desencadenadores del sistema: Trigger.isAfter
, Trigger.isBefore
, Trigger.isInsert
, Trigger.new
, etc. El código de los desencadenadores de Apex que usa este patrón es muy ligero de manera intencionada.
trigger OpportunitiesTrigger on Opportunity (
after delete, after insert, after update, after undelete, before delete, before insert, before update) {
// Creates Domain class instance and calls appropriate methods
fflib_SObjectDomain.triggerHandler(Opportunities.class);
}
La clase Oportunidades a la que se hace referencia en el código anterior contiene métodos como onBeforeInsert
y onAfterUpdate
, los cuales implementan el comportamiento de este objeto cuando se realizan estas operaciones.
Recursos
- GitHub: Patrones de negocio de Apex
- Publicación de blog: Martin Fowler: Modelo de dominio
- Wikipedia: Dominio (ingeniería de software)
- Wikipedia: Separación de intereses
- Publicación de blog: Apex Hours de Salesforce: Patrones de negocio de Apex
- Video: Patrones de negocio de Apex
- Publicación de blog: Martin Fowler: Catálogo de patrones de arquitectura de aplicaciones empresariales