Tutorial di Salesforce Apex per principianti
⚡ Riepilogo intelligente
La programmazione Apex offre agli sviluppatori Salesforce un linguaggio orientato agli oggetti e fortemente tipizzato per aggiungere logica di business personalizzata al CRM. Consente di utilizzare classi, trigger e processi batch, mentre i limiti imposti dal governor mantengono stabile la piattaforma multi-tenant condivisa.

Cos'è Apex in Salesforce?
Apex Apex è un linguaggio di programmazione orientato agli oggetti e fortemente tipizzato, sviluppato da Salesforce per la creazione di applicazioni Software as a Service (SaaS) e Customer Relationship Management (CRM). Apex aiuta gli sviluppatori a creare applicazioni SaaS di terze parti e ad aggiungere logica di business agli eventi di sistema, fornendo supporto per database back-end e interfacce client-server.
Apex aiuta gli sviluppatori ad aggiungere la logica di business agli eventi di sistema come i clic sui pulsanti, gli aggiornamenti dei record correlati e le pagine Visualforce. Apex ha una sintassi simile a Java. Registrati a Salesforce per imparare come funziona il CRM.
Caratteristiche del linguaggio di programmazione Apex
Ecco le caratteristiche importanti di Salesforce Apex:
- Apex è un linguaggio che non distingue tra maiuscole e minuscole.
- Tramite Apex è possibile eseguire operazioni DML come INSERT, UPDATE, UPSERT e DELETE sui record sObject.
- In Apex è possibile interrogare i record sObject utilizzando SOQL (Salesforce Object Query Language) e SOSL (Salesforce Object Search Language).
- Ti permette di creare un test unitario e eseguirlo per verificare il copertura del codice e l'efficienza del codice in Apex.
- Apex viene eseguito in un ambiente multi-tenant e Salesforce Salesforce ha definito dei limiti di governor che impediscono a un utente di monopolizzare le risorse condivise. Qualsiasi codice che superi un limite di governor di Salesforce fallisce e viene visualizzato un errore.
- Un oggetto Salesforce può essere utilizzato come tipo di dati in Apex. Ad esempio:
Account acc = new Account();
In questo contesto, Account è un oggetto standard di Salesforce.
- Apex si aggiorna automaticamente con ogni versione di Salesforce.
Quando uno sviluppatore dovrebbe scegliere Apex?
Il codice Apex dovrebbe essere scritto solo se uno scenario aziendale è troppo complesso per essere implementato utilizzando le funzionalità predefinite "punta e clicca" fornite da Salesforce.
Di seguito sono riportati alcuni scenari in cui è necessario scrivere codice Apex:
- Per creare servizi web che integrino Salesforce con altre applicazioni.
- Per implementare la convalida personalizzata sugli sObject.
- Per eseguire una logica Apex personalizzata quando viene effettuata un'operazione DML.
- Per implementare funzionalità che non possono essere create con gli strumenti di automazione dichiarativa esistenti come Flow.
- Impostare servizi di posta elettronica che elaborano il contenuto, le intestazioni e gli allegati delle email in arrivo.
Una volta capito quando Apex è la scelta giusta, il passo successivo è comprendere cosa succede al codice dopo averlo salvato.
Struttura operativa di Apex
Di seguito è riportato il flusso di azioni per il codice Apex:
- Azione per gli sviluppatori: Quando lo sviluppatore salva il codice sulla piattaforma, tutto il codice Apex viene compilato in un insieme di istruzioni comprensibili all'interprete runtime di Apex, e queste istruzioni vengono quindi salvate come metadati sulla piattaforma.
- Azione dell'utente finale: Quando un evento utente esegue codice Apex, il server della piattaforma recupera le istruzioni compilate dai metadati e le esegue tramite l'interprete Apex prima di restituire il risultato.
Il diagramma seguente mostra come le azioni dello sviluppatore e dell'utente finale interagiscono con il server delle applicazioni di Lightning Platform:
Ambiente di sviluppo Apex
Il codice Apex può essere sviluppato sia in un ambiente sandbox che in un'organizzazione Developer Edition di Salesforce.
La prassi consigliata è quella di sviluppare il codice in un ambiente sandbox e poi distribuirlo nell'ambiente di produzione, come illustrato di seguito:
Strumenti per lo sviluppo di codice Apex: Di seguito sono elencati i tre strumenti disponibili per lo sviluppo di codice Apex in tutte le edizioni di Salesforce:
- Console per gli sviluppatori
- Visual Studio Code con il Salesforce Extension Pack (che sostituisce il Force.com IDE, ora non più supportato)
- Code editor nell'interfaccia utente di configurazione di Salesforce
Ora che il tuo ambiente è pronto, esaminiamo gli elementi costitutivi del linguaggio stesso, a partire dai tipi di dati.
Tipi di dati in Apex
Di seguito sono elencati i tipi di dati supportati da Apex:
Primitivo
Numero intero, DoubleLong, Date, Datetime, Decimal, Time, Blob, String, ID e Boolean sono considerati tipi di dati primitivi. Tutti i tipi di dati primitivi vengono passati per valore, non per riferimento.
Collezioni
In Apex sono disponibili tre tipi di collezioni:
- Lista: Si tratta di una collezione ordinata di primitive, sObject, collezioni o oggetti Apex basata su indici.
- Set: Una collezione non ordinata di elementi unici che non contiene duplicati.
- Carta geografica: Si tratta di una raccolta di chiavi univoche che corrispondono a singoli valori, che possono essere tipi primitivi, sObject, collezioni o oggetti Apex.
sOggetto
Questo è un tipo di dati speciale in Salesforce. È simile a un tavolo in SQL e contiene campi simili alle colonne in SQL.
Enums
Un Enum è un assolutotracTipo di dati t che memorizza un valore di un insieme finito di identificatori specificati.
Classi, oggetti e interfacce
Anche le classi e le interfacce Apex definite dall'utente possono essere utilizzate come tipi di dati. Un oggetto si riferisce a un'istanza di qualsiasi tipo di dati supportato in Apex.
Sintassi dell'apice
Dichiarazione di variabili
Dato che Apex è un linguaggio fortemente tipizzato, è obbligatorio dichiarare una variabile con un tipo di dati in Apex.
Per esempio:
Contact con = new Contact();
Qui la variabile con viene dichiarata con Contact come tipo di dati.
Domanda SOQL
SOQL è l'acronimo di Salesforce Object Query Language. SOQL viene utilizzato per recuperare record sObject dal database di Salesforce. Ad esempio:
Account acc = [SELECT Id, Name FROM Account LIMIT 1];
La query sopra riportata recupera un record di account dal database di Salesforce.
Dichiarazione del ciclo
Un'istruzione di ciclo viene utilizzata per iterare sui record di una lista. Il numero di iterazioni è pari al numero di record nella lista. Ad esempio:
List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
//your logic
}
Nel frammento di codice sopra riportato, listOfAccounts è una variabile di tipo List.
Dichiarazione di controllo del flusso
Un'istruzione di controllo del flusso è utile quando si desidera eseguire alcune righe di codice in base a determinate condizioni.
Per esempio:
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
}
Il frammento di codice sopra riportato interroga i record degli account dal database e verifica la dimensione dell'elenco.
Dichiarazione DML
DML è l'acronimo di Data Manipulation Language (Linguaggio di Manipolazione dei Dati). Le istruzioni DML vengono utilizzate per manipolare i dati nel database di Salesforce. Ad esempio:
Account acc = new Account(Name = 'Test Account'); insert acc; //DML statement to create account record.
Specificatori di accesso Apex
Di seguito sono elencati gli specificatori di accesso supportati da Apex:
Pubblico
Questo specificatore di accesso consente di accedere a una classe, un metodo o una variabile da utilizzare da parte di Apex all'interno di un namespace.
Privata
Questo specificatore di accesso consente di accedere a una classe, un metodo o una variabile da utilizzare localmente, ovvero all'interno della sezione di codice in cui è definita. Tutti i metodi e le variabili che non hanno uno specificatore di accesso definito assumono lo specificatore di accesso predefinito "private".
Protetta
Questo specificatore di accesso consente l'accesso a un metodo o a una variabile da utilizzare da parte di qualsiasi classe interna all'interno della classe Apex che lo definisce.
Global
Questo specificatore di accesso consente ad Apex di accedere a una classe, un metodo o una variabile sia all'interno che all'esterno di un namespace. È buona norma non utilizzare la parola chiave `global` se non strettamente necessario.
Parole chiave in Apex
Con condivisione
Se una classe è definita con questa parola chiave, vengono applicate tutte le regole di condivisione che si applicano all'utente corrente. Se questa parola chiave è assente, il codice viene eseguito nel contesto di sistema.
Per esempio:
public with sharing class MyApexClass{
// sharing rules enforced when code in this class executes
}
Senza condivisione
Se una classe viene definita con questa parola chiave, le regole di condivisione applicabili all'utente corrente non vengono applicate.
Per esempio:
public without sharing class MyApexClass{
// sharing rules are not enforced when code in this class executes
}
statica
Una variabile o un metodo definito con la parola chiave `static` viene inizializzato una sola volta e associato alla classe. Le variabili e i metodi statici possono essere richiamati direttamente tramite il nome della classe, senza la necessità di crearne un'istanza.
fine
Una costante o un metodo definiti con la parola chiave final non possono essere sovrascritti. Ad esempio:
public class myCls {
static final Integer INT_CONST = 10;
}
Se si tenta di sovrascrivere il valore di questa variabile INT_CONST, verrà generata l'eccezione System.FinalException: La variabile Final è già stata inizializzata.
Rientro
Questa parola chiave restituisce un valore da un metodo. Per esempio:
public String getName() {
return 'Test';
}
Nullo
Definisce una costante nulla e può essere assegnata a una variabile. Ad esempio:
Boolean b = null;
Virtuale
Se una classe è definita con la parola chiave `virtual`, può essere estesa e sovrascritta.
Astratto
Se una classe è definita con l'abstracparola chiave t, deve contenere almeno un metodo con la parola chiave abstract, e quel metodo dovrebbe avere solo una firma.
Per esempio:
public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}
Corda apicale
Una stringa è un insieme di caratteri senza limiti di caratteri. Ad esempio:
String name = 'Test';
In Salesforce, la classe String offre diversi metodi integrati. Di seguito ne elenchiamo alcuni tra i più utilizzati:
abbreviare(larghezzamax)
Questo metodo tronca una stringa alla lunghezza specificata e la restituisce se la lunghezza della stringa data è maggiore della lunghezza specificata; altrimenti, restituisce la stringa originale. Se il valore della variabile maxWidth è inferiore a 4, questo metodo genera un'eccezione di runtime: System.StringException: La larghezza minima dell'abbreviazione è 4.
Per esempio:
String s = 'Hello World';
String s2 = s.abbreviate(8);
System.debug('s2: ' + s2); //Hello...
capitalizzare()
Questo metodo converte la prima lettera di una stringa nel titolo e la restituisce.
Per esempio:
String s = 'hello';
String s2 = s.capitalize();
System.assertEquals('Hello', s2);
contiene(sottostringa)
Questo metodo restituisce true se la stringa che lo chiama contiene la sottostringa specificata.
String name1 = 'test1';
String name2 = 'test';
Boolean flag = name1.contains(name2);
System.debug('flag:: ' + flag); //true
è uguale a(stringOrId)
Questo metodo restituisce true se il parametro passato non è nullo e rappresenta la stessa sequenza binaria di caratteri della stringa che chiama il metodo.
Quando si confrontano i valori ID, la lunghezza degli ID potrebbe non essere uguale. Ad esempio, se una stringa che rappresenta un ID di 15 caratteri viene confrontata con un oggetto che rappresenta un ID di 18 caratteri, questo metodo restituisce comunque true. Ad esempio:
String stringValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result = stringValue15.equals(idValue18);
System.debug('result: ' + result); //true
Nell'esempio precedente, il metodo equals confronta un ID oggetto di 15 caratteri con un ID oggetto di 18 caratteri e, se entrambi gli ID rappresentano la stessa sequenza binaria, restituisce true.
Utilizzare questo metodo per effettuare confronti con distinzione tra maiuscole e minuscole.
escapeSingleQuotes(stringToEscape)
Questo metodo aggiunge un carattere di escape (\) prima di ogni virgoletta singola in una stringa e restituisce il risultato. Questo metodo previene l'iniezione SOQL durante la creazione di una query SOQL dinamica. Garantisce che tutte le virgolette singole vengano trattate come stringhe di contenimento anziché come comandi del database.
Per esempio:
String s = 'Hello \'Tom\''; String escapedStr = String.escapeSingleQuotes(s); System.debug(escapedStr); // Outputs Hello \'Tom\'
rimuovi(sottostringa)
Questo metodo rimuove tutte le occorrenze della sottostringa menzionata dalla stringa che chiama il metodo e restituisce la stringa risultante.
Per esempio:
String s1 = 'Salesforce and force.com';
String s2 = s1.remove('force');
System.debug('s2: ' + s2); // 'Sales and .com'
sottostringa(indiceiniziale)
Questo metodo restituisce una sottostringa che inizia dal carattere specificato da startIndex e si estende fino alla fine della stringa.
Per esempio:
String s1 = 'hamburger';
String s2 = s1.substring(3);
System.debug('s2: ' + s2); //burger
inversione()
Questo metodo inverte tutti i caratteri di una stringa e la restituisce. Ad esempio:
String s = 'Hello';
String s2 = s.reverse();
System.debug('s2:::: ' + s2); // olleH
trim ()
Questo metodo rimuove tutti gli spazi bianchi iniziali e finali da una stringa e la restituisce.
valoreOf(toConvert)
Questo metodo restituisce la rappresentazione in stringa dell'oggetto passato come parametro.
Stringhe, classi e parole chiave si uniscono quando si inizia a raggruppare la logica in unità riutilizzabili, che è esattamente lo scopo delle classi Apex.
Classe Apex
Una classe Apex è un modello o schema da cui vengono creati gli oggetti. Un oggetto è un'istanza di una classe.
Esistono tre modi per creare classi Apex in Salesforce:
- Console per gli sviluppatori
- Visual Studio Code con il pacchetto di estensioni Salesforce
- Pagina dei dettagli della classe Apex in Impostazioni
In Apex, è possibile definire una classe esterna, detta anche classe di livello superiore, e si possono anche definire classi all'interno di una classe esterna, dette classi interne.
È obbligatorio utilizzare un modificatore di accesso come global o public nella dichiarazione di una classe esterna.
Non è necessario utilizzare un modificatore di accesso nella dichiarazione delle classi interne.
Una classe Apex viene definita utilizzando la parola chiave `class` seguita dal nome della classe.
La parola chiave `extends` viene utilizzata per estendere una classe esistente in una classe Apex, mentre la parola chiave `implements` viene utilizzata per implementare un'interfaccia in una classe Apex.
Salesforce Apex non supporta l'ereditarietà multipla; una classe Apex può estendere una sola classe Apex esistente, ma può implementare più interfacce.
Una classe Apex può contenere un costruttore definito dall'utente e, se non è disponibile un costruttore definito dall'utente, viene utilizzato un costruttore predefinito. Il codice contenuto in un costruttore viene eseguito quando viene creata un'istanza della classe.
Sintassi di una classe Apex:
public class myApexClass{
// variable declaration
//constructor
public myApexClass(){
}
//methods declaration
}
La parola chiave `new` viene utilizzata per creare un'istanza di una classe Apex. Di seguito è riportata la sintassi per la creazione di un'istanza di una classe Apex:
myApexClass obj = new myApexClass();
Getter e Setter Apex
Una proprietà Apex è simile a una variabile Apex. Per una proprietà Apex sono necessari un metodo getter e un metodo setter. Questi possono essere utilizzati per eseguire del codice prima che il valore della proprietà venga acceduto o modificato. Il codice nel metodo get viene eseguito quando viene letto il valore di una proprietà. Il codice nel metodo set viene eseguito quando il valore di una proprietà viene modificato. Qualsiasi proprietà che abbia solo un metodo get è considerata di sola lettura, qualsiasi proprietà che abbia solo un metodo set è considerata di sola scrittura e qualsiasi proprietà che abbia entrambi i metodi get e set è considerata di lettura/scrittura. Sintassi di una proprietà Apex:
public class myApexClass {
// Property declaration
access_modifier return_type property_name {
get {
//code
}
set{
//code
}
}
}
Qui, access_modifier è il modificatore di accesso della proprietà, return_type è il tipo di dati della proprietà e property_name è il nome della proprietà.
Di seguito è riportato un esempio di proprietà Apex che dispone sia di metodi di accesso get che set:
public class myApex{
public String name{
get{ return name; }
set{ name = value; }
}
}
Qui, il nome della proprietà è name, è una proprietà pubblica e restituisce un tipo di dati String.
Non è obbligatorio inserire del codice nei blocchi get e set. Questi blocchi possono essere lasciati vuoti per definire una proprietà automatica. Ad esempio:
public double MyReadWriteProp{ get; set; }
Gli accessor get e set possono essere definiti anche con i propri modificatori di accesso. Se un accessor è definito con un modificatore, questo sovrascrive il modificatore di accesso della proprietà. Ad esempio:
public String name{private get; set;}// name is private for read and public for write.
Le classi definiscono una logica riutilizzabile che viene richiamata esplicitamente. I trigger, che tratteremo in seguito, vengono eseguiti automaticamente ogni volta che i record vengono modificati.
Trigger dell'apice
I trigger Apex consentono di eseguire codice Apex personalizzato prima e dopo l'esecuzione di un'operazione DML.
Apex supporta i seguenti due tipi di trigger:
Prima dell'attivazione: Questi trigger vengono utilizzati per convalidare e aggiornare il valore di un campo prima che il record venga salvato nel database.
Dopo gli eventi scatenanti: Questi trigger vengono utilizzati per accedere ai valori dei campi (come l'ID del record e il campo LastModifiedDate) che vengono impostati dal sistema dopo che un record è stato salvato nel database. Questi valori di campo possono essere utilizzati per modificare altri record. I record che si attivano a seguito di un trigger sono di sola lettura.
È buona norma scrivere trigger di tipo bulkified. Un trigger bulkified può elaborare un singolo record o più record contemporaneamente.
Sintassi di un trigger Apex:
trigger TriggerName on ObjectName (trigger_events) {
//Code_block
}
Qui, TriggerName è il nome del trigger, ObjectName è il nome dell'oggetto su cui è scritto il trigger e trigger_events è un elenco di eventi separati da virgole.
Di seguito sono elencati gli eventi supportati dai trigger Apex: before insert, before update, before delete, after insert, after update, after delete, after undelete.
Le parole chiave statiche non possono essere utilizzate in un trigger Apex. Tutte le parole chiave applicabili alle classi interne possono essere utilizzate in un trigger Apex.
Ogni trigger definisce delle variabili implicite che restituiscono il contesto di runtime. Queste variabili sono definite nella classe System.Trigger e sono chiamate variabili di contesto. Le due schermate seguenti mostrano le variabili di contesto supportate dai trigger Apex:
Di seguito sono riportate le considerazioni relative alle variabili di contesto nei trigger Apex:
- Non utilizzare trigger.new e trigger.old nelle operazioni DML.
- Trigger.new non può essere eliminato.
- Trigger.new è di sola lettura nei trigger successivi.
- Trigger.new può essere utilizzato per modificare i valori dei campi sullo stesso oggetto solo prima dei trigger.
Le due schermate seguenti elencano le considerazioni relative ad azioni specifiche in diversi eventi di attivazione:
I trigger gestiscono la logica in tempo reale, ma alcuni processi sono semplicemente troppo complessi per una singola transazione. È qui che entra in gioco Apex in modalità batch.
Classe batch in Apex
In Salesforce, una classe batch viene utilizzata per elaborare un numero elevato di record che, se elaborati normalmente, supererebbero i limiti imposti dal governor Apex. Una classe batch esegue il codice in modo asincrono.
Di seguito sono elencati i vantaggi di una lezione in batch:
- Una classe batch elabora i dati a blocchi e, se un blocco non viene elaborato correttamente, i blocchi elaborati con successo non vengono annullati.
- Ogni blocco di dati in una classe batch viene elaborato con un nuovo set di limiti del governor, il che garantisce che il codice venga eseguito entro i limiti di esecuzione del governor.
L'interfaccia Database.Batchable deve essere implementata da una classe Apex per poter essere utilizzata come classe batch. Essa fornisce tre metodi che devono essere implementati dalla classe batch:
1. inizio()
Questo metodo genera l'ambito di record o oggetti da elaborare tramite il metodo execute dell'interfaccia. Viene chiamato una sola volta durante l'esecuzione del batch. Questo metodo restituisce un oggetto Database.QueryLocator o un Iterable. Il numero di record recuperabili tramite una query SOQL utilizzando l'oggetto Database.QueryLocator è di 50 milioni, mentre utilizzando un Iterable, il numero totale di record recuperabili tramite la query SOQL è di soli 50,000. Un Iterable viene utilizzato per generare un ambito complesso per la classe batch.
Sintassi del metodo start:
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
2. esegui()
Questo metodo viene utilizzato per elaborare ciascun blocco di dati. Il metodo execute viene chiamato per ogni blocco di record. La dimensione predefinita del batch per l'esecuzione è di 200 record. Il metodo execute accetta due argomenti:
Un riferimento all'oggetto Database.BatchableContext,
Un elenco di sObject, come List , oppure un elenco di tipi parametrizzati. Sintassi del metodo execute:
global void execute(Database.BatchableContext bc, List<P> records){}
3. fine()
Il metodo finish viene chiamato una sola volta durante l'esecuzione della classe batch. Nel metodo finish è possibile eseguire operazioni di post-elaborazione, ad esempio l'invio di un'e-mail di conferma. Questo metodo viene chiamato al termine dell'elaborazione di tutti i batch. Sintassi del metodo finish:
global void finish(Database.BatchableContext bc){}
Oggetto Database.BatchableContext
Ciascun metodo dell'interfaccia Database.Batchable ha un riferimento a un oggetto Database.BatchableContext.
Questo oggetto viene utilizzato per track l'avanzamento del processo batch.
Di seguito sono riportati i metodi di istanza forniti da BatchableContext:
- getChildJobId(): Questo metodo restituisce l'ID del job batch attualmente in fase di elaborazione.
- getJobId(): questo metodo restituisce l'ID del lavoro batch.
Di seguito è riportata la sintassi di una classe batch:
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
}
}
Metodo Database.executeBatch
Il metodo Database.executeBatch viene utilizzato per eseguire una classe batch.
Questo metodo accetta due parametri: un'istanza della classe batch da elaborare e un parametro di ambito opzionale per specificare la dimensione del batch. Se non specificato, viene utilizzata la dimensione predefinita di 200.
Sintassi di Database.executeBatch:
Database.executeBatch(myBatchObject, scope)
Esecuzione di una classe batch denominata MyBatchClass:
MyBatchClass myBatchObject = new MyBatchClass(); Id batchId = Database.executeBatch(myBatchObject, 100);
Database con stato
Una classe batch è senza stato per impostazione predefinita. Ogni volta che viene chiamato il metodo execute, viene ricevuta una nuova copia dell'oggetto e tutte le variabili della classe vengono inizializzate.
Database.Stateful è implementato per rendere una classe batch con stato.
Se la tua classe batch implementa l' Banca Dati.Interfaccia con stato: tutte le variabili di istanza mantengono i loro valori, mentre le variabili statiche vengono reimpostate tra una transazione e l'altra.
Apex asincrono oltre il batch
Batch Apex è solo uno dei diversi modi per eseguire codice in modo asincrono. Salesforce offre quattro opzioni asincrone e la scelta di quella più adatta dipende dalla quantità di dati da elaborare e dalla necessità di concatenare o pianificare le attività.
- Metodi futuri: Contrassegnati con @future, questi sono ideali per operazioni semplici e immediate, come le chiamate a servizi web esterni.
- Apex in coda: Implementa l'interfaccia Queueable, accetta tipi di oggetti complessi, restituisce un ID di lavoro e supporta il concatenamento di un lavoro all'altro.
- Batch Apex: Elabora volumi di dati molto grandi in blocchi, come descritto in precedenza.
- Apex programmato: Implementa l'interfaccia Schedulable in modo che una classe venga eseguita a un orario specifico, ad esempio un'attività di pulizia notturna.
| Tipo | migliori Per | Capacità chiave |
|---|---|---|
| Metodo futuro | Semplici chiamate | Fai fuoco e dimentica |
| Apex in coda | Elaborazione sequenziale | Concatenamento e monitoraggio dei lavori |
| Batch Apex | Milioni di record | Elaborazione a blocchi |
| Apex programmato | Lavori ricorrenti | Temporizzazione basata su Cron |
Indipendentemente dal modello di esecuzione scelto, ogni transazione viene comunque misurata rispetto ai limiti imposti dalla piattaforma, elencati di seguito.
Limiti del governatore Apex
I limiti imposti dal motore di runtime Apex per garantire che eventuali codici e processi Apex non gestiti correttamente non monopolizzino le risorse condivise e non interrompano l'elaborazione degli altri utenti nell'ambiente multi-tenant. Questi limiti vengono verificati per ogni transazione Apex. Di seguito sono riportati i limiti definiti da Salesforce per ogni transazione Apex:
| Descrizione | Limitare |
|---|---|
| Query SOQL che possono essere eseguite in una transazione sincrona | 100 |
| Query SOQL che possono essere eseguite in una transazione asincrona | 200 |
| Record che possono essere recuperati da una query SOQL | 50,000 |
| Record che possono essere recuperati da Database.getQueryLocator | 10,000 |
| Query SOSL che possono essere eseguite in una transazione Apex | 20 |
| Record che possono essere recuperati da una query SOSL | 2,000 |
| Istruzioni DML che possono essere eseguite in una transazione Apex | 150 |
| Record che possono essere elaborati come risultato di un'istruzione DML, Approval.process o database.emptyRecycleBin | 10,000 |
| Chiamate che possono essere effettuate in una transazione Apex | 100 |
| Limite di timeout cumulativo per tutte le chiamate effettuate in una transazione Apex | 120 secondi |
| Limite al numero di job Apex che possono essere aggiunti alla coda con System.enqueueJob | 50 |
| Limite temporale di esecuzione per ciascuna transazione Apex | 10 minuti |
| Limite sui caratteri che possono essere utilizzati in una classe Apex e attivare | 1 milioni |
| Limite di tempo CPU per una transazione sincrona | Millisecondi 10,000 |
| Limite di tempo CPU per una transazione asincrona | Millisecondi 60,000 |
| Dimensione totale dell'hedget | 6 MB (sincrono) / 12 MB (asincrono) |
Come scrivere una classe di test in Apex
Salesforce richiede che almeno il 75% del codice Apex sia coperto da unit test prima di poterlo distribuire in produzione, e ogni trigger deve avere una qualche copertura di test. Scrivere classi di test è quindi una competenza fondamentale di Apex, non un'opzione facoltativa.
Una classe di test è annotata con @isTest, e ogni metodo di test è anch'esso contrassegnato con @isTest. I metodi di test non eseguono il commit dei dati nel database e non visualizzano la maggior parte dei dati esistenti dell'organizzazione, quindi ogni test crea i propri record. I metodi Test.startTest() e Test.stopTest() forniscono al codice da testare un nuovo set di limiti del governor, e le asserzioni verificano che la logica si sia comportata come previsto.
Ecco una semplice classe di test per la logica di creazione dell'account:
@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);
}
}
Quando si preparano i test, è necessario seguire queste linee guida:
- Utilizza il metodo @testSetup per creare una volta i dati di test condivisi per tutti i metodi di test della classe.
- Verifica il comportamento in blocco inserendo 200 record, non solo uno.
- Descrivere scenari positivi, negativi e con accesso limitato.
- È fondamentale includere sempre istruzioni System.assert significative; la copertura senza asserzioni non dimostra nulla.
Apex migliori Practices
Spesso i principianti scrivono codice Apex che funziona per un singolo record ma fallisce nelle operazioni di massa reali. Le pratiche descritte di seguito mantengono il codice entro i limiti imposti dal governor e ne facilitano la manutenzione:
- Aumentare la quantità di tutto: Scrivi una logica che gestisca le raccolte di record, poiché i trigger possono ricevere fino a 200 record in un singolo batch.
- Evitate i cicli con SOQL e DML: Eseguire una query prima del ciclo, raccogliere le modifiche in un elenco ed eseguire un'istruzione DML dopo il ciclo.
- Un trigger per ogni oggetto: Mantieni i trigger privi di logica e delega il lavoro alle classi di gestione, in modo da rendere prevedibile l'ordine di esecuzione.
- Da utilizzare con la condivisione: Applicare la sicurezza a livello di record a meno che non vi sia un motivo documentato per eseguirla nel contesto di sistema.
- Evitate di inserire ID fissi nel codice: Gli ID dei record differiscono tra gli ambienti di test e di produzione, quindi è necessario richiederli tramite query oppure utilizzare i metadati personalizzati.
- Limiti di monitoraggio nel codice: I metodi della classe Limits, come Limits.getQueries(), consentono di verificare il consumo di risorse in fase di esecuzione.
💡 Suggerimento: Prima di implementare il codice, eseguilo su 200 record in un ambiente di test. La maggior parte degli errori relativi ai limiti del governor si verifica solo con volumi elevati, e individuarli tempestivamente è molto più economico che risolverli in produzione.






