Compréhension du contexte d'exécution
Objectifs de formation
Une fois cette unité terminée, vous pourrez :
- Comprendre les méthodes à utiliser pour invoquer un code Apex
- Écrire un déclencheur pour un objet Salesforce
- Observer le fonctionnement du contexte d'exécution en exécutant un code dans la Developer Console
- Comprendre l'impact des limites du gouverneur sur les modèles de conception
- Comprendre l'importance de l'utilisation d'opérations en masse
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.
(Ce clip commence à 16 min 36 s, au cas où vous voudriez revenir en arrière et regarder à nouveau le début de l’étape.)
Qu'est-ce que le contexte d'exécution ?
Pour les applications ASP.NET, le code est exécuté dans le contexte d'un domaine d'application. Dans l'univers de la plate-forme Lightning, le code est exécuté dans le contexte d'exécution. En résumé, ce contexte représente le délai entre l'exécution du code et sa fin. Il est important de comprendre que le code Apex que vous écrivez n'est pas toujours le seul code exécuté.
Pour comprendre son fonctionnement, vous devez connaître toutes les méthodes d'exécution d'un code Apex sur la plate-forme.
Méthodes d’invocation Apex
Méthode |
Description |
---|---|
Déclencheur de base de données |
Invoqué pour un événement spécifique dans un objet personnalisé ou standard. |
Apex anonyme |
Extraits de code exécutés sur-le-champ dans la Developer Console et dans d'autres outils. |
Apex asynchrone |
Se produit lors de l'exécution d'Apex future ou queueable, de l'exécution d'une tâche par lot ou de la planification de l'exécution d'un code Apex à une fréquence spécifiée. |
Services Web |
Code exposé via des services Web entrants ou sortants SOAP ou REST. |
Services de messagerie |
Code configuré pour traiter les e-mails entrants ou sortants. |
Pages Visualforce ou Lightning |
Les contrôleurs Visualforce et les composants Lightning peuvent exécuter un code Apex automatiquement ou lorsqu'un utilisateur initie une action, par exemple un clic sur un bouton. Les composants Lightning sont également exécutés par des processus et des flux Lightning. |
Outre l'invocation d'un code Apex, des actions telles que la création d'une page, l'envoi d'un e-mail, l'exécution d'une mise à jour de champ ou l'envoi d'un message sortant, peuvent être déclenchées par l'une des fonctionnalités de plate-forme déclaratives. Ces actions sont également exécutées dans un contexte d'exécution.
Un autre élément important à prendre en compte est le contexte de l'utilisateur qui exécute le code Apex. Par défaut, Apex est exécuté dans le contexte du système. Le code Apex a accès à tous les objets et à tous les champs. Les autorisations d'objet, la sécurité au niveau du champ et les règles de partage ne sont pas appliquées à l'utilisateur actif. Vous pouvez utiliser le mot-clé with sharing pour spécifier l'application des règles de partage à l'utilisateur actif pour une classe. Ce point est important. Reportez-vous à Utilisation des mots-clés with sharing et without sharing.
Éléments essentiels sur les déclencheurs
Avant d'aller plus loin sur le contexte d'exécution, arrêtons-nous un instant sur l'univers des déclencheurs de base de données. Semblables aux déclencheurs dans SQL Server, les déclencheurs de base de données Apex exécutent une logique de programmation avant ou après des événements sur des enregistrements dans Salesforce. Lors de la définition du déclencheur, vous pouvez spécifier plusieurs événements parmi les suivants :
- before insert
- before update
- before delete
- after insert
- after update
- after delete
- after undelete
La syntaxe de base d'un déclencheur se présente comme suit :
trigger TriggerName on ObjectName (trigger_events) { // code_block }
Nous sommes conscients qu’en tant que développeur .NET, vous aimez résoudre les problèmes avec un code. Laissez-nous néanmoins vous donner un précieux conseil afin de gagner en productivité. Ayez recours à un déclencheur uniquement lorsque vous êtes absolument certain que la même opération ne peut pas être accomplie avec l’un de nos outils d’automatisation par pointer-cliquer.
Pour faciliter votre travail, la plate-forme Salesforce inclut un puissant outil d’automatisation, Flow Builder, qui permet de gérer une logique métier sans écrire de code. Dans la plupart des cas, les tâches qui pouvaient auparavant être réalisées avec un déclencheur sont désormais plus simples avec des outils d'automatisation.
Marquage du contexte d'exécution
Pour mieux comprendre le contexte d'exécution, examinons la création d'un déclencheur de base de données Apex qui crée une opportunité lorsqu'un nouveau compte est saisi. Ce déclencheur appelle une méthode à partir d'une classe de gestionnaire, que nous devons au préalable créer.
- Dans Configuration, sélectionnez Votre nom > Developer Console pour ouvrir la Developer Console.
- Dans la Developer Console, sélectionnez Fichier > Nouveau > Classe Apex.
- Saisissez le nom de classe AccountHandler, puis cliquez sur OK.
- Supprimez le code existant, puis insérez l'extrait suivant :
public with sharing class AccountHandler { public static void CreateNewOpportunity(List<Account> accts) { for (Account a : accts) { Opportunity opp = new Opportunity(); opp.Name = a.Name + ' Opportunity'; opp.AccountId = a.Id; opp.StageName = 'Prospecting'; opp.CloseDate = System.Today().addMonths(1); insert opp; } } }
- Appuyez sur Ctrl + S pour enregistrer votre classe.
Nous avons maintenant une classe de gestionnaires, nous pouvons créer le déclencheur Account.
- Dans la Developer Console, sélectionnez Fichier > Nouveau > Déclencheur Apex.
- Saisissez le nom AccountTrigger, puis sélectionnez le sObject Account.
- Cliquez sur Soumettre.
- Supprimez le code existant, puis insérez l’extrait suivant :
trigger AccountTrigger on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { if (Trigger.isAfter && Trigger.isInsert) { AccountHandler.CreateNewOpportunity(Trigger.New); } }
- Appuyez sur Ctrl + S pour enregistrer votre déclencheur.
Pour terminer la procédure, nous exécutons un code anonyme afin de simuler la saisie du nouveau compte par un utilisateur en utilisant l'interface Salesforce. Souvenez-vous que le code Apex peut être exécuté de plusieurs façons.
- Dans Configuration, sélectionnez Votre nom > Developer Console pour ouvrir la Developer Console.
- Sélectionnez Débogage > Ouvrir la fenêtre d’exécution anonyme.
- Supprimez le code existant, puis insérez l’extrait suivant :
Account acct = new Account( Name='Test Account 2', Phone='(415)555-8989', NumberOfEmployees=50, BillingCity='San Francisco'); insert acct;
- Assurez-vous que l'option Open Log est sélectionnée, puis cliquez sur Execute. Un nouvel onglet affiche le journal d'exécution. Laissez-le ouvert pour pouvoir l'examiner attentivement.
Examen du journal d'exécution
Notez que la première ligne du journal d'exécution désigne l'événement EXECUTION_STARTED et que la dernière ligne est l'événement EXECUTION_FINISHED. Tout ce qui se situe entre ces deux lignes correspond au contexte d'exécution.
Examinons l'exécution de plus près. Un événement CODE_UNIT_STARTED marque le démarrage du code dans la fenêtre Execute Anonymous. La ligne est entourée en rouge dans l'image ci-dessous.
La deuxième ligne CODE_UNIT_STARTED entourée indique l'heure à laquelle l'événement BeforeInsert a été exécuté.
Vous ne pouvez pas le voir sur cette image, mais si vous suivez avec votre propre instance de Developer Console, faites défiler les résultats et examinez les autres instances de CODE_UNIT_STARTED. Au moins une autre instance représentant l'exécution du code de l'événement AfterInsert doit être affichée. Si vous avez créé des règles de workflow qui se déclenchent lors de la création d'un compte, elles devraient également être affichées dans le journal d'exécution. Tout ce code fonctionne dans le même contexte d'exécution. Par conséquent, il est soumis au même ensemble de limites du gouverneur.
Vous vous demandez peut-être pourquoi il est important de comprendre ce point ? Salesforce est un environnement mutualisé. Par conséquent, ces limitations sont essentielles pour éviter que chaque instance d'une organisation Salesforce consomme trop de ressources. Fondamentalement, elles empêchent la défaillance du système.
Utilisation de limites
Cela nous renvoie à l'utilisation de limites. Les deux limites qui vous intéressent le plus concernent probablement le nombre de requêtes SOQL ou d'instructions DML. Elles ont tendance à gêner les développeurs qui débutent sur la plate-forme. Par conséquent, nous allons examiner comment les éviter.
Exécution en masse
De nombreux développeurs tombent dans le piège classique qui consiste à concevoir un code qui fonctionne pour un seul enregistrement. Ils s'aperçoivent rapidement qu'il s'agit d'une grave erreur sur la plate-forme Lightning.
Les déclencheurs Apex peuvent recevoir jusqu’à 200 enregistrements à la fois. Actuellement, la limite synchrone pour le nombre total de requêtes SOQL est de 100 et de 150 pour le nombre total d’instructions DML émises. Par conséquent, si vous avez un déclencheur qui exécute une requête SOQL ou une instruction DML dans une boucle et que le déclencheur est activé pour une opération en masse, devinez quoi ?
BOUM !!!
Oui, vous allez obtenir une erreur de limitation. Il est possible de déployer un code et de l'exécuter sans problème avant d'atteindre la limite. Une fois atteinte, le développeur doit réagir rapidement et déterminer comment traiter le code « en masse ». Cette deuxième tentative prend souvent beaucoup plus de temps que la conception initiale. Pour éviter ce scénario, concevez votre code Apex pour gérer les opérations en masse dès sa création. Pour découvrir les différentes méthodes disponibles, suivez le module Déclencheurs Apex en masse.
Vous avez peut-être remarqué que le code du gestionnaire de déclencheur que nous avons créé plus haut n’utilisait pas de modèle en masse. Par conséquent, il est exposé aux erreurs de limitation. En guise de rappel, le code d'origine se présentait comme suit :
public with sharing class AccountHandler { public static void CreateNewOpportunity(List<Account> accts) { for (Account a : accts) { Opportunity opp = new Opportunity(); opp.Name = a.Name + ' Opportunity'; opp.AccountId = a.Id; opp.StageName = 'Prospecting'; opp.CloseDate = System.Today().addMonths(1); insert opp; } } }
Notez que l'opération DML insert est à l'intérieur de la boucle for. Vous devez toujours éviter cette situation.
Heureusement pour nous, nous pouvons corriger ce code en le modifiant pour écrire dans une variable de liste à l'intérieur de la boucle, puis insérer le contenu de la liste en une étape.
- Dans Configuration, sélectionnez Votre nom > Developer Console pour ouvrir la Developer Console.
- Dans la Developer Console, sélectionnez Fichier > Ouvrir.
- Sélectionnez le type d'entité Classes. Sélectionnez l'entité AccountHandler.
- Cliquez sur Open.
- Supprimez le code existant, puis insérez l’extrait suivant :
public with sharing class AccountHandler { public static void CreateNewOpportunity(List<Account> accts) { List<Opportunity> opps = new List<Opportunity>(); for (Account a : accts) { Opportunity opp = new Opportunity(); opp.Name = a.Name + ' Opportunity'; opp.AccountId = a.Id; opp.StageName = 'Prospecting'; opp.CloseDate = System.Today().addMonths(1); opps.add(opp); } if (opps.size() > 0) { insert opps; } } }
- Appuyez sur Ctrl + S pour enregistrer votre classe.
Nous avons corrigé le code du gestionnaire du déclencheur. Nous pouvons maintenant tester afin de vérifier que le déclencheur peut traiter une charge de 200 enregistrements. Comme vous le savez, l'écriture de tests unitaires pour s'assurer du bon fonctionnement du code est une excellente pratique.
- Dans la Developer Console, sélectionnez Fichier > Nouveau > Classe Apex.
- Saisissez le nom de classe AccountTrigger_Test, puis cliquez sur OK.
- Supprimez le code existant, puis insérez l’extrait suivant :
@isTest private class AccountTrigger_Test { @isTest static void TestCreateNewAccountInBulk() { // Test Setup data // Create 200 new Accounts List<Account> accts = new List<Account>(); for(Integer i=0; i < 200; i++) { Account acct = new Account(Name='Test Account ' + i); accts.add(acct); } // Perform Test Test.startTest(); insert accts; Test.stopTest(); // Verify that 200 new Accounts were inserted List<Account> verifyAccts = [SELECT Id FROM Account]; System.assertEquals(200, verifyAccts.size()); // Also verify that 200 new Opportunities were inserted List<Opportunity> verifyOpps = [SELECT Id FROM Opportunity]; System.assertEquals(200, verifyOpps.size()); } }
- Appuyez sur Ctrl + S pour enregistrer votre classe.
- Sélectionnez Test > Nouvelle exécution.
- Sélectionnez AccountTrigger_Test en tant que TestClass, puis TestCreateNewAccountInBulk en tant que méthode de test.
- Cliquez sur Exécuter.
- Sélectionnez l’onglet Tests, puis vérifiez que le test est entièrement exécuté sans erreur, ce qui est indiqué par une coche verte dans la colonne de statut.
En savoir plus
Apex utilise un bloc try-catch-finally habituel pour gérer les exceptions. Cependant votre instruction catch et l'instruction rollback éventuelle peuvent différer selon l'emplacement où le code Apex est exécuté. Pour consulter les meilleures pratiques d'utilisation de try, catch et rollback en Apex, suivez les liens de la section Ressources.
Aucune variable d'application ou de session n'existe dans la plate-forme Lightning. Si vous avez besoin de données persistantes entre les classes, des variables statiques existent, mais elles ne fonctionnent pas de la même façon dans la plate-forme Lightning que dans .NET. Dans l'univers de la plate-forme Lightning, une variable statique peut maintenir des informations seulement dans un contexte d'exécution unique, même si d'autres options de gestion des données entre des invocations de déclencheurs sont disponibles. Pour en savoir plus, suivez les liens qui se rapportent à Advanced Apex dans les Ressources Internet.
Lors de l'utilisation de limites, vous devez faire de nombreux compromis, notamment pour le développement de packages gérés. À ce propos, les partenaires Salesforce utilisent généralement des packages gérés pour distribuer et vendre des applications. Dans ce module, nous avons évoqué les principaux éléments que vous devez connaître. Pour aller plus loin dans le développement Apex, suivez les liens qui se rapportent à Advanced Apex dans les Ressources Internet.
Ressources
-
Invoking Apex dans le guide Apex Code Developer’s Guide
-
Getting Started with Apex Triggers dans le parcours pour développeur débutant
-
Compréhension des limitations et des gouverneurs d’exécution
-
Tester les déclencheurs dans le parcours pour développeur débutant