Как правильно вызывать функции в условии Если Тогда в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При написании логических проверок в процедурах и функциях 1С разработчики часто сталкиваются с вопросом выбора стиля написания кода. Рассмотрим два базовых варианта вызова функции, возвращающей логическое значение для условного оператора Если:

Вариант 1. Предварительное сохранение в переменную:


ТекущееЗначение = ПроверитьВозможностьОтгрузки();
Если ТекущееЗначение Тогда
    // Действия при истинном условии
КонецЕсли;

Вариант 2. Прямой вызов в заголовке условия:


Если ПроверитьВозможностьОтгрузки() Тогда
    // Действия при истинном условии
КонецЕсли;

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

Критерий повторного использования результата

Первое и главное правило архитектуры кода: выясним, используется ли возвращенное значение дальше по тексту процедуры. Если логический результат функции требуется только один раз исключительно для ветвления логики, создание дополнительной переменной часто бывает избыточным.

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


// Неоптимальный вариант: повторный тяжелый вызов
Если ЗаказКлиентаОплачен(ТекущийЗаказ) Тогда
    ЗаблокироватьИзменение();
КонецЕсли;

// Позже в коде:
Если ЗаказКлиентаОплачен(ТекущийЗаказ) Тогда
    ОтправитьУведомление();
КонецЕсли;

В таких ситуациях всегда сохраняем результат в переменную перед первым использованием, чтобы гарантировать однократное выполнение алгоритма функции:


ЗаказОплачен = ЗаказКлиентаОплачен(ТекущийЗаказ);
Если ЗаказОплачен Тогда
    ЗаблокироватьИзменение();
КонецЕсли;

// Повторный вызов функции отсутствует
Если ЗаказОплачен Тогда
    ОтправитьУведомление();
КонецЕсли;

Поведение платформы и ленивые вычисления

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

Посмотрим на пример с составным условием:


Если ЭтоНовыйОбъект И ПроверитьПраваПользователяСервер() Тогда
    // Какая-то логика
КонецЕсли;

В этом примере, если свойство ЭтоНовыйОбъект равно Ложь, платформа даже не станет выполнять функцию ПроверитьПраваПользователяСервер(). Если же мы предварительно вынесем вызов этой функции в переменную перед блоком Если, функция выполнится в 100% случаев, что может повлечь за собой лишние запросы к базе данных или лишние серверные вызовы.

Влияние на отладку и серверные вызовы

Обратим внимание на процесс сопровождения и отладки кода:

  1. Просмотр значений в отладчике. Когда значение вычислено в отдельную переменную, достаточно навести курсор на переменную или посмотреть ее значение в панели «Локальные переменные».
  2. Побочные эффекты при отладке. Если выделить вызов функции ФункцияСЗапросом() и нажать «Вычислить выражение» (Shift+F9), платформа выполнит тело функции заново. Если функция находится на сервере, а точка останова на клиенте, произойдет полноценный контекстный или бесконтекстный серверный вызов. Если внутри функции присутствовали транзакции или изменение данных, повторное вычисление в отладчике может привести к ошибкам в алгоритме. Наличие промежуточной переменной полностью исключает эту проблему.
  3. Локализация ошибок приведения типов. Конструкция Если требует строгого типа Булево. Если функция по ошибке вернет Неопределено или NULL, строка Если Функция() Тогда вызовет исключение «Преобразование к типу Булево не может быть выполнено». По стеку ошибки при прямом вызове трудно понять, какое именно некорректное значение пришло. Промежуточная переменная позволяет сразу увидеть фактическое значение и тип переменной в точке ошибки.

Миф о расходе оперативной памяти

Иногда высказываются опасения, что создание отдельной переменной перегружает память сеанса. Это заблуждение: примитивные типы данных (к которым относится Булево, Число, Дата) занимают в стеке выполнения платформы считаные байты. Очищать такие переменные вручную конструкциями вида Переменная = ""; не имеет никакого смысла — это лишь загромождает программный код.

Стандарты разработки 1С и именование функций

Рассмотрим официальные стандарты разработки платформы 1С:Предприятие, касающиеся функций-предикатов:

  1. Имена функций не должны содержать префикс «Получить», если они возвращают логическое утверждение или конкретное значение объекта. Вместо ПолучитьЗначениеБулево() или ПолучитьПолноеИмя() следует использовать ПолноеИмя() или краткие предикаты.
  2. Для булевых проверок рекомендуется давать функциям имена, звучащие как утверждение: ЭтоНовыйОбъект(), ПравоИзмененияДоступно(), ПроведениеРазрешено().
  3. Если функция уже названа говорящим предикатом, присвоение ее значения переменной с точно таким же именем создает избыточное дублирование:

// Избыточный код
ЭтоНовыйОбъект = ЭтоНовыйОбъект();
Если ЭтоНовыйОбъект Тогда
    // ...
КонецЕсли;

// Лаконичный и правильный вариант
Если ЭтоНовыйОбъект() Тогда
    // ...
КонецЕсли;

Паттерн «Поясняющая переменная»

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


// Без поясняющей переменной смысл неочевиден
Если ПроверитьДоступ(Пользователь, "Документ.ЗаказКлиента", 2) Тогда
    // ...
КонецЕсли;

// С поясняющей переменной код читается значительно легче
ДоступноРедактированиеЗаказа = ПроверитьДоступ(Пользователь, "Документ.ЗаказКлиента", 2);
Если ДоступноРедактированиеЗаказа Тогда
    // ...
КонецЕсли;

Итоговые рекомендации

Обобщим правила выбора структуры кода:

  1. Пишем вызов напрямую в условии, если функция вызывается один раз, имеет понятное говорящее имя (предикат), не требует сложной отладки и используется в составе сокращенных вычислений (после проверки быстрых условий через И).
  2. Выносим вызов в промежуточную переменную, если значение требуется повторно в процедуре, если имя функции требует смыслового пояснения в текущем контексте или если метод выполняется на сервере и его результат важно зафиксировать для анализа в отладчике.
← На главную