При разработке и отладке сложных систем на платформе «1С:Предприятие 8» (особенно таких масштабных решений, как 1С:ERP) разработчики часто сталкиваются с неочевидным поведением отладчика. Одна из классических проблем — когда запись в регистр сведений успешно выполняется, но точки останова в процедурах ПередЗаписью и ПриЗаписи модуля набора записей упорно игнорируются системой. При этом замер производительности также может показывать полное отсутствие обращений к этим процедурам.
В рамках этой статьи мы подробно разберем, почему возникает такая ситуация, как настроить отладчик для стабильной работы и каким образом можно программно управлять логикой выполнения обработчиков событий при записи наборов данных.
Проанализируем наиболее распространенную и банальную причину, с которой столкнулся автор темы. В процессе длительной работы серверные процессы 1С (rphost) или сам отладчик могут частично терять связь. При этом отладка в некоторых серверных общих модулях продолжает работать исправно, а в модулях объектов или модулях наборов записей — полностью прекращается.
Для решения этой проблемы выполним следующие шаги:
rphost через консоль администрирования.Очень часто в современных конфигурациях (особенно в ERP-системах) запись тяжелых наборов данных или проведение документов переносится в фоновые задания, чтобы не блокировать интерфейс пользователя. Если запись регистра сведений выполняется асинхронно, стандартный сеанс отладки просто «не видит» этот процесс.
Выясним, как правильно настроить автоматическое подключение к фоновым заданиям:
Современный подход к доработке систем предполагает активное использование расширений. Если в вашей системе установлено расширение, в котором перехвачены события записи данного регистра сведений с помощью аннотации &Вместо, оригинальный код может вообще не вызываться.
Рассмотрим пример кода в расширении, который полностью блокирует выполнение оригинального обработчика:
&Вместо("ПередЗаписью")
Процедура Мой_ПередЗаписью(Отказ, Замещение)
// Если здесь нет вызова ПродолжитьВызов(),
// оригинальный обработчик из основной конфигурации никогда не выполнится!
// Точка останова в основной конфигурации не сработает.
КонецПроцедуры
Для исправления этой ситуации убедимся, что во всех перехватывающих процедурах расширений присутствует обязательный вызов базового метода:
&Вместо("ПередЗаписью")
Процедура Мой_ПередЗаписью(Отказ, Замещение)
// Выполняем предварительную логику расширения
// Обязательный вызов оригинального обработчика основной конфигурации:
ПродолжитьВызов(Отказ, Замещение);
// Выполняем последующую логику расширения
КонецПроцедуры
Иногда перед разработчиком встает задача: записать данные в регистр сведений программно, но так, чтобы тяжелая бизнес-логика (проверки, заполнение связанных регистров), написанная в ПередЗаписью или ПриЗаписи, не выполнялась.
Штатными средствами платформы полностью запретить вызов самих процедур-обработчиков при записи через встроенный язык 1С невозможно. Платформа в любом случае инициализирует события при вызове метода Записать(). Однако мы можем легко обойти выполнение кода внутри этих обработчиков с помощью свойства ОбменДанными.Загрузка.
Рассмотрим, как правильно реализовать этот механизм. В самом начале процедур модуля набора записей всегда должна присутствовать проверка флага загрузки:
Процедура ПередЗаписью(Отказ, Замещение)
// Если включен режим загрузки данных, немедленно прерываем выполнение обработчика
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Ниже идет основная бизнес-логика, которая будет пропущена
ВыполнитьСложныеПроверки();
КонецПроцедуры
Теперь для записи данных в «чистом» виде, без вызова проверок, нам достаточно установить это свойство в коде, который производит запись набора:
НаборЗаписей = РегистрыСведений.МестоПозицииШтатногоРасписанияВСтруктуреПредприятия.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
// Заполняем набор записей новыми данными...
НоваяСтрока = НаборЗаписей.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ДанныеИсточника);
// Включаем режим загрузки для обхода обработчиков событий модуля набора
НаборЗаписей.ОбменДанными.Загрузка = Истина;
// Производим запись
НаборЗаписей.Записать();
Важное примечание: Использование МенеджераЗаписи вместо НабораЗаписей не решает проблему обхода обработчиков, так как под капотом платформа 1С при записи менеджера всё равно создает набор записей и инициирует те же самые события модуля набора записей.
Разберем еще одну неочевидную особенность работы платформы с независимыми регистрами сведений, которая часто ставит в тупик начинающих разработчиков. При изменении или перезаписи существующей записи платформа производит операцию в два этапа:
ПередЗаписью и ПриЗаписи вызываются в первый раз, но коллекция записей ЭтотОбъект будет пустой (ЭтотОбъект.Количество() = 0).Если в вашей точке останова было установлено условие (например, проверка наличия записей в наборе или анализ конкретных значений реквизитов), отладчик гарантированно пропустит первый этап (очистку), что может быть ошибочно воспринято как нестабильная работа платформы.
Для корректного анализа всегда учитывайте этот двухэтапный механизм и при необходимости проверяйте количество записей в наборе:
Процедура ПередЗаписью(Отказ, Замещение)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если ЭтотОбъект.Количество() = 0 Тогда
// Это этап очистки (удаления старых записей).
// Здесь также можно разместить логику, специфичную для удаления данных.
Иначе
// Это этап записи новых данных.
КонецЕсли;
КонецПроцедуры
Применяя данные подходы и понимая внутренние механизмы платформы «1С:Предприятие 8», вы сможете легко локализовать любые проблемы с отладкой серверного кода и гибко управлять логикой записи данных в регистры сведений.