Tutoriel Salesforce Apex pour débutants
⚡ Résumé intelligent
La programmation Apex offre aux développeurs Salesforce un langage orienté objet et fortement typé pour ajouter une logique métier personnalisée au CRM. Elle permet de gérer les classes, les déclencheurs et les traitements par lots, tandis que les limites de ressources garantissent la stabilité de la plateforme mutualisée.
Qu’est-ce qu’Apex dans Salesforce ?
Apex Apex est un langage de programmation orienté objet et fortement typé, développé par Salesforce pour la création d'applications SaaS (Software as a Service) et CRM (Customer Relationship Management). Apex permet aux développeurs de créer des applications SaaS tierces et d'ajouter une logique métier aux événements système grâce à la prise en charge des bases de données et aux interfaces client-serveur.
Apex permet aux développeurs d'ajouter une logique métier aux événements système tels que les clics sur des boutons, les mises à jour d'enregistrements associés et les pages Visualforce. La syntaxe d'Apex est similaire à celle de Java. S'inscrire à Salesforce pour apprendre comment fonctionne le CRM.
Caractéristiques du langage de programmation Apex
Voici les fonctionnalités importantes de Salesforce Apex :
- Apex est un langage insensible à la casse.
- Vous pouvez effectuer des opérations DML telles que INSERT, UPDATE, UPSERT et DELETE sur les enregistrements sObject à l'aide d'Apex.
- Vous pouvez interroger les enregistrements sObject à l'aide de SOQL (Salesforce Object Query Language) et de SOSL (Salesforce Object Search Language) dans Apex.
- Permet de créer un Test de l'unité et l'exécuter pour vérifier le couverture de code et l'efficacité du code en Apex.
- Apex s'exécute dans un environnement multi-tenant et Salesforce Salesforce a défini des limites de gouvernance afin d'empêcher un utilisateur de monopoliser les ressources partagées. Tout code dépassant une limite de gouvernance Salesforce échoue et une erreur s'affiche.
- Un objet Salesforce peut être utilisé comme type de données dans Apex. Par exemple :
Account acc = new Account();
Ici, Account est un objet Salesforce standard.
- Apex est automatiquement mis à niveau avec chaque version de Salesforce.
Quand un développeur devrait-il choisir Apex ?
Le code Apex ne doit être écrit que si un scénario métier est trop complexe pour être mis en œuvre à l'aide des fonctionnalités prédéfinies et intuitives fournies par Salesforce.
Voici quelques scénarios dans lesquels vous devrez écrire du code Apex :
- Pour créer des services Web qui intègrent Salesforce à d'autres applications.
- Pour implémenter une validation personnalisée sur les sObjects.
- Pour exécuter une logique Apex personnalisée lors de l'exécution d'une opération DML.
- Pour implémenter des fonctionnalités qui ne peuvent pas être réalisées avec les outils d'automatisation déclaratifs existants tels que Flow.
- Installer services de messagerie qui traitent le contenu, les en-têtes et les pièces jointes des courriels entrants.
Une fois que vous savez quand Apex est le bon choix, l'étape suivante consiste à comprendre ce qui arrive à votre code après l'avoir enregistré.
Structure de fonctionnement d'Apex
Voici le déroulement des actions pour le code Apex :
- Action du développeur : Lorsque le développeur enregistre du code sur la plateforme, tout le code Apex est compilé en un ensemble d'instructions que l'interpréteur d'exécution Apex peut comprendre, et ces instructions sont ensuite enregistrées en tant que métadonnées sur la plateforme.
- Action de l'utilisateur final : Lorsqu'un événement utilisateur exécute du code Apex, le serveur de la plateforme récupère les instructions compilées à partir des métadonnées et les exécute via l'interpréteur Apex avant de renvoyer le résultat.
Le diagramme ci-dessous illustre comment les actions du développeur et de l'utilisateur final interagissent avec le serveur d'applications de la plateforme Lightning :
Environnement de développement Apex
Le code Apex peut être développé soit dans un environnement sandbox, soit dans une organisation Developer Edition de Salesforce.
Il est recommandé de développer le code dans un environnement de test (sandbox) puis de le déployer dans l'environnement de production, comme illustré ci-dessous :
Outils de développement de code Apex : Voici les trois outils disponibles pour développer du code Apex dans toutes les éditions de Salesforce :
- Console développeur
- Visual Studio Code avec le pack d'extensions Salesforce (qui remplace l'IDE Force.com désormais obsolète)
- Code éditeur dans l'interface utilisateur de configuration de Salesforce
Votre environnement étant prêt, examinons les éléments constitutifs du langage lui-même, en commençant par les types de données.
Types de données dans Apex
Voici les types de données pris en charge par Apex :
Primitif
Entier, DoubleLes types Long, Date, Datetime, Decimal, Time, Blob, String, ID et Boolean sont considérés comme des types de données primitifs. Tous les types de données primitifs sont passés par valeur, et non par référence.
Collections
Trois types de collections sont disponibles dans Apex :
- Liste: Il s'agit d'une collection ordonnée de primitives, d'objets sObject, de collections ou d'objets Apex basée sur des index.
- Ensemble: Une collection non ordonnée d'éléments uniques ne contenant aucun doublon.
- Carte: Il s'agit d'un ensemble de clés uniques qui correspondent à des valeurs uniques, qui peuvent être des types primitifs, des sObjects, des collections ou des objets Apex.
sObjet
Il s'agit d'un type de données spécial dans Salesforce. C'est semblable à un tableau dans SQL et contient des champs similaires aux colonnes SQL.
Enums
Un Enum est un absolutractype de données t qui stocke une valeur d'un ensemble fini d'identifiants spécifiés.
Classes, objets et interfaces
Les classes et interfaces Apex définies par l'utilisateur peuvent également servir de types de données. Un objet désigne une instance de n'importe quel type de données pris en charge par Apex.
Syntaxe Apex
Déclaration de variable
Comme Apex est un langage fortement typé, il est obligatoire de déclarer une variable avec un type de données en Apex.
Par exemple :
Contact con = new Contact();
Ici, la variable con est déclarée avec Contact comme type de données.
Requête SOQL
SOQL signifie Salesforce Object Query Language (langage de requête d'objets Salesforce). SOQL est utilisé pour extraire des enregistrements sObject de la base de données Salesforce. Par exemple :
Account acc = [SELECT Id, Name FROM Account LIMIT 1];
La requête ci-dessus récupère un enregistrement de compte dans la base de données Salesforce.
Instruction de boucle
Une boucle permet de parcourir les enregistrements d'une liste. Le nombre d'itérations est égal au nombre d'enregistrements dans la liste. Par exemple :
List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
//your logic
}
Dans l'extrait de code ci-dessus, listOfAccounts est une variable de type List.
Déclaration de contrôle de flux
Une instruction de contrôle de flux est utile lorsque vous souhaitez exécuter certaines lignes de code en fonction de certaines conditions.
Par exemple :
List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// execute the logic if the size of the account list is greater than zero
if(listOfAccounts.size() > 0){
//your logic
}
L'extrait de code ci-dessus interroge la base de données pour récupérer les enregistrements de comptes et vérifie la taille de la liste.
Déclaration DML
DML signifie Data Manipulation Language (langage de manipulation de données). Les instructions DML servent à manipuler les données dans la base de données Salesforce. Par exemple :
Account acc = new Account(Name = 'Test Account'); insert acc; //DML statement to create account record.
Spécificateurs d'accès Apex
Voici les spécificateurs d'accès pris en charge par Apex :
Public mode
Ce spécificateur d'accès permet d'accéder à une classe, une méthode ou une variable utilisable par Apex au sein d'un espace de noms.
Privé mode
Ce spécificateur d'accès autorise l'utilisation locale d'une classe, d'une méthode ou d'une variable, c'est-à-dire au sein de la section de code où elle est définie. Toutes les méthodes et variables sans spécificateur d'accès défini adoptent le spécificateur d'accès par défaut « private ».
Protégé
Ce spécificateur d'accès permet d'accéder à une méthode ou à une variable utilisable par toutes les classes internes de la classe Apex définissante.
Importation
Ce spécificateur d'accès permet à Apex d'accéder à une classe, une méthode ou une variable, aussi bien à l'intérieur qu'à l'extérieur d'un espace de noms. Il est recommandé de n'utiliser le mot-clé global qu'en cas de nécessité.
Mots-clés dans Apex
Avec partage
Si une classe est définie avec ce mot-clé, toutes les règles de partage applicables à l'utilisateur actuel sont appliquées. En l'absence de ce mot-clé, le code s'exécute dans le contexte système.
Par exemple :
public with sharing class MyApexClass{
// sharing rules enforced when code in this class executes
}
Sans partage
Si une classe est définie avec ce mot-clé, les règles de partage applicables à l'utilisateur actuel ne sont pas appliquées.
Par exemple :
public without sharing class MyApexClass{
// sharing rules are not enforced when code in this class executes
}
Statique
Une variable ou une méthode définie avec le mot-clé `static` est initialisée une seule fois et associée à la classe. Les variables et méthodes statiques peuvent être appelées directement par le nom de la classe sans qu'il soit nécessaire de créer une instance de celle-ci.
Final
Une constante ou une méthode définie avec le mot-clé final ne peut pas être redéfinie. Par exemple :
public class myCls {
static final Integer INT_CONST = 10;
}
Si vous tentez de modifier la valeur de cette variable INT_CONST, vous obtiendrez l'exception suivante : System.FinalException : La variable finale a déjà été initialisée.
Retour
Ce mot-clé renvoie une valeur d'une méthode. Par exemple:
public String getName() {
return 'Test';
}
Null
Elle définit une constante nulle et peut être affectée à une variable. Par exemple :
Boolean b = null;
Salle de conférence virtuelle
Si une classe est définie avec le mot-clé virtual, elle peut être étendue et surchargée.
Abstract
Si une classe est définie avec l'abstracSi le mot-clé est t, il doit contenir au moins une méthode avec le mot-clé abstracet cette méthode ne devrait avoir qu'une signature.
Par exemple :
public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}
Chaîne Apex
Une chaîne de caractères est un ensemble de caractères sans limite de longueur. Par exemple :
String name = 'Test';
La classe String de Salesforce propose plusieurs méthodes intégrées. Voici quelques méthodes fréquemment utilisées :
abréger (maxWidth)
Cette méthode tronque une chaîne de caractères à la longueur spécifiée et la renvoie si sa longueur est supérieure ; sinon, elle renvoie la chaîne originale. Si la valeur de la variable maxWidth est inférieure à 4, cette méthode lève une exception d'exécution : System.StringException : La largeur minimale d'une abréviation est de 4.
Par exemple :
String s = 'Hello World';
String s2 = s.abbreviate(8);
System.debug('s2: ' + s2); //Hello...
capitaliser()
Cette méthode convertit la première lettre d'une chaîne en casse du titre et la renvoie.
Par exemple :
String s = 'hello';
String s2 = s.capitalize();
System.assertEquals('Hello', s2);
contient (sous-chaîne)
Cette méthode renvoie la valeur « vrai » si la chaîne appelant la méthode contient la sous-chaîne spécifiée.
String name1 = 'test1';
String name2 = 'test';
Boolean flag = name1.contains(name2);
System.debug('flag:: ' + flag); //true
est égal à (chaîneOuId)
Cette méthode renvoie vrai si le paramètre passé n'est pas nul et représente la même séquence binaire de caractères que la chaîne qui appelle la méthode.
Lors de la comparaison des identifiants, leurs longueurs peuvent différer. Par exemple, si une chaîne de caractères représentant un identifiant de 15 caractères est comparée à un objet représentant un identifiant de 18 caractères, cette méthode renvoie tout de même la valeur « vrai ». Par exemple :
String stringValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result = stringValue15.equals(idValue18);
System.debug('result: ' + result); //true
Dans l'exemple ci-dessus, la méthode equals compare un identifiant d'objet de 15 caractères avec un identifiant d'objet de 18 caractères, et si les deux identifiants représentent la même séquence binaire, elle renvoie vrai.
Utilisez cette méthode pour effectuer des comparaisons sensibles à la casse.
escapeSingleQuotes (stringVersEscape)
Cette méthode ajoute un caractère d'échappement (\) avant chaque guillemet simple dans une chaîne et renvoie le résultat. Elle empêche les injections SOQL lors de la création d'une requête SOQL dynamique et garantit que tous les guillemets simples sont interprétés comme des chaînes de caractères et non comme des commandes de base de données.
Par exemple :
String s = 'Hello \'Tom\''; String escapedStr = String.escapeSingleQuotes(s); System.debug(escapedStr); // Outputs Hello \'Tom\'
supprimer (sous-chaîne)
Cette méthode supprime toutes les occurrences de la sous-chaîne mentionnée de la chaîne qui appelle la méthode et renvoie la chaîne résultante.
Par exemple :
String s1 = 'Salesforce and force.com';
String s2 = s1.remove('force');
System.debug('s2: ' + s2); // 'Sales and .com'
sous-chaîne (indexdébut)
Cette méthode renvoie une sous-chaîne qui commence au caractère situé à l'index de départ et s'étend jusqu'à la fin de la chaîne.
Par exemple :
String s1 = 'hamburger';
String s2 = s1.substring(3);
System.debug('s2: ' + s2); //burger
inverser ()
Cette méthode inverse tous les caractères d'une chaîne et la renvoie. Par exemple :
String s = 'Hello';
String s2 = s.reverse();
System.debug('s2:::: ' + s2); // olleH
trim ()
Cette méthode supprime tous les espaces blancs de début et de fin d'une chaîne de caractères et la renvoie.
valeurDe(versConvertir)
Cette méthode renvoie la représentation sous forme de chaîne de caractères de l'objet passé en paramètre.
Les chaînes de caractères, les classes et les mots-clés se combinent lorsque vous commencez à regrouper la logique en unités réutilisables, ce à quoi servent précisément les classes Apex.
Classe Apex
Une classe Apex est un modèle ou un plan à partir duquel des objets sont créés. Un objet est une instance d'une classe.
Il existe trois façons de créer des classes Apex dans Salesforce :
- Console développeur
- Visual Studio Code avec le pack d'extension Salesforce
- Page de détails de la classe Apex dans la configuration
En Apex, vous pouvez définir une classe externe, également appelée classe de niveau supérieur, et vous pouvez également définir des classes à l'intérieur d'une classe externe, appelées classes internes.
Il est obligatoire d'utiliser un modificateur d'accès tel que global ou public dans la déclaration d'une classe externe.
Il n'est pas nécessaire d'utiliser un modificateur d'accès dans la déclaration des classes internes.
Une classe Apex est définie à l'aide du mot-clé class suivi du nom de la classe.
Le mot-clé extends est utilisé pour étendre une classe existante dans une classe Apex, et le mot-clé implements est utilisé pour implémenter une interface dans une classe Apex.
Salesforce Apex ne prend pas en charge l'héritage multiple ; une classe Apex ne peut étendre qu'une seule classe Apex existante, mais peut implémenter plusieurs interfaces.
Une classe Apex peut contenir un constructeur défini par l'utilisateur. Si aucun constructeur défini par l'utilisateur n'est disponible, un constructeur par défaut est utilisé. Le code du constructeur s'exécute lors de la création d'une instance de la classe.
Syntaxe d'une classe Apex :
public class myApexClass{
// variable declaration
//constructor
public myApexClass(){
}
//methods declaration
}
Le mot-clé `new` permet de créer une instance d'une classe Apex. Voici la syntaxe pour créer une instance d'une classe Apex :
myApexClass obj = new myApexClass();
Apex Getter et Setter
Une propriété Apex est similaire à une variable Apex. Un accesseur (getter) et un mutateur (setter) sont nécessaires pour une propriété Apex. Ils permettent d'exécuter du code avant que la valeur de la propriété ne soit consultée ou modifiée. Le code de l'accesseur get s'exécute lors de la lecture de la valeur de la propriété. Le code de l'accesseur set s'exécute lors de la modification de la valeur de la propriété. Une propriété ne possédant qu'un accesseur get est considérée comme étant en lecture seule, une propriété ne possédant qu'un accesseur set est considérée comme étant en écriture seule, et une propriété possédant à la fois un accesseur get et un accesseur set est considérée comme étant en lecture-écriture. Syntaxe d'une propriété Apex :
public class myApexClass {
// Property declaration
access_modifier return_type property_name {
get {
//code
}
set{
//code
}
}
}
Ici, access_modifier est le modificateur d'accès de la propriété, return_type est le type de données de la propriété et property_name est le nom de la propriété.
Voici un exemple de propriété Apex possédant à la fois des accesseurs get et set :
public class myApex{
public String name{
get{ return name; }
set{ name = value; }
}
}
Ici, la propriété s'appelle « name », c'est une propriété publique et elle renvoie un type de données String.
Il n'est pas obligatoire d'insérer du code dans les blocs get et set. Ces blocs peuvent être laissés vides pour définir une propriété automatique. Par exemple :
public double MyReadWriteProp{ get; set; }
Les accesseurs get et set peuvent également être définis avec leurs propres modificateurs d'accès. Si un accesseur est défini avec un modificateur, celui-ci remplace le modificateur d'accès de la propriété. Par exemple :
public String name{private get; set;}// name is private for read and public for write.
Les classes définissent une logique réutilisable que vous appelez explicitement. Les déclencheurs, que nous aborderons plus loin, s'exécutent automatiquement à chaque modification d'enregistrement.
Déclencheur d'apex
Les déclencheurs Apex vous permettent d'exécuter du code Apex personnalisé avant et après l'exécution d'une opération DML.
Apex prend en charge les deux types de déclencheurs suivants :
Avant les déclencheurs : Ces déclencheurs servent à valider et à mettre à jour la valeur d'un champ avant que l'enregistrement ne soit sauvegardé dans la base de données.
Après les déclencheurs : Ces déclencheurs permettent d'accéder aux valeurs de champs (comme l'identifiant de l'enregistrement et le champ LastModifiedDate) définies par le système après la validation d'un enregistrement dans la base de données. Ces valeurs peuvent ensuite être utilisées pour modifier d'autres enregistrements. Les enregistrements déclenchés par ces déclencheurs sont en lecture seule.
Il est recommandé d'écrire des déclencheurs optimisés pour le traitement par lots. Un déclencheur optimisé pour le traitement par lots peut traiter un seul enregistrement ou plusieurs enregistrements simultanément.
Syntaxe d'un déclencheur Apex :
trigger TriggerName on ObjectName (trigger_events) {
//Code_block
}
Ici, TriggerName est le nom du déclencheur, ObjectName est le nom de l'objet sur lequel le déclencheur est écrit, et trigger_events est une liste d'événements séparés par des virgules.
Voici les événements pris en charge par les déclencheurs Apex : avant insertion, avant mise à jour, avant suppression, après insertion, après mise à jour, après suppression, après restauration.
Les mots clés statiques ne peuvent pas être utilisés dans un déclencheur Apex. Tous les mots clés applicables aux classes internes peuvent être utilisés dans un déclencheur Apex.
Chaque déclencheur définit des variables implicites qui renvoient le contexte d'exécution. Ces variables, définies dans la classe System.Trigger, sont appelées variables de contexte. Les deux captures d'écran ci-dessous présentent les variables de contexte prises en charge par les déclencheurs Apex :
Voici les points à prendre en compte concernant les variables de contexte dans les déclencheurs Apex :
- N'utilisez pas trigger.new et trigger.old dans les opérations DML.
- Trigger.new ne peut pas être supprimé.
- Trigger.new est en lecture seule après le déclenchement.
- Trigger.new peut être utilisé pour modifier les valeurs des champs du même objet uniquement dans les déclencheurs précédents.
Les deux captures d'écran ci-dessous répertorient les points à prendre en compte concernant des actions spécifiques dans différents événements déclencheurs :
Les déclencheurs gèrent la logique en temps réel, mais certaines tâches sont tout simplement trop volumineuses pour une seule transaction. C'est là qu'intervient le traitement par lots Apex.
Classe par lots dans Apex
Dans Salesforce, une classe de traitement par lots permet de traiter un grand nombre d'enregistrements dont le traitement normal dépasserait les limites de gouvernance d'Apex. Cette classe exécute le code de manière asynchrone.
Voici les avantages d'un cours par lots :
- Une classe de traitement par lots traite les données par blocs, et si un bloc ne peut être traité correctement, les blocs traités avec succès ne sont pas annulés.
- Chaque bloc de données d'une classe de traitement par lots est traité avec un nouvel ensemble de limites de gouvernance, ce qui garantit que le code s'exécute dans les limites d'exécution de la gouvernance.
L'interface Database.Batchable doit être implémentée par une classe Apex pour être utilisée comme classe de traitement par lots. Elle fournit trois méthodes qui doivent être implémentées par la classe de traitement par lots :
1. démarrer()
Cette méthode définit le périmètre des enregistrements ou objets à traiter par la méthode `execute` de l'interface. Elle est appelée une seule fois lors de l'exécution du lot. Cette méthode renvoie soit un objet `Database.QueryLocator`, soit un `Iterable`. Le nombre d'enregistrements pouvant être récupérés par une requête SOQL avec un objet `Database.QueryLocator` est de 50 millions, tandis qu'avec un `Iterable`, ce nombre est limité à 50 000. Un `Iterable` est utilisé pour définir un périmètre complexe pour la classe de traitement par lots.
Syntaxe de la méthode start :
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
2. exécuter()
Cette méthode est utilisée pour traiter chaque lot de données. La méthode `execute` est appelée pour chaque lot d'enregistrements. La taille de lot par défaut est de 200 enregistrements. La méthode `execute` prend deux arguments :
Une référence à l'objet Database.BatchableContext,
Une liste d'objets sObject, telle qu'une liste , ou une liste de types paramétrés. Syntaxe de la méthode execute :
global void execute(Database.BatchableContext bc, List<P> records){}
3. terminer()
La méthode `finish` est appelée une seule fois lors de l'exécution de la classe de traitement par lots. Des opérations de post-traitement peuvent être effectuées dans cette méthode, comme l'envoi d'un courriel de confirmation. Elle est appelée lorsque tous les lots sont traités. Syntaxe de la méthode `finish` :
global void finish(Database.BatchableContext bc){}
Objet Database.BatchableContext
Chaque méthode de l'interface Database.Batchable possède une référence à un objet Database.BatchableContext.
Cet objet est utilisé pour track la progression du traitement par lots.
Voici les méthodes d'instance fournies par BatchableContext :
- getChildJobId() : Cette méthode renvoie l'ID du traitement par lots en cours.
- getJobId() : cette méthode renvoie l'ID du travail par lots.
Voici la syntaxe d'une classe par lots :
global class MyBatchClass implements Database.Batchable<sObject> {
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {
// collect the batches of records or objects to be passed to execute
}
global void execute(Database.BatchableContext bc, List<P> records){
// process each batch of records
}
global void finish(Database.BatchableContext bc){
// execute any post-processing operations
}
}
Méthode Database.executeBatch
La méthode Database.executeBatch est utilisée pour exécuter une classe de traitement par lots.
Cette méthode prend deux paramètres : une instance de la classe de traitement par lots et un paramètre de portée optionnel permettant de spécifier la taille du lot. Si ce dernier n’est pas spécifié, la taille par défaut de 200 est utilisée.
Syntaxe de Database.executeBatch :
Database.executeBatch(myBatchObject, scope)
Exécution d'une classe par lots nommée MyBatchClass :
MyBatchClass myBatchObject = new MyBatchClass(); Id batchId = Database.executeBatch(myBatchObject, 100);
Base de données.État
Une classe de traitement par lots est sans état par défaut. À chaque appel de la méthode execute, une nouvelle copie de l'objet est reçue et toutes les variables de la classe sont initialisées.
L'interface Database.Stateful est implémentée pour rendre une classe batch avec état.
Si votre classe de traitement par lots implémente le Base de donnéesDans une interface à état, toutes les variables d'instance conservent leurs valeurs, mais les variables statiques sont réinitialisées entre les transactions.
Apex asynchrone au-delà du traitement par lots
Batch Apex n'est qu'une des nombreuses méthodes permettant d'exécuter du code de manière asynchrone. Salesforce propose quatre options asynchrones ; le choix de la plus appropriée dépend du volume de données à traiter et de la nécessité d'enchaîner ou de planifier les tâches.
- Méthodes futures : Annotées avec @future, elles sont idéales pour les opérations simples et automatisées telles que les appels à des services web externes.
- Apex en file d'attente : Implémente l'interface Queueable, accepte des types d'objets complexes, renvoie un ID de tâche et prend en charge l'enchaînement des tâches.
- Batch Apex : Traite de très grands volumes de données par blocs, comme décrit ci-dessus.
- Apex programmé : Implémente l'interface Schedulable afin qu'une classe s'exécute à une heure précise, par exemple pour une tâche de nettoyage nocturne.
| Type | Meilleur pour | Capacité clé |
|---|---|---|
| Méthode future | Légendes simples | Feu et oubli |
| Apex en file d'attente | Traitement séquentiel | Enchaînement et suivi des tâches |
| Batch Apex | Des millions de disques | Traitement par blocs |
| Apex programmé | Emplois récurrents | Chronométrage basé sur Cron |
Quel que soit le modèle d'exécution choisi, chaque transaction est toujours mesurée par rapport aux limites de gouvernance globales de la plateforme énumérées ci-dessous.
Limites du gouverneur Apex
Les limites de gouvernance Apex sont des limitations imposées par le moteur d'exécution Apex afin d'éviter que le code et les processus Apex incontrôlés ne monopolisent les ressources partagées et ne perturbent le traitement des données par les autres utilisateurs dans l'environnement mutualisé. Ces limites sont vérifiées pour chaque transaction Apex. Voici les limites de gouvernance définies par Salesforce pour chaque transaction Apex :
| Description | Limiter |
|---|---|
| Requêtes SOQL pouvant être effectuées dans une transaction synchrone | 100 |
| Requêtes SOQL pouvant être effectuées dans une transaction asynchrone | 200 |
| Enregistrements pouvant être récupérés par une requête SOQL | 50,000 |
| Enregistrements pouvant être récupérés par Database.getQueryLocator | 10,000 |
| Requêtes SOSL pouvant être effectuées dans une transaction Apex | 20 |
| Enregistrements pouvant être récupérés par une requête SOSL | 2,000 |
| Instructions DML pouvant être exécutées dans une transaction Apex | 150 |
| Enregistrements pouvant être traités à la suite d'une instruction DML, Approval.process ou database.emptyRecycleBin | 10,000 |
| Appels pouvant être effectués dans une transaction Apex | 100 |
| Limite de délai d'expiration cumulée pour tous les appels sortants effectués dans une transaction Apex | 120 secondes |
| Limite du nombre de tâches Apex pouvant être ajoutées à la file d'attente avec System.enqueueJob | 50 |
| Délai d'exécution pour chaque transaction Apex | 10 minutes |
| Limite du nombre de caractères utilisables dans une classe Apex et déclencheur | 1 millions |
| Limite de temps CPU pour une transaction synchrone | Millisecondes 10,000 |
| Limite de temps CPU pour une transaction asynchrone | Millisecondes 60,000 |
| Taille totale du tas | 6 Mo (synchrone) / 12 Mo (asynchrone) |
Comment écrire une classe de test en Apex
Salesforce exige qu'au moins 75 % de votre code Apex soit couvert par des tests unitaires avant son déploiement en production, et chaque déclencheur doit être partiellement couvert. L'écriture de classes de test est donc une compétence fondamentale en Apex, et non une option.
Une classe de test est annotée avec `@isTest`, et chaque méthode de test l'est également. Les méthodes de test n'enregistrent aucune donnée dans la base de données et n'ont pas accès à la plupart des données existantes de l'organisation ; chaque test crée donc ses propres enregistrements. Les méthodes `Test.startTest()` et `Test.stopTest()` réinitialisent les limites de ressources du code testé, et des assertions vérifient que la logique s'est comportée comme prévu.
Voici une classe de test simple pour la logique de création de compte :
@isTest
private class AccountHandlerTest {
@isTest
static void testCreateAccount() {
Account acc = new Account(Name = 'Test Account');
Test.startTest();
insert acc;
Test.stopTest();
Account result = [SELECT Id, Name FROM Account WHERE Id = :acc.Id];
System.assertEquals('Test Account', result.Name);
}
}
Suivez ces consignes lors de la rédaction des tests :
- Utilisez la méthode @testSetup pour créer une seule fois des données de test partagées pour toutes les méthodes de test de la classe.
- Testez le comportement par lots en insérant 200 enregistrements, et non un seul.
- Couvrir les scénarios positifs, négatifs et à utilisateurs restreints.
- Incluez toujours des instructions System.assert pertinentes ; une couverture sans assertions ne prouve rien.
Meilleures pratiques d'excellence
Les débutants écrivent souvent du code Apex qui fonctionne pour un seul enregistrement, mais qui échoue lors d'opérations en masse. Les bonnes pratiques ci-dessous permettent de respecter les limites de ressources et facilitent la maintenance du code :
- Tout mettre en vrac : Écrivez une logique qui gère les collections d'enregistrements, car les déclencheurs peuvent recevoir jusqu'à 200 enregistrements dans un seul lot.
- Évitez d'utiliser SOQL et DML dans les boucles : Effectuer une requête avant la boucle, collecter les modifications dans une liste et exécuter une instruction DML après la boucle.
- Un déclencheur par objet : Veillez à ce que les déclencheurs ne contiennent aucune logique et déléguez le travail aux classes de gestionnaires, ce qui rend l'ordre d'exécution prévisible.
- Utilisation avec partage : Appliquer une sécurité au niveau de l'enregistrement, sauf s'il existe une raison documentée d'exécuter le programme dans le contexte du système.
- Évitez d'intégrer les identifiants en dur : Les identifiants d'enregistrement diffèrent entre les environnements de test et de production ; il est donc conseillé de les rechercher ou d'utiliser des métadonnées personnalisées.
- Limites de surveillance dans le code : Les méthodes de la classe Limits, telles que Limits.getQueries(), vous permettent de vérifier la consommation des ressources lors de l'exécution.
💡 Astuce: Testez votre code sur 200 enregistrements dans un environnement de test avant le déploiement. La plupart des dépassements de limites de gouvernance n'apparaissent qu'avec des volumes importants de données ; les détecter au plus tôt est bien moins coûteux que de les déboguer en production.







