Apprendre les principes de la couche Domaine
Objectifs de formation
Une fois cette unité terminée, vous pourrez :
- Résumer les origines du modèle de Domaine en utilisant des modèles d’architecture d’entreprise
- Déterminer quel type de code Apex appartient à la couche Domaine
- Expliquer la place qu’occupe la couche Domaine dans votre architecture d’application et la plate-forme
- Concevoir une couche Domaine qui fonctionne avec les bonnes pratiques de la plate-forme
Prérequis
Dans tous les cas, bienvenue ! Ce module s’appuie sur les principes appris dans le module Apex Enterprise Patterns : Couche Service et les étapes que vous avez effectuées dans votre Trailhead Playground lors des défis pratiques. Dans ce module, nous vous avons présenté la couche Service comme un moyen d’encapsuler les processus métier de votre application, tout en nous concentrant sur la manière dont les services sont exposés de manière cohérente et significative à d’autres aspects de votre application, telles que les contrôleurs Visualforce, Apex par lot et les API orientées public.
Si vous n’avez pas encore suivi le module Apex Enterprise Patterns : Couche Service, terminez-le avant de continuer.
Couche Domaine
Domaine (génie logiciel) : « On entend par domaine un champ d’étude définissant un ensemble d’exigences, une terminologie et des fonctionnalités communes à tous les programmes logiciels construits pour résoudre un problème dans le secteur de la programmation informatique, connu sous le nom de génie de domaine ». — Wikipédia, Domaine (ingénierie logicielle)
Avec Salesforce Platform Entreprise Patterns, la couche Domaine est définie par les objets personnalisés que vous créez (projet, facture, etc.), ce qui vous permet de rapidement mettre en place le stockage de données de votre application. Cependant, qu’en est-il du comportement de ces objets, comme la validation, le calcul et la manipulation complexe des données ? Dans Salesforce, vous pouvez à la fois exprimer des comportements de manière déclarative (via des outils de type pointer-cliquer) et par programmation à l’aide d’Apex. Pour réussir dans le développement d’applications sur la plate-forme, il est essentiel d’utiliser ces deux possibilités de manière efficace. Et, soyons honnêtes : développer efficacement sur la plate-forme, n’est-ce pas là notre objectif à tous ?
Modèle de Domaine
Si la complexité de certains comportements relatifs aux objets au sein de votre application nécessite l’utilisation de code Apex, envisagez de structurer et de factoriser le code à l’aide de techniques de programmation orientée objet (ou OOP) et du modèle de Domaine.
Modèle de Domaine : « Un modèle d’objet du domaine intégrant à la fois des comportements et des données ». « Dans certains cas extrêmes, la logique métier peut être très complexe. Les règles et la logique décrivent alors un grand nombre de cas et de variations du comportement. Les objets ont précisément été conçus pour être associés à une telle complexité ». — Martin Fowler
À l’instar de la couche Service, le modèle Domaine fournit un niveau plus précis d’encapsulation et de réutilisation de code au sein de votre application, tel que la validation complexe, le retour aux valeurs par défaut ainsi que d’autres logiques liées aux calculs et manipulations complexes.
Cette unité aborde le modèle de Domaine sous une perspective propre à Apex. Il fournit des instructions permettant d’associer clairement du code de la couche Domaine à chaque objet personnalisé, vous permettant ainsi de gérer plus efficacement la mise en couche et la séparation des préoccupations (SOC) au sein de la base de code de votre application. Avant de nous intéresser aux éléments constitutifs d’une classe Domaine, intéressons-nous à leurs cas d’utilisation.
- Déclencheurs Apex : des opérations CRUD (create, read, update et delete, signifiant création, lecture, mise à jour et suppression), y compris des restaurations, se produisent sur vos objets personnalisés lorsque les utilisateurs ou les outils interagissent via une interface utilisateur standard de Salesforce ou l’une des API de la plate-forme. Ces opérations sont acheminées vers le code de classe Domaine adéquat, correspondant à cet objet et à cette opération.
- Services Apex : le code de la couche Service doit être facile à identifier. Il doit faciliter la réutilisation du code relatif à un ou plusieurs objets avec lesquels interagit chacune de ses opérations via des classes Domaine. Cette approche permet de consacrer le code de la couche Service à l’orchestration du processus métier ou de la tâche qu’il expose.
La classe Apex Domaine est utilisée par la logique du gestionnaire de déclencheur Apex et l’appel de méthode de service Apex présentés dans le module Apex Enterprise Patterns : Couche Service. Cette unité explique comment ces deux éléments peuvent partager la logique exposée par une classe Domaine, soit de manière explicite en appelant ses méthodes, soit de manière indirecte via une logique de gestionnaire de déclencheur.
Important : n’oubliez pas que le code relatif aux contrôleurs de composants Web Lightning, aux contrôleurs Visualforce, à Apex par lot et aux classes d’API que vous développez doit utiliser des fonctionnalités exposées uniquement via les opérations de la couche Service. Ainsi, le code écrit dans la couche Domaine est toujours appelé de manière indirecte par les classes clientes de niveau de service. Généralement, le code de la couche Domaine est un aspect de la logique métier interne de votre application.
Considérations de conception
La couche Domaine permet à votre application d’utiliser des fonctionnalités de la programmation orientée objet au sein d’Apex, en adéquation (selon les conventions de nommage, principalement) avec les termes et concepts de domaine de votre application et les bonnes pratiques propres à la plate-forme.
Voici quelques considérations de conception à prendre en compte.
Vidéo de démonstration Trail Together
Vous souhaitez être guidé pas à pas par un expert pendant que vous travaillez sur cette étape ? Regardez cette vidéo qui fait partie de la série Trail Together.
Utilisation de classes Domaine à partir de services
Intéressons-nous à OpportunitiesService
, que nous avions présenté dans le module Apex Enterprise Patterns : Couche Service pour refactoriser plus en aval certains comportements de la méthode applyDiscounts
dans une méthode de classe Domaine.
Le code suivant présente une nouvelle implémentation de la méthode de service applyDiscounts
. Cette fois, elle utilise la nouvelle classe Opportunities que nous créons dans cette unité. Cette classe encapsule la logique qui effectue les calculs de remise via sa propre méthode, 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(); }
Utilisation de classes Domaine à partir de déclencheurs
Considérons maintenant la situation depuis un autre point d’entrée. Comme l’illustre le diagramme figurant dans la section Modèle de Domaine, les utilisateurs invoquent des déclencheurs Apex via les interfaces utilisateur de Salesforce ou en manipulant le code des enregistrements via DML ou des API Salesforce.
Au vu du rôle joué par la classe Domaine dans l’encapsulation de l’ensemble de la logique et du comportement d’un objet Domaine donné, il est essentiel de s’assurer que les appels de déclencheurs Apex sont également acheminés vers les méthodes de classe appropriées.
Tout comme avec de nombreux modèles émergents dans le domaine des déclencheurs Apex, il est ici judicieux de n’employer que le minimum de logique possible dans le déclencheur. Les déclencheurs Apex ne sont pas des classes et disposent de moyens limités pour factoriser du code ou utiliser des principes orientés objet tels que l’héritage. La logique, même moyennement complexe, n’y a donc pas vraiment sa place.
Le fonctionnement du code de déclencheur Apex suivant est rendu possible grâce à l’utilisation de la classe fflib_SObjectDomain, qui fait partie de la bibliothèque open source Apex Enterprise Patterns. Cette classe forme une classe de base pour toutes les classes Domaine de votre application. Nous reviendrons sur ce point dans l’unité suivante.
La méthode statique fflib_SObjectDomain.triggerHandler
garantit que la méthode applicable dans la classe Opportunities est appelée en lisant les variables de contexte de déclencheur système Trigger.isAfter
, Trigger.isBefore
, Trigger.isInsert
, Trigger.new
, etc. Le code intégré aux déclencheurs Apex utilisant ce modèle est volontairement très léger.
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 classe Opportunities référencée dans le code ci-dessus contient des méthodes comme onBeforeInsert
et onAfterUpdate
, qui mettent en œuvre le comportement de cet objet lorsque ces opérations ont lieu.
Ressources
- GitHub : Apex Enterprise Patterns
- Publication sur le blog : Martin Fowler : Modèle de Domaine
- Wikipedia : Domaine (ingénierie logicielle)
- Wikipedia: Séparation des préoccupations
- Publication sur le blog : Blog Apex Hours de Salesforce : Apex Enterprise Patterns
- Vidéo : Apex Enterprise Patterns
- Publication sur le blog : Martin Fowler : catalogue de modèles d’architecture d’applications d’entreprise