Как отладить код внутри функции Выполнить() в 1С?

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

Каждый разработчик на платформе «1С:Предприятие» рано или поздно сталкивается с динамическим кодом. Использование функций Выполнить() или Вычислить() незаменимо, когда алгоритм должен формироваться на лету, настраиваться пользователем в режиме «1С:Предприятие» или загружаться из внешних источников (например, при обмене данными). Однако в процессе разработки возникает серьезная проблема: как только выполнение доходит до динамической строки, отладчик просто «пролетает» ее насквозь. Зайти внутрь этой строки стандартным шагом (клавишей F11) невозможно.

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

Почему не получается войти отладкой в Выполнить() напрямую?

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

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

Тем не менее, у нас есть целый арсенал обходных путей. Рассмотрим их по шагам от простых к продвинутым.

Способ 1. Метод временного выноса кода (ручной перенос)

Это самый очевидный и простой способ, который часто применяется «на скорую руку». Если динамический код хранится в переменной или константе, мы можем временно перенести его в реальный модуль конфигурации.

Рассмотрим этот процесс по шагам:

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

Посмотрим на пример. Было:


// Динамический код, который невозможно отладить
КодСТипомСтрока = "РезультатТаблицы = Запрос.Выполнить().Выгрузить();";
Выполнить(КодСТипомСтрока);

На время отладки мы преобразуем это в следующий вид:


// Временно закомментировали динамический вызов
// Выполнить(КодСТипомСтрока); 

// Вызываем временную процедуру отладки
Тест_ОтладкаКода();

А в конце модуля определяем саму процедуру, где ставим точку останова на строке с запросом:


Процедура Тест_ОтладкаКода()
    // Сюда мы скопировали динамический код
    РезультатТаблицы = Запрос.Выполнить().Выгрузить(); // <-- Сюда ставим точку останова (F9)
КонецПроцедуры

Минусы метода: если динамический код активно использует локальный контекст (переменные исходной процедуры), вам придется передавать все эти переменные в параметры временной процедуры, что бывает крайне трудоемко при большом количестве связей.

Способ 2. Вывод состояния через Сообщить() или Журнал регистрации

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

Для этого внутрь исполняемого текста внедряются вызовы функций Сообщить() или запись в журнал регистрации через ЗаписьЖурналаРегистрации().

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


КодСТипомСтрока = "Для Каждого Стр Из Таблица Цикл " +
                  "    Сообщить(""Обработка строки: "" + Стр.Номенклатура); " +
                  "    Стр.Цена = Стр.Цена * 1.1; " +
                  "КонецЦикла;";
Выполнить(КодСТипомСтрока);

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

Способ 3. Вынос динамического кода в общий модуль или расширение

Если динамический код в вашей системе — это не разовое решение, а регулярно изменяемый бизнес-алгоритм (например, формулы расчета скидок, правила заполнения реквизитов), лучшей практикой будет полный отказ от хранения этого кода в виде строк в базе данных.

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

Как это реализовать:

Посмотрим на пример реализации:


// В базе данных вместо огромного куска кода храним только одну строчку вызова:
КодСТипомСтрока = "дф_ДинамическиеАлгоритмы.ВыполнитьРасчетСкидки(ПараметрыАлгоритма);";
Выполнить(КодСТипомСтрока);

Сам алгоритм теперь находится в конфигураторе:


Процедура ВыполнитьРасчетСкидки(ПараметрыАлгоритма) Экспорт
    // Здесь находится весь сложный код
    // Мы можем без проблем поставить точку останова на любой строке ниже!
    Для Каждого СтрокаТовара Из ПараметрыАлгоритма.ТабличнаяЧасть Цикл
        СтрокаТовара.Скидка = СтрокаТовара.Сумма * 0.05;
    КонецЦикла;
КонецПроцедуры

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

Способ 4. Использование функций-помощников в Табло отладчика

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

В штатном режиме окно «Вычислить выражение» (Shift + F9) в 1С не умеет выполнять многострочные конструкции или присвоения (например, Объект.Отказ = Истина там написать нельзя — возникнет ошибка синтаксиса).

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


Функция ДУ(Код, П1 = Неопределено, П2 = Неопределено) Экспорт
    Выполнить(Код);
    Возврат П1;
КонецФункции

Теперь, когда вы стоите на любой точке останова в программе, вы можете открыть окно Табло (Ctrl + Alt + W) или Вычислить выражение (Shift + F9) и написать там вызов вашей функции, передав код строкой:

ДУ("П1.Отказ = Истина", ЭтотОбъект)

В данном случае функция выполнит код, который изменит свойство Отказ у переданного объекта ЭтотОбъект (который внутри функции привязан к параметру П1), и вернет измененный объект обратно в табло. Это дает мощный инструмент интерактивной отладки «на лету».

Способ 5. Динамическая генерация внешней обработки (подход «Конвертации данных»)

Этот способ отлично знаком тем, кто работал с правилами обмена в «Конвертации данных 2.0». Там обработчики событий пишутся в виде текста, но при выгрузке/загрузке их нужно как-то отлаживать.

Суть метода заключается в программном создании временного файла внешней обработки:

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

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

Способ 6. Профессиональный инструмент — «Инструменты разработчика» (ИР)

Если вы хотите заниматься разработкой и отладкой на профессиональном уровне, рекомендуем использовать мощный бесплатный пакет программ «Инструменты разработчика» (автор TormozIT).

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

Подведем итоги

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

Выбирайте наиболее подходящий под ваши задачи метод и делайте вашу разработку в 1С быстрой и комфортной!

← На главную