Учебное пособие по Salesforce Apex для начинающих

⚡ Умное резюме

Язык программирования Apex предоставляет разработчикам Salesforce объектно-ориентированный, строго типизированный язык для добавления пользовательской бизнес-логики в CRM. Он обеспечивает работу классов, триггеров и пакетных заданий, а ограничения Governor Limits поддерживают стабильность общей многопользовательской платформы.

  • 🧱 Foundation: Apex — это язык, нечувствительный к регистру. JavaСинтаксис, похожий на синтаксис, который работает непосредственно на платформе Salesforce Lightning.
  • 🇧🇷 Доступ к данным: Запросы SOQL и операторы DML позволяют вашему коду считывать и записывать записи sObject непосредственно в базу данных Salesforce.
  • 🇧🇷 Реализация: Классы, свойства и триггеры позволяют привязывать пользовательскую логику к операциям вставки, обновления, удаления записей и другим системным событиям.
  • 📦 Масштаб: Пакетная обработка Apex и другие асинхронные решения обрабатывают миллионы записей по частям, не превышая лимиты платформы.
  • 🚦 Лимиты губернатора: Ограничения на количество транзакций, такие как 100 синхронных SOQL-запросов и 150 операторов DML, защищают совместно используемые ресурсы.
  • Качество: Перед развертыванием в продакшене модульные тесты должны охватывать не менее 75 процентов кода Apex.

Обзор программирования APEX в Salesforce

Что такое Apex в Salesforce?

Вершина Apex — это объектно-ориентированный и строго типизированный язык программирования, разработанный компанией Salesforce для создания приложений «программное обеспечение как услуга» (SaaS) и систем управления взаимоотношениями с клиентами (CRM). Apex помогает разработчикам создавать сторонние SaaS-приложения и добавлять бизнес-логику к системным событиям, предоставляя поддержку баз данных и клиент-серверные интерфейсы.

Apex помогает разработчикам добавлять бизнес-логику к системным событиям, таким как нажатия кнопок, обновления связанных записей и страницы Visualforce. Синтаксис Apex похож на... Java. Зарегистрируйтесь в Salesforce чтобы узнать, как работает CRM-система.

Особенности языка программирования Apex

Вот важные особенности Salesforce Apex:

  • Apex — это язык программирования, нечувствительный к регистру.
  • С помощью Apex можно выполнять операции DML, такие как INSERT, UPDATE, UPSERT и DELETE, над записями sObject.
  • В Apex можно запрашивать записи sObject, используя SOQL (Salesforce Object Query Language) и SOSL (Salesforce Object Search Language).
  • Позволяет создать модульный тест и выполнить его для проверки. покрытие кода и эффективность кода в Apex.
  • Apex работает в многопользовательской среде и Salesforce В Salesforce установлены ограничения, которые не позволяют пользователю монополизировать общие ресурсы. Любой код, превышающий установленное ограничение, завершается с ошибкой.
  • В Apex объект Salesforce можно использовать в качестве типа данных. Например:
    Account acc = new Account();

    В данном случае Account — это стандартный объект Salesforce.

  • Apex автоматически обновляется с каждой версией Salesforce.

В каких случаях разработчику следует выбрать Apex?

Код Apex следует писать только в том случае, если бизнес-сценарий слишком сложен для реализации с использованием встроенных функций Salesforce, позволяющих создавать приложения с помощью мыши.

Ниже приведены несколько сценариев, в которых вам потребуется написать код Apex:

  • Для создания веб-сервисов, интегрирующих Salesforce с другими приложениями.
  • Для реализации пользовательской проверки объектов sObject.
  • Для выполнения пользовательской логики Apex при выполнении операции DML.
  • Реализация функциональности, которую невозможно реализовать с помощью существующих инструментов декларативной автоматизации, таких как Flow.
  • Установить почтовые службы которые обрабатывают содержимое, заголовки и вложения входящих электронных писем.

Как только вы поймете, когда Apex — правильный выбор, следующим шагом будет понимание того, что происходит с вашим кодом после его сохранения.

Рабочая структура Apex

Ниже представлена ​​последовательность действий для кода Apex:

  • Действия разработчика: Когда разработчик сохраняет код на платформе, весь код Apex компилируется в набор инструкций, понятных интерпретатору среды выполнения Apex, и эти инструкции затем сохраняются в качестве метаданных на платформе.
  • Действие конечного пользователя: Когда пользовательское событие запускает код Apex, сервер платформы извлекает скомпилированные инструкции из метаданных и пропускает их через интерпретатор Apex, прежде чем вернуть результат.

На приведенной ниже диаграмме показано, как действия разработчика и конечного пользователя взаимодействуют с сервером приложений платформы Lightning:

Рабочая структура Apex

Среда разработки Apex

Код Apex можно разрабатывать либо в изолированной среде (песочнице), либо в организации Developer Edition Salesforce.

Рекомендуется разрабатывать код в изолированной среде (песочнице), а затем развертывать его в производственной среде, как показано ниже:

Среда разработки Apex

Инструменты разработки кода Apex: Ниже перечислены три инструмента, доступные для разработки кода Apex во всех версиях Salesforce:

  • Консоль разработчика
  • Visual Studio Code с пакетом расширений Salesforce (он заменяет устаревшую среду разработки Force.com IDE).
  • Code редактор в пользовательском интерфейсе настройки Salesforce

Подготовив среду, давайте рассмотрим основные составляющие самого языка, начиная с типов данных.

Типы данных в Apex

Ниже перечислены типы данных, поддерживаемые Apex:

Примитивный

Целое число, DoubleТипы данных Long, Date, Datetime, Decimal, Time, Blob, String, ID и Boolean считаются примитивными. Все примитивные типы данных передаются по значению, а не по ссылке.

Коллекции

В Apex доступны три типа коллекций:

  • Список: Это упорядоченная коллекция примитивов, sObjects, коллекций или объектов Apex, основанная на индексах.
  • Набор: Неупорядоченная коллекция уникальных элементов, не содержащая дубликатов.
  • Карта: Это набор уникальных ключей, которые сопоставляются с отдельными значениями, которые могут быть примитивами, объектами sObject, коллекциями или объектами Apex.

sОбъект

Это специальный тип данных в Salesforce. Это похоже на таблицу в SQL и содержит поля, аналогичные столбцам в SQL.

Перечисления

Enum — это аббревиатура.tract — это тип данных, который хранит одно значение из конечного набора заданных идентификаторов.

Классы, объекты и интерфейсы

В качестве типов данных также можно использовать определяемые пользователем классы и интерфейсы Apex. Объект обозначает экземпляр любого типа данных, поддерживаемого в Apex.

Синтаксис апекса

Объявление переменной

Поскольку Apex — это язык со строгой типизацией, в Apex обязательно нужно объявлять переменную с указанием типа данных.

Например:

Contact con = new Contact();

Здесь переменная con объявлена ​​с типом данных Contact.

SOQL-запрос

SOQL расшифровывается как Salesforce Object Query Language (язык запросов к объектам 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, его можно расширить и переопределить.

Резюме

Если класс определен с помощью абсолютногоtracКлючевое слово `t` должно содержать как минимум один метод с ключевым словом `abs`.tracи этот метод должен иметь только сигнатуру.

Например:

public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}

Апексная строка

Строка — это набор символов без ограничения по количеству символов. Например:

String name = 'Test';

В Salesforce класс String предоставляет несколько встроенных методов. Ниже приведены некоторые из наиболее часто используемых методов:

сократить (maxWidth)

Этот метод обрезает строку до указанной длины и возвращает её, если длина заданной строки превышает указанную; в противном случае он возвращает исходную строку. Если значение переменной maxWidth меньше 4, этот метод генерирует исключение времени выполнения — System.StringException: Minimum abbreviation 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

равно (строкаOrId)

Этот метод возвращает 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)

Этот метод добавляет экранирующий символ (\) перед любой одинарной кавычкой в ​​строке и возвращает результат. Метод предотвращает внедрение 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

отделка()

Этот метод удаляет все начальные и конечные пробелы из строки и возвращает её.

значениеOf(toConvert)

Этот метод возвращает строковое представление переданного объекта.

Строки, классы и ключевые слова объединяются, когда вы начинаете упаковывать логику в многократно используемые модули, и именно для этого и предназначены классы Apex.

Класс Apex

Класс Apex — это шаблон или основа, на основе которой создаются объекты. Объект — это экземпляр класса.

В Salesforce существует три способа создания классов Apex:

  • Консоль разработчика
  • 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 аналогично переменной Apex. Для свойства Apex необходимы геттер и сеттер. Они могут использоваться для выполнения кода до того, как значение свойства будет считано или изменено. Код в геттере выполняется при чтении значения свойства. Код в сеттере выполняется при изменении значения свойства. Любое свойство, имеющее только геттер, считается доступным только для чтения, любое свойство, имеющее только сеттер, считается доступным только для записи, а любое свойство, имеющее как геттер, так и сеттер, считается доступным для чтения и записи. Синтаксис свойства 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 до и после выполнения операций DML.

Apex поддерживает следующие два типа триггеров:

Перед срабатыванием триггеров: Эти триггеры используются для проверки и обновления значения поля перед сохранением записи в базу данных.

После срабатывания триггеров: Эти триггеры используются для доступа к значениям полей (таким как идентификатор записи и поле LastModifiedDate), которые устанавливаются системой после сохранения записи в базе данных. Эти значения полей могут использоваться для изменения других записей. Записи, срабатывающие после триггеров, доступны только для чтения.

Рекомендуется использовать пакетные триггеры. Пакетный триггер может обрабатывать как одну, так и несколько записей одновременно.

Синтаксис триггера Apex:

trigger TriggerName on ObjectName (trigger_events) {
	//Code_block
 }

Здесь TriggerName — это имя триггера, ObjectName — имя объекта, на котором записан триггер, а trigger_events — список событий, разделенных запятыми.

Ниже перечислены события, поддерживаемые триггерами Apex: before insert, before update, before delete, after insert, after update, after delete, after undelete.

В триггерах Apex нельзя использовать статические ключевые слова. В триггерах Apex можно использовать все ключевые слова, применимые к внутренним классам.

В каждом триггере определены неявные переменные, возвращающие контекст времени выполнения. Эти переменные определены в классе System.Trigger и называются контекстными переменными. На двух скриншотах ниже перечислены контекстные переменные, поддерживаемые триггерами Apex:

Контекстные переменные триггеров Apex

Контекстные переменные триггеров Apex (продолжение)

Ниже приведены рекомендации по использованию контекстных переменных в триггерах Apex:

  • Не используйте trigger.new и trigger.old в операциях DML.
  • Файл Trigger.new удалить невозможно.
  • Функция `Trigger.new` доступна только для чтения после срабатывания триггеров.
  • Метод `Trigger.new` можно использовать для изменения значений полей одного и того же объекта только в триггерах `before`.

На двух скриншотах ниже перечислены моменты, которые следует учитывать при выполнении конкретных действий в различных триггерных событиях:

Вопросы, касающиеся запуска событий Apex.

Вопросы, касающиеся событий запуска Apex (продолжение)

Триггеры обрабатывают логику в реальном времени, но некоторые задачи слишком велики для одной транзакции. Вот тут-то и пригодится пакетный Apex.

Пакетный класс в Apex

В Salesforce пакетный класс используется для обработки большого количества записей, которые при обычной обработке превысили бы лимиты Apex Governor. Пакетный класс выполняет код асинхронно.

Ниже перечислены преимущества пакетных занятий:

  • Класс пакетной обработки обрабатывает данные по частям, и если одна часть не обрабатывается успешно, успешно обработанные части не откатываются.
  • Каждый фрагмент данных в пакетном классе обрабатывается с новым набором ограничений, установленных регулятором, что гарантирует выполнение кода в пределах этих ограничений.

Для использования в качестве пакетного класса необходимо реализовать интерфейс Database.Batchable в классе Apex. Он предоставляет три метода, которые должны быть реализованы пакетным классом:

1. start()

Этот метод генерирует область действия записей или объектов, которые будут обрабатываться методом execute интерфейса. Он вызывается только один раз за время выполнения пакета. Этот метод возвращает либо объект Database.QueryLocator, либо Iterable. Количество записей, которые можно получить с помощью SOQL-запроса, используя объект Database.QueryLocator, составляет 50 миллионов, но при использовании Iterable общее количество записей, которые можно получить с помощью SOQL-запроса, составляет всего 50 000. Iterable используется для генерации сложной области действия для класса пакета.

Синтаксис метода запуска:

global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}

2. execute()

Этот метод используется для обработки каждого фрагмента данных. Метод execute вызывается для каждого фрагмента записей. Размер пакета по умолчанию для выполнения составляет 200 записей. Метод execute принимает два аргумента:

Ссылка на объект Database.BatchableContext,

Список объектов типа sObject, например, List или список параметризованных типов. Синтаксис метода execute:

global void execute(Database.BatchableContext bc, List<P> records){}

3. finish()

Метод `finish` вызывается один раз во время выполнения класса `batch`. В методе `finish` можно выполнять операции постобработки. Например: отправка подтверждающего письма по электронной почте. Этот метод вызывается после обработки всех пакетов. Синтаксис метода `finish`:

global void finish(Database.BatchableContext bc){}

Объект Database.BatchableContext

Каждый метод интерфейса Database.Batchable содержит ссылку на объект Database.BatchableContext.

Этот объект используется для tracотслеживайте ход выполнения пакетного задания.

Ниже перечислены методы экземпляра, предоставляемые 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 используется для выполнения пакета кода.

Этот метод принимает два параметра: экземпляр класса пакета для обработки и необязательный параметр scope для указания размера пакета. Если он не указан, используется размер по умолчанию, равный 200.

Синтаксис метода Database.executeBatch:

Database.executeBatch(myBatchObject, scope)

Выполнение пакетного класса с именем MyBatchClass:

MyBatchClass myBatchObject = new MyBatchClass();
Id batchId = Database.executeBatch(myBatchObject, 100);

Database.Stateful

Класс пакетной обработки по умолчанию является безсостоятельным. Каждый раз при вызове метода execute получается новая копия объекта, и все переменные класса инициализируются.

Метод Database.Stateful реализован для того, чтобы сделать класс пакетной обработки данных сохраняющим состояние.

Если ваш пакетный класс реализует интерфейс База данныхВ этом интерфейсе, сохраняющем состояние, все переменные экземпляра сохраняют свои значения, но статические переменные сбрасываются между транзакциями.

Асинхронный Apex, выходящий за рамки пакетной обработки.

Пакетный Apex — это лишь один из нескольких способов асинхронного выполнения кода. Salesforce предлагает четыре варианта асинхронного выполнения, и выбор подходящего зависит от объема обрабатываемых данных и от того, нужно ли объединять задачи в цепочки или планировать их выполнение.

  • Перспективные методы: Эти аннотации, помеченные @future, лучше всего подходят для простых операций, выполняемых один раз и забывающихся, таких как вызовы внешних веб-сервисов.
  • Queueable Apex: Реализует интерфейс Queueable, принимает сложные типы объектов, возвращает идентификатор задания и поддерживает цепочку заданий.
  • Пакетный Apex: Обрабатывает очень большие объемы данных по частям, как описано выше.
  • Запланированная вершина: Реализует интерфейс Schedulable, позволяющий классу запускаться в определенное время, например, в качестве ночной задачи очистки.
Тип лучший для Возможности ключа
Будущий метод Простые выноски Выстрелил и забыл
Очередь Apex Последовательная обработка Последовательность выполнения заданий и мониторинг
Пакетный Апекс Миллионы записей Обработка фрагментами
Запланированный Апекс Повторяющиеся задания тайминг на основе Cron

Какой бы модели исполнения вы ни выбрали, каждая транзакция по-прежнему будет оцениваться в соответствии с общеплатформенными ограничениями, указанными ниже.

Пределы губернатора Apex

Ограничения Apex Governor Limits — это ограничения, устанавливаемые средой выполнения Apex для предотвращения монополизации общих ресурсов любым неконтролируемым кодом и процессами Apex, а также для предотвращения сбоев в обработке данных другими пользователями в многопользовательской среде. Эти ограничения проверяются для каждой транзакции Apex. Ниже приведены ограничения Governor Limits, определенные Salesforce для каждой транзакции Apex:

Описание Ограничивать
SOQL-запросы, которые можно выполнить в синхронной транзакции 100
SOQL-запросы, которые можно выполнять в асинхронной транзакции. 200
Записи, которые можно получить с помощью запроса SOQL. 50,000
Записи, которые можно получить с помощью Database.getQueryLocator. 10,000
Запросы SOSL, которые можно выполнить в транзакции Apex. 20
Записи, которые можно получить с помощью запроса SOSL. 2,000
Операторы DML, которые можно выполнить в транзакции Apex. 150
Записи, которые могут быть обработаны в результате инструкции DML, Approval.process или data.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 записях в песочнице. Большинство сбоев, связанных с ограничениями системы управления ресурсами, проявляются только при обработке больших объемов данных, и их обнаружение на ранней стадии обходится гораздо дешевле, чем отладка в производственной среде.

Часто задаваемые вопросы (FAQ)

Нет. Apex заимствует средства. JavaСинтаксис похож на SOQL, но нечувствителен к регистру, работает только на платформе Salesforce Lightning, напрямую интегрирует SOQL в язык и регулируется лимитами на транзакцию. Java не имеет.

Зарегистрируйте бесплатную организацию Salesforce Developer Edition, которая включает консоль разработчика, и выполните практические упражнения. Trailhead, официальная обучающая платформа от Salesforce.

Visualforce — это язык разметки для создания страниц пользовательского интерфейса, а Apex — это серверный язык, который обеспечивает логику их работы. Страницы Visualforce часто вызывают классы контроллеров Apex для запроса и обновления данных.

Да. Agentforce для разработчиковИИ-помощник от Salesforce для Visual Studio CodeГенерирует и объясняет код Apex на основе подсказок на естественном языке. Всегда проверяйте и тестируйте сгенерированный ИИ код на соответствие ограничениям системы управления ресурсами перед развертыванием.

Классы Apex, помеченные аннотацией @InvocableMethod, могут быть представлены в виде пользовательских действий, позволяя ботам Einstein и агентам Agentforce вызывать вашу бизнес-логику, а Apex также может вызывать шаблоны подсказок Einstein и модели ИИ через API платформы.

Подведем итог этой публикации следующим образом: