При разработке в среде 1С:Предприятие 8.3 использование расширений стало стандартом де-факто. Однако механизмы расширения конфигурации таят в себе подводные камни, особенно когда речь идет о стандартных событиях формы, таких как ПриСозданииНаСервере. Рассмотрим ситуацию, когда добавленная процедура с аннотацией &После (After) упорно отказывается выполняться, несмотря на наличие корректной привязки в свойствах формы.
Для начала проанализируем, как платформа 1С обрабатывает расширяющие методы. Когда мы добавляем процедуру ПриСозданииНаСервереПосле, мы ожидаем, что она выполнится сразу после того, как отработает основной код типовой конфигурации. Но важно понимать, что если в системе установлено несколько расширений (включая автоматические исправления — патчи от 1С), порядок их выполнения критически важен.
Выясним причину возможного прерывания цепочки. Основная проблема часто кроется в использовании аннотации &Вместо (Instead) в другом расширении. Рассмотрим схему:
ПриСозданииНаСервере.&Вместо, то выполнение типового кода полностью замещается кодом из этого расширения.&Вместо не прописан метод ПродолжитьВызов(), то выполнение всех остальных расширений (и &Перед, и &После) блокируется.Зачастую разработчик даже не подозревает, что в базе установлено расширение-исправление от вендора. Патчи от 1С — это такие же расширения. Если 1С выпустила исправление для конкретной формы документа, в котором процедура ПриСозданииНаСервере перекрыта через &Вместо, ваш код в пользовательском расширении перестанет вызываться.
Чтобы проверить это, выполним следующие шаги:
Иногда мы сталкиваемся с обратной ситуацией: код выполняется несколько раз или "перескакивает" из одного расширения в другое. Это происходит из-за того, что платформа пытается объединить вызовы. Если в одном расширении процедура привязана к событию формы, а в другом — просто объявлена с той же аннотацией, может возникнуть путаница в контекстах.
Посмотрим на пример из практики, когда стек вызовов показывает сложную структуру переходов между общими модулями расширения и модулем формы:
// В расширении Аренды
&После("ПриСозданииНаСервере")
Процедура ГУТА_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Вызов общего модуля для модификации формы
ГУТА_МодификацияКонфигурации.ПриСозданииНаСервереПосле(ЭтаФорма, Отказ, СтандартнаяОбработка);
КонецПроцедуры
Если в системе несколько таких расширений, и они используют схожие имена процедур, платформа может ошибочно интерпретировать вызовы. Рекомендуется всегда использовать уникальные префиксы для имен процедур в расширениях, чтобы избежать коллизий.
Если нам абсолютно необходимо использовать &Вместо, но мы не хотим "ломать" работу других расширений, мы обязаны использовать метод ПродолжитьВызов(). Это позволит платформе передать управление дальше по цепочке.
Проанализируем правильный пример реализации:
&Вместо("ПриСозданииНаСервере")
Процедура Моя_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Наш код, который должен выполниться ДО основного
Сообщить("Выполняется предварительная логика расширения");
// Передаем управление основному коду и другим расширениям (&После)
ПродолжитьВызов(Отказ, СтандартнаяОбработка);
// Наш код, который должен выполниться ПОСЛЕ основного
Сообщить("Выполняется финальная логика расширения");
КонецПроцедуры
Если визуальный осмотр расширений не помогает, воспользуемся замером производительности. Это самый надежный способ увидеть реальную картину исполнения кода.
ПриСозданииНаСервере. В замере будет четко видно, на каком расширении прерывается исполнение и заходит ли управление в ваш блок &После.Также стоит обратить внимание на свойство формы "Состав" в расширении. Убедимся, что сама форма добавлена в расширение корректно. Иногда помогает удаление формы из расширения и ее повторное добавление с переносом обработчиков событий.
Проблема неработающего обработчика ПриСозданииНаСервереПосле в 90% случаев не является багом платформы, а является следствием архитектурного конфликта. Помните: любое расширение с аннотацией &Вместо без вызова ПродолжитьВызов() "убивает" все последующие расширения в очереди. Порядок расширений в списке (вверх/вниз) определяет эту очередь, и именно его нужно проверять в первую очередь при возникновении подобных проблем.