Урок за Salesforce Apex за начинаещи
⚡ Умно обобщение
Програмирането с Apex предоставя на разработчиците на Salesforce обектно-ориентиран, силно типизиран език за добавяне на персонализирана бизнес логика към CRM. Той захранва класове, тригери и пакетни задачи, докато ограниченията на регулаторите поддържат стабилността на споделената многонаемателна платформа.

Какво е Apex в Salesforce?
Връх е обектно-ориентиран и силно типизиран език за програмиране, разработен от Salesforce за изграждане на приложения за софтуер като услуга (SaaS) и управление на взаимоотношенията с клиенти (CRM). Apex помага на разработчиците да създават SaaS приложения на трети страни и да добавят бизнес логика към системни събития, като предоставя поддръжка на back-end бази данни и клиент-сървър интерфейси.
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();
Тук „Акаунт“ е стандартен обект на Salesforce.
- Apex автоматично се надгражда с всяко издание на Salesforce.
Кога разработчикът трябва да избере Apex?
Кодът за Apex трябва да се пише само ако даден бизнес сценарий е твърде сложен, за да бъде реализиран с помощта на предварително изградената функционалност „посочи и щракни“, предоставена от Salesforce.
Следват няколко сценария, в които трябва да напишете Apex код:
- За създаване на уеб услуги, които интегрират Salesforce с други приложения.
- За да се внедри персонализирана валидация на sObjects.
- За изпълнение на персонализирана Apex логика при извършване на DML операция.
- Да се имплементира функционалност, която не може да бъде изградена със съществуващи инструменти за декларативна автоматизация, като например Flow.
- Нагласям имейл услуги които обработват съдържанието, заглавките и прикачените файлове на входящите имейли.
След като разберете кога Apex е правилният избор, следващата стъпка е да разберете какво се случва с кода ви, след като го запазите.
Работна структура на Apex
Следва потокът от действия за Apex код:
- Действие на разработчика: Когато разработчикът запазва код на платформата, целият Apex код се компилира в набор от инструкции, които Apex runtime интерпретаторът може да разбере, и тези инструкции след това се запазват като метаданни на платформата.
- Действие на крайния потребител: Когато потребителско събитие изпълни Apex код, сървърът на платформата извлича компилираните инструкции от метаданните и ги изпълнява през интерпретатора на Apex, преди да върне резултата.
Диаграмата по-долу показва как действията на разработчика и крайния потребител взаимодействат със сървъра на приложенията на Lightning Platform:
Среда за разработка Apex
Кодът на Apex може да бъде разработен или в пясъчник, или в организация на Salesforce, разработена чрез Developer Edition.
Най-добрата практика е кодът да се разработи в пясъчник (sandbox) и след това да се внедри в производствената среда, както е илюстрирано по-долу:
Инструменти за разработване на Apex код: Следват три инструмента, достъпни за разработване на Apex код във всички издания на Salesforce:
- Конзола за програмисти
- Visual Studio Code с пакета за разширение Salesforce (той замества пенсионираната Force.com IDE)
- Code редактор в потребителския интерфейс на Salesforce Setup
След като средата ви е готова, нека разгледаме градивните елементи на самия език, като започнем с типовете данни.
Типове данни в Apex
Следните типове данни се поддържат от Apex:
Примитивен
Цяло число, Double, Long, Date, Datetime, Decimal, Time, Blob, String, ID и Boolean се считат за примитивни типове данни. Всички примитивни типове данни се предават по стойност, а не по препратка.
колекции
В Apex са налични три вида колекции:
- Списък: Това е подредена колекция от примитиви, sObjects, колекции или Apex обекти, базирани на индекси.
- Комплект: Неподредена колекция от уникални елементи, която не съдържа дубликати.
- Карта: Това е колекция от уникални ключове, които се съпоставят с единични стойности, които могат да бъдат примитиви, sObjects, колекции или Apex обекти.
sОбект
Това е специален тип данни в Salesforce. Подобно е на маса в SQL и съдържа полета, които са подобни на колоните в SQL.
Преброявания
Enum е abstract тип данни, който съхранява една стойност от краен набор от зададени идентификатори.
Класове, обекти и интерфейси
Потребителски дефинирани класове и интерфейси на Apex също могат да се използват като типове данни. Обектът се отнася до екземпляр на всеки тип данни, който се поддържа в Apex.
Apex Синтаксис
Декларация за променлива
Тъй като Apex е силно типизиран език, е задължително да се декларира променлива с тип данни в Apex.
Например:
Contact con = new Contact();
Тук променливата con е декларирана с тип данни Contact.
SOQL заявка
SOQL е съкращение от Salesforce Object Query Language. 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 е съкращение от език за манипулиране на данни. 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
Той дефинира null константа и може да бъде присвоен на променлива. Например:
Boolean b = null;
Фактически
Ако даден клас е дефиниран с ключовата дума virtual, той може да бъде разширен и презаписан.
Резюме
Ако даден клас е дефиниран с abstracключова дума t, тя трябва да съдържа поне един метод с ключовата дума abstract, и този метод трябва да има само подпис.
Например:
public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}
Apex String
Низът е набор от символи без ограничение на броя символи. Например:
String name = 'Test';
В Salesforce класът String предоставя няколко вградени метода. Следват няколко често използвани метода:
съкращаване (maxWidth)
Този метод отрязва низ до зададената дължина и го връща, ако дължината на дадения низ е по-дълга от зададената дължина; в противен случай връща оригиналния низ. Ако стойността на променливата maxWidth е по-малка от 4, този метод хвърля изключение по време на изпълнение – System.StringException: Minimum abreviation width is 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-символен обектен Id с 18-символен обектен Id и ако и двата ID представляват една и съща двоична последователност, той връща 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
отрежете ()
Този метод премахва всички начални и крайни интервали от низ и го връща.
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 са необходими getter и setter. Те могат да се използват за изпълнение на код, преди стойността на свойството да бъде достъпна или променена. Кодът в accessor get се изпълнява, когато стойността на свойство се прочете. Кодът в accessor set се изпълнява, когато стойността на свойство се промени. Всяко свойство, което има само get accessor, се счита за само за четене, всяко свойство, което има само set accessor, се счита за само за запис, а всяко свойство, което има и get, и set accessor, се счита за четене и запис. Синтаксис на свойство 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 accessors:
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 Trigger
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 triggers.
- Trigger.new може да се използва за промяна на стойностите на полетата на един и същ обект само в предишно тригериране.
Двете екранни снимки по-долу изброяват съображенията относно специфични действия при различни задействащи събития:
Тригерите обработват логика в реално време, но някои задачи са просто твърде големи за една транзакция. Тук се намесва batch Apex.
Пакетен клас в Apex
Пакетният клас в Salesforce се използва за обработка на голям брой записи, които биха надвишили ограниченията на Apex governor, ако се обработват нормално. Пакетният клас изпълнява кода асинхронно.
Следните предимства са на пакетния клас:
- Пакетният клас обработва данните на парчета и ако едно парче не успее да се обработи успешно, успешно обработените парчета не се отменят.
- Всеки блок данни в пакетен клас се обработва с нов набор от ограничения на регулатора, което гарантира, че кодът се изпълнява в рамките на ограниченията за изпълнение на регулатора.
Интерфейсът Database.Batchable трябва да бъде реализиран от клас Apex, за да се използва като пакетен клас. Той предоставя три метода, които трябва да бъдат реализирани от пакетния клас:
1. начало()
Този метод генерира обхвата на записите или обектите, които ще бъдат обработени от интерфейсния метод execute. Той се извиква само веднъж по време на изпълнението на batch. Този метод връща или обект 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 се извиква веднъж по време на изпълнението на класа batch. В метода 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 се използва за изпълнение на пакетен клас.
Този метод приема два параметъра: екземпляр на класа batch, който ще се обработва, и опционален параметър scope, който определя размера на пакета. Ако не е зададен, се използва размерът по подразбиране от 200.
Синтаксис на Database.executeBatch:
Database.executeBatch(myBatchObject, scope)
Изпълнение на пакетен клас с име MyBatchClass:
MyBatchClass myBatchObject = new MyBatchClass(); Id batchId = Database.executeBatch(myBatchObject, 100);
Database.Stateful
Пакетният клас е без състояние по подразбиране. Всеки път, когато се извика методът execute, се получава ново копие на обекта и всички променливи на класа се инициализират.
Database.Stateful е имплементиран, за да направи пакетния клас със състояние.
Ако вашият пакетен клас реализира База данни.Stateful интерфейс, всички променливи на екземпляра запазват стойностите си, но статичните променливи се нулират между транзакциите.
Асинхронен Apex Beyond Batch
Batch Apex е само един от няколкото начина за асинхронно изпълнение на код. Salesforce предлага четири асинхронни опции, а изборът на правилната зависи от това колко данни обработвате и дали задачите трябва да бъдат верижни или планирани.
- Бъдещи методи: Анотирани с @future, те са най-подходящи за прости операции от типа „изстреляй и забрави“, като например извиквания към външни уеб услуги.
- Връх, който може да се постави в опашка: Реализира интерфейса Queueable, приема сложни типове обекти, връща идентификатор на задача и поддържа свързването на една задача с друга.
- Партиден апекс: Обработва много големи обеми данни на части, както е описано по-горе.
- Планиран апекс: Реализира интерфейса Schedulable, така че класът да се изпълнява в определено време, например нощно почистване.
| Тип | Най-добър за | Ключова способност |
|---|---|---|
| Бъдещ метод | Прости допълнителни описания | Пали и забрави |
| Apex за опашка | Последователна обработка | Верижно свързване на задачи и наблюдение |
| Партиден апекс | Милиони записи | Разделена обработка |
| Планиран апекс | Повтарящи се работни места | Cron-базирано време |
Независимо от избрания от вас модел на изпълнение, всяка транзакция се измерва спрямо ограниченията на регулатора за цялата платформа, изброени по-долу.
Лимити на управителя на Apex
Ограниченията на Apex регулаторите са ограниченията, налагани от Apex runtime engine, за да се гарантира, че всеки неконтролируем Apex код и процеси не монополизират споделените ресурси и не нарушават обработката на други потребители в многопотребителска среда. Тези ограничения се проверяват за всяка Apex транзакция. Следните ограничения са определени от Salesforce за всяка Apex транзакция:
| Descriptйон | Граница |
|---|---|
| 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 MB (синхронно) / 12 MB (асинхронно) |
Как да напишем тестов клас в 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 записа в пясъчник, преди да го внедрите. Повечето грешки в ограниченията на регулаторите се появяват само при голям обем данни и ранното им откриване е много по-евтино от отстраняването на грешки в производствената среда.






