Как отладить программный код, который выполняется командой Выполнить()?

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

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

В этой статье мы подробно разберем, как обойти это ограничение, проанализируем различные методики — от простых "сообщений" до продвинутой генерации внешних обработок — и выясним, какой подход наиболее эффективен в разных ситуациях.

Способ 1. Вынос кода в общий модуль или расширение (Рекомендуемый)

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

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

Рассмотрим пример реализации. В текстовом поле настроек вместо огромного куска кода мы оставляем лишь короткий вызов:


// В пользовательской настройке (текст для Выполнить)
ПараметрыВызова = Новый Структура;
ПараметрыВызова.Вставить("Объект", Объект);
ПараметрыВызова.Вставить("ДополнительныеДанные", ДополнительныеДанные);

Результат = МойМодульОтладки.ВыполнитьАлгоритм(ПараметрыВызова);

Теперь мы можем открыть конфигуратор, найти МойМодульОтладки и поставить стандартную точку останова в процедуре ВыполнитьАлгоритм. Это дает нам полный доступ ко всем инструментам отладки: просмотру локальных переменных, стеку вызовов и пошаговому выполнению.

Способ 2. Динамическое создание внешней обработки

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

Разберем по шагам, как это работает:

  1. Программа берет текст кода из настроек.
  2. Создается временный файл с расширением .epf, содержащий структуру внешней обработки с модулем объекта.
  3. Текст кода помещается в одну из процедур модуля объекта.
  4. Для отладки вы открываете этот временный файл в Конфигураторе и ставите точку останова (упростить процесс может специальное расширение для отладки внешних обработок).
  5. В основном коде вызывается ВнешниеОбработки.Создать(ПутьКФайлу).

Этот метод сложнее в реализации, так как требует формирования бинарного файла обработки или использования шаблона дополнительной обработки, в который подставляется текст. Однако он незаменим, когда нужно отладить сложный алгоритм в "боевых" условиях без изменения структуры метаданных.

Способ 3. Использование консолей кода и инструментов разработчика

Выясним, как упростить себе жизнь с помощью готовых инструментов. Существуют сторонние разработки, такие как "Инструменты разработчика" (ИР). Рассмотрим функционал "Консоли кода", которая позволяет выполнять и отлаживать произвольные алгоритмы.

Если код внутри Выполнить() имеет слабую связь с контекстом (не обращается к локальным переменным модуля, которые нельзя сериализовать), мы можем поступить так:

  1. В точке вызова Выполнить() ставим точку останова.
  2. Используем инструменты сериализации (например, из состава ИР), чтобы выгрузить значения всех входящих параметров в файл или строку.
  3. Открываем "Консоль кода", загружаем туда эти параметры и сам текст алгоритма.
  4. Запускаем отладку непосредственно в консоли.

Важный момент: основная сложность здесь заключается в передаче контекста. Если динамический код обращается к методам текущей формы или объекта через ЭтотОбъект, перенести такой код в консоль без правки будет затруднительно.

Способ 4. Логирование и методы "грубой" отладки

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

Самый простой вариант — использование команды Сообщить(). Рассмотрим пример:


// Вставляем в отлаживаемый текст
Сообщить("Значение переменной X = " + Строка(ПеременнаяX));

Однако если код выполняется в фоновом задании или на сервере без возврата контекста на клиент, сообщение просто пропадет. В этом случае следует использовать ЗаписьЖурналаРегистрации(). Посмотрим на пример вызова:


ЗаписьЖурналаРегистрации("ОтладкаДинамическогоКода", 
    УровеньЖурналаРегистрации.Предупреждение, , , 
    "Текущее состояние структуры: " + ЗначениеВСтрокуВнутр(МояСтруктураДанных));

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

Способ 5. Использование исключений для получения дампа данных

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


// Вставляем в нужное место кода
ОписаниеСостояния = "Данные: А=" + А + "; Б=" + Б;
ВызватьИсключение ОписаниеСостояния;

При выполнении этого кода система выдаст окно с ошибкой, в котором будет написано содержимое ваших переменных. Это позволяет быстро получить "снимок" состояния без настройки сложных инструментов.

Рекомендации по написанию отлаживаемого динамического кода

Чтобы в будущем не сталкиваться с трудностями отладки, придерживайтесь следующих правил при проектировании систем с использованием Выполнить():

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

Рассмотрим шаблон безопасного выполнения:


Попытка
    Выполнить(ТекстАлгоритма);
Исключение
    ЗаписьЖурналаРегистрации("ОшибкаДинамическогоКода", УровеньЖурналаРегистрации.Ошибка, , , 
        ОписаниеОшибки() + Символы.ПС + ТекстАлгоритма);
    ВызватьИсключение "Ошибка в динамическом алгоритме. Подробности в журнале регистрации.";
КонецПопытки;

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

← На главную