Некоторые уже не раз слышали о том, как лучше всего работать с триггерами, чтобы избежать проблем — не только в будущем, но и решая текущую задачу. Но для некоторых это будет чем-то новым .
Уже неоднократно сам обжигался, когда мой чудо-триггер мог сломать часть уже готовой логики по причине выхода за лимиты по времени, из-за множества SOQL запросов и т.п.
А иногда просто впадал в бесконечный цикл
Поэтому решил собрать памятки, о которых никогда не стоит забывать при работе с триггерами — как начинающим разработчикам, так и уже опытным.
1. Один триггер на объект.
Для объекта всегда должно существовать не более 1-го триггера. Представьте какая путаница возникнет — ведь порядок их выполнения контролировать невозможно. Но бывают исключения. Например если установлен managed package, который тоже содержит триггер на нужный вам объект. В этом случае стоит строго определить события, при которых логика вашего триггера будет вызвана.
2. Всю логику выносить в helper class
Триггер должен содержать логику для вызова необходимого хелпер класса. Всё остальное должно быть уже внутри helper class.
3. Bulkify Code
Код вашего helper класса должен быть готов принимать по 200 записей за раз. Поэтому вся логика вашего класса должна уметь работать с коллекциями.
4. Никаких SOQL и SOSL в цикле
Довольно старое правило, но всё же его стоит помнить. Это касается и тех случаев, когда метод helper class будет вызван внутри цикла. Cитуация редкая но случается.
5. Одна DML операция
Как говорит Dan Appelman, ваш helper class должен содержать не более одной DML операции. Например, если helper class содержит несколько условий, и в каждом из них нужно обновить определённую коллекцию. Понятно, что лучше собрать их всех воедино и вызвать операцию update, чем указывать её вызов под каждую из коллекций. Вот рисунок для более наглядного примера.
6. Имя триггера
Всегда стоит называть триггер в формате Имя объекта + Trigger.
Например: AccountTrigger. Так как триггер должен быть 1, то и найти его должно быть очень просто. Так вы упростите жизнь и себе, и тем, кто будет работать с вашим кодом после вас.
7. SOQL только для тех записей, которые нам нужны
Для фильтрации необходимых записей - старайтесь по максимуму использовать WHERE. Незачем запрашивать лишнее, тем более что у вас есть ограничение в 50 000. На Sandbox такое может и прокатит, но на Production всё может закончиться плохо. Так же не стоит делать отдельный SOQL запрос под каждую группу записей, лучше получить все сразу, и уже в цикле разбить на группы.
8. Unit test для триггера проверять на большом кол-ве значений
То что ваш триггер успешно прошёл проверку 3-мя записями - ещё ничего не значит. Попробуйте создать или обновить 200 записей , это поможет выявить ошибки ещё до отправки на production. Например, если существуют процессы автоматизации, которые так же повлияют на CPU time лимит. Не стоит забывать о таких подводных камнях.
9. Никаких hardcoded ID
Например, если вы вставляете Record Type Id , то на production он может отличаться. И Это тоже приведёт к ошибке. Всегда нужно ссылаться на получение актуальных данных.
10. BEFORE предпочтительнее перед AFTER
Конечно, есть случаи, когда лучше использовать именно after триггер (например, работа с ID записей или вставка/изменение записей других объектов). Но, в общем, при прочих равных, before триггер не требует дополнительной DML операции для сохранения изменений.