Підручник з Salesforce Apex для початківців
⚡ Розумний підсумок
Програмування Apex надає розробникам Salesforce об'єктно-орієнтовану мову строго типізованих програм для додавання власної бізнес-логіки до CRM. Вона забезпечує класи, тригери та пакетні завдання, тоді як обмеження регуляторів підтримують стабільність спільної багатокористувацької платформи.

Що таке Apex у Salesforce?
Вершина — це об'єктно-орієнтована мова програмування зі строгою типізацією, розроблена Salesforce для створення програмного забезпечення як послуги (SaaS) та програм для управління взаємовідносинами з клієнтами (CRM). Apex допомагає розробникам створювати сторонні SaaS-програми та додавати бізнес-логіку до системних подій, забезпечуючи підтримку серверних баз даних та клієнт-серверні інтерфейси.
Apex допомагає розробникам додавати бізнес-логіку до системних подій, таких як натискання кнопок, оновлення пов’язаних записів та сторінки Visualforce. Apex має синтаксис, подібний до Java. Зареєструйтеся в Salesforce щоб дізнатися, як працює CRM.
Особливості мови програмування Apex
Ось важливі функції Salesforce Apex:
- Apex — це мова, яка не враховує регістр літер.
- Ви можете виконувати операції DML, такі як INSERT, UPDATE, UPSERT та DELETE, над записами sObject за допомогою Apex.
- Ви можете запитувати записи sObject за допомогою SOQL (Salesforce Object Query Language) та SOSL (Salesforce Object Search Language) в Apex.
- Дозволяє створювати a одиничне випробування і виконайте його, щоб перевірити покриття коду та ефективність коду в Apex.
- Apex працює в середовищі з кількома клієнтами Salesforce має визначені обмеження регуляторів, які запобігають монополізуванню користувачем спільних ресурсів. Будь-який код, який перевищує обмеження регулятора Salesforce, завершується невдачею, і з'являється повідомлення про помилку.
- Об'єкт Salesforce можна використовувати як тип даних в Apex. Наприклад:
Account acc = new Account();
Тут Account – це стандартний об’єкт Salesforce.
- Apex автоматично оновлюється з кожним випуском Salesforce.
Коли розробнику варто обрати Apex?
Код Apex слід писати лише тоді, коли бізнес-сценарій занадто складний для реалізації за допомогою попередньо вбудованої функції «вкажи та клацни», що надається Salesforce.
Нижче наведено кілька сценаріїв, у яких вам потрібно написати код Apex:
- Щоб створити веб-сервіси, які інтегрують Salesforce з іншими програмами.
- Реалізувати власну валідацію на sObjects.
- Виконувати власну логіку Apex під час виконання операції DML.
- Для реалізації функціональності, яку неможливо створити за допомогою існуючих декларативних інструментів автоматизації, таких як Flow.
- Встановлювати послуги електронної пошти що обробляють вміст, заголовки та вкладення вхідної електронної пошти.
Щойно ви зрозумієте, коли Apex — правильний вибір, наступним кроком буде розуміння того, що відбувається з вашим кодом після його збереження.
Робоча структура Apex
Нижче наведено послідовність дій для коду Apex:
- Дія розробника: Коли розробник зберігає код на платформі, весь код Apex компілюється в набір інструкцій, які може зрозуміти інтерпретатор середовища виконання Apex, а потім ці інструкції зберігаються як метадані на платформі.
- Дія кінцевого користувача: Коли подія користувача виконує код Apex, сервер платформи отримує скомпільовані інструкції з метаданих та пропускає їх через інтерпретатор Apex, перш ніж повернути результат.
На діаграмі нижче показано, як дії розробника та кінцевого користувача взаємодіють із сервером застосунків Lightning Platform:
Середовище розробки Apex
Код Apex можна розробляти або в ізольованому середовищі, або в організації Salesforce Developer Edition.
Найкращою практикою є розробка коду в ізольованому середовищі, а потім розгортання його у робочому середовищі, як показано нижче:
Інструменти розробки коду Apex: Нижче наведено три інструменти, доступні для розробки коду Apex у всіх версіях Salesforce:
- Консоль розробника
- Visual Studio Code з пакетом розширень Salesforce (він замінює списану IDE Force.com)
- Code редактор у інтерфейсі користувача налаштування Salesforce
Коли ваше середовище готове, давайте розглянемо основні елементи самої мови, починаючи з типів даних.
Типи даних в Apex
Apex підтримує такі типи даних:
примітив
ціле число, Double, Long, Date, Datetime, Decimal, Time, Blob, String, ID та Boolean вважаються примітивними типами даних. Усі примітивні типи даних передаються за значенням, а не за посиланням.
Колекції
В Apex доступні три типи колекцій:
- список: Це впорядкована колекція примітивів, sObjects, колекцій або об'єктів Apex на основі індексів.
- Комплект: Невпорядкована колекція унікальних елементів, яка не містить дублікатів.
- Карта: Це колекція унікальних ключів, які відповідають окремим значенням, що можуть бути примітивами, sObjects, колекціями або об'єктами Apex.
sObject
Це особливий тип даних у Salesforce. Він схожий на таблицю в SQL і містить поля, подібні до стовпців у SQL.
Переліки
Перелік — це абсtracТип даних t, який зберігає одне значення скінченного набору заданих ідентифікаторів.
Класи, об'єкти та інтерфейси
Визначені користувачем класи та інтерфейси Apex також можуть використовуватися як типи даних. Об'єкт посилається на екземпляр будь-якого типу даних, що підтримується в Apex.
Синтаксис Apex
Декларація змінних
Оскільки Apex є строго типізованою мовою, обов'язково оголошувати змінну з типом даних в Apex.
Наприклад:
Contact con = new Contact();
Тут змінна con оголошується з типом даних Contact.
Запит SOQL
SOQL розшифровується як мова запитів об'єктів Salesforce. SOQL використовується для отримання записів sObject з бази даних Salesforce. Наприклад:
Account acc = [SELECT Id, Name FROM Account LIMIT 1];
Наведений вище запит отримує запис облікового запису з бази даних Salesforce.
Оператор циклу
Оператор циклу використовується для перебору записів у списку. Кількість ітерацій дорівнює кількості записів у списку. Наприклад:
List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
//your logic
}
У наведеному вище фрагменті коду listOfAccounts – це змінна типу даних List.
Заява про керування потоком
Оператор керування потоком корисний, коли потрібно виконати кілька рядків коду на основі певних умов.
Наприклад:
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
}
Наведений вище фрагмент коду запитує записи облікових записів з бази даних та перевіряє розмір списку.
Заява DML
DML розшифровується як мова маніпулювання даними (Data Manipulation Language). Оператори DML використовуються для маніпулювання даними в базі даних Salesforce. Наприклад:
Account acc = new Account(Name = 'Test Account'); insert acc; //DML statement to create account record.
Специфікатори доступу Apex
Нижче наведено специфікатори доступу, що підтримуються Apex:
громадськості
Цей специфікатор доступу надає доступ до класу, методу або змінної, що використовуються Apex у просторі імен.
приватний
Цей специфікатор доступу надає доступ до класу, методу або змінної, які будуть використовуватися локально або в розділі коду, де вони визначені. Усі методи та змінні, для яких не визначено специфікатор доступу, використовують специфікатор доступу за замовчуванням private.
захищений
Цей специфікатор доступу надає доступ до методу або змінної, яка буде використовуватися будь-якими внутрішніми класами в межах визначального класу Apex.
Глобальний
Цей специфікатор доступу надає доступ до класу, методу або змінної, які будуть використовуватися Apex як у просторі імен, так і поза ним. Рекомендується не використовувати ключове слово global, якщо в цьому немає необхідності.
Ключові слова в Apex
З поділом
Якщо клас визначено за допомогою цього ключового слова, то застосовуються всі правила спільного доступу, що застосовуються до поточного користувача. Якщо це ключове слово відсутнє, код виконується в системному контексті.
Наприклад:
public with sharing class MyApexClass{
// sharing rules enforced when code in this class executes
}
Не ділячись
Якщо клас визначено за допомогою цього ключового слова, то правила спільного доступу, що застосовуються до поточного користувача, не застосовуються.
Наприклад:
public without sharing class MyApexClass{
// sharing rules are not enforced when code in this class executes
}
Статичний
Змінна або метод, визначені за допомогою ключового слова static, ініціалізуються один раз та асоціюються з класом. Статичні змінні та методи можна викликати безпосередньо за іменем класу, не створюючи екземпляр класу.
Остаточний
Константу або метод, визначені за допомогою ключового слова final, не можна перевизначити. Наприклад:
public class myCls {
static final Integer INT_CONST = 10;
}
Якщо ви спробуєте перевизначити значення цієї змінної INT_CONST, ви отримаєте виняток – System.FinalException: Final variable has already been initialized.
Повернення
Це ключове слово повертає значення з методу. Наприклад:
public String getName() {
return 'Test';
}
Null
Він визначає нульову константу та може бути присвоєний змінній. Наприклад:
Boolean b = null;
Віртуальний
Якщо клас визначено за допомогою ключового слова virtual, його можна розширити та перевизначити.
Abstract
Якщо клас визначено за допомогою abstracключове слово t, воно повинно містити принаймні один метод з ключовим словом abstract, і цей метод повинен мати лише підпис.
Наприклад:
public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}
Apex String
Рядок — це набір символів без обмеження кількості символів. Наприклад:
String name = 'Test';
Клас String у Salesforce пропонує кілька вбудованих методів. Нижче наведено кілька часто використовуваних методів:
скоротити (maxWidth)
Цей метод скорочує рядок до заданої довжини та повертає її, якщо довжина заданого рядка перевищує задану довжину; в іншому випадку він повертає початковий рядок. Якщо значення змінної maxWidth менше за 4, цей метод викидає виняток під час виконання – System.StringException: Мінімальна ширина абревіатури – 4.
Наприклад:
String s = 'Hello World';
String s2 = s.abbreviate(8);
System.debug('s2: ' + s2); //Hello...
використовувати великі літери ()
Цей метод перетворює першу літеру рядка на регістр заголовка та повертає її.
Наприклад:
String s = 'hello';
String s2 = s.capitalize();
System.assertEquals('Hello', s2);
містить (підрядок)
Цей метод повертає значення true, якщо рядок, що викликає метод, містить вказаний підрядок.
String name1 = 'test1';
String name2 = 'test';
Boolean flag = name1.contains(name2);
System.debug('flag:: ' + flag); //true
дорівнює (stringOrId)
Цей метод повертає значення true, якщо переданий параметр не є null та представляє ту саму двійкову послідовність символів, що й рядок, що викликає метод.
Під час порівняння значень ідентифікаторів довжини ідентифікаторів можуть не збігатися. Наприклад, якщо рядок, який представляє 15-символьний ідентифікатор, порівнюється з об'єктом, який представляє 18-символьний ідентифікатор, цей метод все одно повертає значення true. Наприклад:
String stringValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result = stringValue15.equals(idValue18);
System.debug('result: ' + result); //true
У наведеному вище прикладі метод equals порівнює 15-символьний ідентифікатор об'єкта з 18-символьним ідентифікатором об'єкта, і якщо обидва ідентифікатори представляють одну й ту саму двійкову послідовність, він повертає значення true.
Використовуйте цей метод для порівняння з урахуванням регістру.
escapeSingleQuotes(stringToEscape)
Цей метод додає escape-символ (\) перед будь-якими одинарними лапками в рядку та повертає результат. Цей метод запобігає SOQL-ін'єкції під час створення динамічного SOQL-запиту. Він гарантує, що всі одинарні лапки обробляються як рядки, що містять їх, а не як команди бази даних.
Наприклад:
String s = 'Hello \'Tom\''; String escapedStr = String.escapeSingleQuotes(s); System.debug(escapedStr); // Outputs Hello \'Tom\'
видалити (підрядок)
Цей метод видаляє всі екземпляри згаданого підрядка з рядка, який викликає метод, та повертає результуючий рядок.
Наприклад:
String s1 = 'Salesforce and force.com';
String s2 = s1.remove('force');
System.debug('s2: ' + s2); // 'Sales and .com'
підрядок (початковий індекс)
Цей метод повертає підрядок, який починається з символу в startIndex і продовжується до кінця рядка.
Наприклад:
String s1 = 'hamburger';
String s2 = s1.substring(3);
System.debug('s2: ' + s2); //burger
зворотний()
Цей метод інвертує всі символи рядка та повертає його. Наприклад:
String s = 'Hello';
String s2 = s.reverse();
System.debug('s2:::: ' + s2); // olleH
trim ()
Цей метод видаляє всі початкові та кінцеві пробіли з рядка та повертає його.
valueOf(toConvert)
Цей метод повертає рядкове представлення переданого об'єкта.
Рядки, класи та ключові слова об'єднуються, коли ви починаєте пакувати логіку в повторно використовувані одиниці, і саме для цього існують класи Apex.
Клас Апекс
Клас Apex — це креслення або шаблон, на основі якого створюються об'єкти. Об'єкт — це екземпляр класу.
Існує три способи створення класів Apex у Salesforce:
- Консоль розробника
- Visual Studio Code з пакетом розширення Salesforce
- Сторінка деталей класу Apex у розділі налаштувань
В Apex можна визначити зовнішній клас, який також називають класом верхнього рівня, а також можна визначити класи всередині зовнішнього класу, які називаються внутрішніми класами.
Обов'язково використовувати модифікатор доступу, такий як global або public, в оголошенні зовнішнього класу.
Немає потреби використовувати модифікатор доступу в оголошенні внутрішніх класів.
Клас Apex визначається за допомогою ключового слова class, за яким слідує ім'я класу.
Ключове слово extends використовується для розширення існуючого класу в класі Apex, а ключове слово implements використовується для реалізації інтерфейсу в класі Apex.
Salesforce Apex не підтримує множинне успадкування; клас Apex може розширювати лише один існуючий клас Apex, але може реалізовувати кілька інтерфейсів.
Клас Apex може містити користувацький конструктор, а якщо користувацький конструктор недоступний, використовується конструктор за замовчуванням. Код у конструкторі виконується під час створення екземпляра класу.
Синтаксис класу Apex:
public class myApexClass{
// variable declaration
//constructor
public myApexClass(){
}
//methods declaration
}
Ключове слово new використовується для створення екземпляра класу Apex. Нижче наведено синтаксис для створення екземпляра класу Apex:
myApexClass obj = new myApexClass();
Apex Getter і Setter
Властивість Apex подібна до змінної Apex. Для властивості Apex необхідні геттер та сеттер. Їх можна використовувати для виконання коду перед тим, як значення властивості буде доступне або змінено. Код в аксессорі get виконується, коли значення властивості зчитується. Код в аксессорі set виконується, коли значення властивості змінюється. Будь-яка властивість, що має лише аксессор get, вважається доступною лише для читання, будь-яка властивість, що має лише аксессор set, вважається доступною лише для запису, а будь-яка властивість, що має обидва аксессори get та set, вважається доступною для читання та запису. Синтаксис властивості Apex:
public class myApexClass {
// Property declaration
access_modifier return_type property_name {
get {
//code
}
set{
//code
}
}
}
Тут access_modifier – це модифікатор доступу властивості, return_type – це тип даних властивості, а property_name – це назва властивості.
Нижче наведено приклад властивості Apex, яка має як аксессори get, так і set:
public class myApex{
public String name{
get{ return name; }
set{ name = value; }
}
}
Тут назва властивості — name, вона є публічною властивістю та повертає тип даних String.
Необов'язково мати код у блоках get та set. Ці блоки можна залишити порожніми для визначення автоматичної властивості. Наприклад:
public double MyReadWriteProp{ get; set; }
Методи доступу Get та Set також можуть бути визначені з власними модифікаторами доступу. Якщо метод доступу визначено з модифікатором, він перевизначає модифікатор доступу властивості. Наприклад:
public String name{private get; set;}// name is private for read and public for write.
Класи визначають логіку повторного використання, яку ви викликаєте явно. Тригери, які розглядаються далі, запускаються автоматично щоразу, коли записи змінюються.
Тригер Apex
Тригери Apex дозволяють виконувати користувацькі Apex до та після виконання операції DML.
Apex підтримує такі два типи тригерів:
Перед тригерами: Ці тригери використовуються для перевірки та оновлення значення поля перед збереженням запису в базі даних.
Після тригерів: Ці тригери використовуються для доступу до значень полів (таких як ідентифікатор запису та поле LastModifiedDate), які встановлюються системою після того, як запис буде додано до бази даних. Ці значення полів можна використовувати для зміни інших записів. Записи, що спрацьовують після тригерів, доступні лише для читання.
Найкращою практикою є написання групових тригерів. Груповий тригер може обробляти як один запис, так і кілька записів одночасно.
Синтаксис тригера Apex:
trigger TriggerName on ObjectName (trigger_events) {
//Code_block
}
Тут TriggerName – це назва тригера, ObjectName – це назва об’єкта, для якого записано тригер, а trigger_events – це список подій, розділених комами.
Нижче наведено події, що підтримуються тригерами Apex: перед вставкою, перед оновленням, перед видаленням, після вставки, після оновлення, після видалення, після відновлення видалення.
Статичні ключові слова не можна використовувати в тригері Apex. Усі ключові слова, що застосовуються до внутрішніх класів, можна використовувати в тригері Apex.
Кожен тригер визначає неявні змінні, які повертають контекст виконання. Ці змінні визначені в класі System.Trigger і називаються контекстними змінними. На двох знімках екрана нижче перелічено контекстні змінні, що підтримуються тригерами Apex:
Нижче наведено міркування щодо контекстних змінних у тригерах Apex:
- Не використовуйте trigger.new та trigger.old в операціях DML.
- Trigger.new неможливо видалити.
- Trigger.new доступний лише для читання в after-тригерах.
- Trigger.new можна використовувати для зміни значень полів того самого об'єкта лише у попередніх тригерах.
На двох знімках екрана нижче наведено міркування щодо конкретних дій у різних тригерних подіях:
Тригери обробляють логіку реального часу, але деякі завдання просто занадто великі для однієї транзакції. Саме тут і приходить на допомогу пакетний Apex.
Пакетний клас в Apex
Пакетний клас у Salesforce використовується для обробки великої кількості записів, які перевищили б ліміти регулятора Apex за умови звичайної обробки. Пакетний клас виконує код асинхронно.
Нижче наведено переваги пакетного класу:
- Пакетний клас обробляє дані фрагментами, і якщо один фрагмент не вдається обробити успішно, успішно оброблені фрагменти не відкочуються.
- Кожен фрагмент даних у пакетному класі обробляється з новим набором обмежень регулятора, що гарантує, що код виконується в межах обмежень виконання регулятора.
Інтерфейс Database.Batchable має бути реалізований класом Apex для використання як пакетний клас. Він надає три методи, які мають бути реалізовані класом batch:
1. початок()
Цей метод генерує область видимості записів або об'єктів, які будуть оброблені методом інтерфейсу execute. Він викликається лише один раз під час виконання пакетної операції. Цей метод повертає або об'єкт Database.QueryLocator, або об'єкт Iterable. Кількість записів, які можна отримати за допомогою запиту SOQL з використанням об'єкта Database.QueryLocator, становить 50 мільйонів, але при використанні об'єкта Iterable загальна кількість записів, які можна отримати за допомогою запиту SOQL, становить лише 50 000. Iterable використовується для створення складної області видимості для класу batch.
Синтаксис методу start:
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
2. виконати()
Цей метод використовується для обробки кожного фрагмента даних. Метод execute викликається для кожного фрагмента записів. Розмір пакета виконання за замовчуванням становить 200 записів. Метод execute приймає два аргументи:
Посилання на об’єкт Database.BatchableContext,
Список sObjects, наприклад List , або список параметризованих типів. Синтаксис методу execute:
global void execute(Database.BatchableContext bc, List<P> records){}
3. завершення()
Метод finish викликається один раз під час виконання класу пакетної обробки. У методі finish можна виконувати операції постобробки. Наприклад: надсилання електронного листа з підтвердженням. Цей метод викликається, коли всі пакети обробки завершено. Синтаксис методу finish:
global void finish(Database.BatchableContext bc){}
Об'єкт Database.BatchableContext
Кожен метод інтерфейсу Database.Batchable має посилання на об'єкт Database.BatchableContext.
Цей об'єкт використовується для track прогрес пакетного завдання.
Нижче наведено методи екземпляра, що надаються BatchableContext:
- getChildJobId(): Цей метод повертає ідентифікатор пакетного завдання, яке наразі обробляється.
- getJobId(): цей метод повертає ідентифікатор пакетного завдання.
Нижче наведено синтаксис пакетного класу:
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
}
}
Метод Database.executeBatch
Метод Database.executeBatch використовується для виконання пакетного класу.
Цей метод приймає два параметри: екземпляр класу пакета, який потрібно обробити, та необов'язковий параметр області видимості для визначення розміру пакета. Якщо його не вказано, використовується розмір за замовчуванням, що дорівнює 200.
Синтаксис Database.executeBatch:
Database.executeBatch(myBatchObject, scope)
Виконання пакетного класу з назвою MyBatchClass:
MyBatchClass myBatchObject = new MyBatchClass(); Id batchId = Database.executeBatch(myBatchObject, 100);
База даних.Stateful
Клас пакетної обробки за замовчуванням не зберігає стан. Щоразу, коли викликається метод execute, отримується нова копія об'єкта, а всі змінні класу ініціалізуються.
Database.Stateful реалізовано для того, щоб пакетний клас мав стан.
Якщо ваш пакетний клас реалізує Database.Інтерфейс зі збереженням стану, всі змінні екземпляра зберігають свої значення, але статичні змінні скидаються між транзакціями.
Асинхронний пакет Apex Beyond
Batch Apex — це лише один із кількох способів асинхронного виконання коду. Salesforce пропонує чотири асинхронні варіанти, і вибір правильного залежить від обсягу даних, які ви обробляєте, та від того, чи потрібно завдання об’єднувати в ланцюжок, чи планувати.
- Майбутні методи: Анотовані як @future, вони найкраще підходять для простих операцій типу «запустив і забув», таких як виклики зовнішніх веб-сервісів.
- Apex, що можна поставити в чергу: Реалізує інтерфейс Queueable, приймає складні типи об'єктів, повертає ідентифікатор завдання та підтримує ланцюжок одного завдання з іншим.
- Пакетний апекс: Обробляє дуже великі обсяги даних фрагментами, як описано вище.
- Запланований Апекс: Реалізує інтерфейс Schedulable, щоб клас запускався у певний час, наприклад, щонічне завдання очищення.
| тип | Best For | Ключові можливості |
|---|---|---|
| Майбутній метод | Прості виклики | Вогонь і забуй |
| Apex, що можна поставити в чергу | Послідовна обробка | Ланцюжок завдань та моніторинг |
| Пакетний Apex | Мільйони записів | Подрібнена обробка |
| Запланований Апекс | Повторювані вакансії | Таймінг на основі Cron |
Яку б модель виконання ви не обрали, кожна транзакція все одно вимірюється відповідно до лімітів регулятора для всієї платформи, перелічених нижче.
Межі регулятора Apex
Ліміти регуляторів Apex – це ліміти, що застосовуються механізмом виконання Apex, щоб гарантувати, що будь-який неконтрольований код та процеси Apex не монополізуватимуть спільні ресурси та не порушуватимуть обробку інших користувачів у багатокористувацькому середовищі. Ці ліміти перевіряються для кожної транзакції Apex. Нижче наведено ліміти регуляторів, визначені Salesforce для кожної транзакції Apex:
| Опис | Limit |
|---|---|
| Запити SOQL, які можна виконати в синхронній транзакції | 100 |
| SOQL-запити, які можна виконувати в асинхронній транзакції | 200 |
| Записи, які можна отримати за допомогою запиту SOQL | 50,000 |
| Записи, які можна отримати за допомогою Database.getQueryLocator | 10,000 |
| SOSL-запити, які можна виконати в транзакції Apex | 20 |
| Записи, які можна отримати за допомогою запиту SOSL | 2,000 |
| Оператори DML, які можна виконувати в транзакції Apex | 150 |
| Записи, які можна обробити в результаті оператора DML, Approval.process або database.emptyRecycleBin | 10,000 |
| Виклики, які можна виконати в транзакції Apex | 100 |
| Сукупний ліміт часу очікування для всіх викликів, що виконуються в транзакції Apex | 120 секунд: |
| Обмеження на кількість завдань Apex, які можна додати до черги за допомогою System.enqueueJob | 50 |
| Обмеження часу виконання для кожної транзакції Apex | 10 хвилин |
| Обмеження на символи, які можна використовувати в класі та тригері Apex | 1 млн |
| Обмеження часу процесора для синхронної транзакції | 10,000 мілісекунд |
| Обмеження часу процесора для асинхронної транзакції | 60,000 мілісекунд |
| Загальний розмір купи | 6 МБ (синхронно) / 12 МБ (асинхронно) |
Як написати тестовий клас в Apex
Salesforce вимагає, щоб щонайменше 75 відсотків вашого коду Apex було охоплено модульними тестами, перш ніж ви зможете розгорнути його у продакшені, і кожен тригер повинен мати певне покриття. Тому написання тестових класів є основною навичкою Apex, а не додатковим доповненням.
Тестовий клас позначається тегом @isTest, а кожен тестовий метод також позначається тегом @isTest. Тестові методи не передадуть дані до бази даних і не бачать більшість існуючих даних організації, тому кожен тест створює власні записи. Методи Test.startTest() та Test.stopTest() надають тестованому коду новий набір обмежень регулятора, а твердження перевіряють, чи логіка поводилася належним чином.
Ось простий тестовий клас для логіки створення облікового запису:
@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);
}
}
Дотримуйтесь цих правил під час написання тестів:
- Використовуйте метод @testSetup для створення спільних тестових даних один раз для всіх тестових методів у класі.
- Перевірте масову поведінку, вставивши 200 записів, а не лише один.
- Охопіть позитивні, негативні сценарії та сценарії з обмеженим доступом до користувачів.
- Завжди включайте змістовні оператори System.assert; покриття без тверджень нічого не доводить.
Найкращі практики Apex
Початківці часто пишуть Apex, який працює для одного запису, але не працює в реальних масових операціях. Наведені нижче методи дозволяють утримувати ваш код у межах обмежень регулятора та полегшують його підтримку:
- Збільшити обсяг усього: Напишіть логіку, яка обробляє колекції записів, оскільки тригери можуть отримувати до 200 записів за один пакет.
- Уникайте циклів у SOQL та DML: Зробіть запит перед циклом, зберіть зміни у списку та виконайте один DML-інструкцію після циклу.
- Один тригер на об'єкт: Зберігайте тригери без логіки та делегуйте роботу класам обробників, що робить порядок виконання передбачуваним.
- Використовувати з обміном: Забезпечте безпеку на рівні записів, якщо немає задокументованої причини для запуску в системному контексті.
- Уникайте жорсткого кодування ідентифікаторів: Ідентифікатори записів відрізняються між ізольованими середовищами та робочими середовищами, тому запитуйте їх або використовуйте натомість користувацькі метадані.
- Моніторинг обмежень у коді: Методи класу Limits, такі як Limits.getQueries(), дозволяють перевіряти споживання ресурсів під час виконання.
💡 Порада: Перед розгортанням запустіть свій код на 200 записах у пісочниці. Більшість збоїв обмеження регуляторів виникають лише при масовому використанні, і їх раннє виявлення набагато дешевше, ніж налагодження у продакшені.






