Как внутри метода Выполнить использовать локальные функции и псевдопроцедуры?

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

Часто в процессе разработки универсальных механизмов или консолей кода возникает необходимость вызывать функции, которые описаны прямо в динамически исполняемом тексте. Поскольку метод Выполнить() не поддерживает прямое объявление функций, которые «видит» интерпретатор, нам приходится применять нестандартные подходы. Давайте разберем, как можно реализовать подобные конструкции, и проанализируем, какие инструменты нам в этом помогут.

Реализация через коллекцию функций и структуру

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


Функции = Новый Структура();
Функции.Вставить("X", "Параметры.Результат = Параметры.А + Параметры.Б;");
Функции.Вставить("Y", "Параметры.Результат = Параметры.А * 2;");

Параметры = Новый Структура("А, Б, Результат", 10, 20, 0);
Выполнить(Функции.X);
Сообщить(Параметры.Результат);

Рассмотрим этот подход подробнее. Мы используем структуру Параметры в качестве контейнера для обмена данными между внешним кодом и «псевдофункцией». Такой метод позволяет передавать аргументы и получать результат без использования глобальных переменных.

Использование стека для реентерабельности

Если ваши псевдофункции должны быть реентерабельными (вызываться друг из друга), одного объекта структуры может быть недостаточно. В этом случае мы можем организовать стек вызовов на базе массива. Разберем шаги реализации:

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

Важно помнить, что такой подход делает код крайне сложным для отладки, так как стандартный отладчик 1С не сможет «зайти» внутрь строки, исполняемой через Выполнить().

Применение оператора перехода (Goto)

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


Текст = "Первый";
МеткаВозврата = "Возврат1";
Перейти ~Сообщить;
~Возврат1:
Текст = "Второй";
МеткаВозврата = "Возврат2";
Перейти ~Сообщить;
~Возврат2:
Перейти ~Конец;
~Сообщить:
Сообщить(Текст);
Если МеткаВозврата = "Возврат1" Тогда
    Перейти ~Возврат1;
ИначеЕсли МеткаВозврата = "Возврат2" Тогда
    Перейти ~Возврат2;
КонецЕсли;
~Конец:

Здесь мы явно управляем потоком исполнения. Важное предупреждение: такой метод крайне не рекомендуется использовать в продуктовом коде (продакшене). Это путь к созданию «нечитаемого говнокода», который будет практически невозможно поддерживать другим разработчикам.

Когда стоит использовать такие приемы?

Проанализировав все «за» и «против», мы приходим к выводу, что использование Выполнить() для бизнес-логики — это антипаттерн. Тем не менее, есть специфические случаи, когда это оправдано:

Почему это опасно?

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

  1. Проблемы отладки: Код, исполняемый динамически, скрыт от инструментов отладки конфигуратора.
  2. Веб-клиент: Метод Выполнить() не работает в веб-клиенте, поэтому ваше решение не будет переносимым в браузер.
  3. Безопасность: Динамический код может стать «дырой» в безопасности системы, если не использовать ВыполнитьВБезопасномРежиме().

В заключение, старайтесь максимально использовать ОбщиеМодули и РасширенияКонфигурации. Если же вы все-таки решили применить методы эмуляции функций внутри Выполнить(), делайте это осознанно, тщательно документируя каждый шаг, чтобы ваши коллеги не столкнулись с непреодолимыми трудностями при поддержке такого решения в будущем.

← На главную