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