Как настроить совместную работу нескольких расширений в 1С и избежать конфликтов при вызове одного метода?

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

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

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

Поймем суть проблемы: почему директива &После может не сработать?

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

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

Как платформа 1С определяет приоритет применения расширений

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

  1. Принадлежность к РИБ (Распределенной информационной базе). Расширения, переданные из главного узла, всегда имеют приоритет над локально установленными.
  2. Свойство «Назначение». Это ключевой инструмент управления приоритетом. Платформа подключает расширения в строгой последовательности их назначения:
    • Исправление (Патчи) — самый высокий приоритет, применяются в первую очередь.
    • Адаптация — средний приоритет, применяются во вторую очередь.
    • Дополнение — самый низкий приоритет, применяются в последнюю очередь.
  3. Порядок регистрации (или создания). Если у двух расширений совпадает назначение (например, оба являются «Адаптацией»), приоритет определяется внутренним идентификатором регистрации (параметр _ExtensionOrder в базе данных). Простыми словами, то расширение, которое было загружено или создано позже, окажется ниже в списке и применится последним (поверх остальных).

Вы можете визуально оценить этот порядок в окне «Расширения конфигурации» в Конфигураторе: они выполняются ровно в том порядке, в котором расположены в списке сверху вниз.

Схема выполнения методов: принцип «слоеного пирога»

Когда несколько расширений дорабатывают один и тот же метод конфигурации, платформа выстраивает их выполнение по принципу слоев:

Пошаговое решение: создание цепочки вызовов

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

Шаг 1. Создание и настройка вашего расширения.
Создайте новое расширение в Конфигураторе. Чтобы гарантировать, что наше расширение применится поверх расширения франчайзи (то есть будет внешним слоем), установите ему назначение «Дополнение» (при условии, что у франчайзи выставлена «Адаптация»). Если у них также стоит «Дополнение», убедитесь, что ваше расширение в списке находится ниже их расширения.

Шаг 2. Написание перехватывающего метода.
Вместо директивы &После мы задействуем директиву &Вместо. Посмотрим на пример реализации кода:


&Вместо("ПриСозданииНаСервере")
Процедура ИмяПерсоны_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // 1. Передаем управление внутрь "пирога" — к коду франчайзи
    ПродолжитьВызов(Отказ, СтандартнаяОбработка); 
    
    // 2. Сюда управление вернется только после того, как полностью
    // отработает процедура "Вместо" из расширения франчайзи.
    // Пишем нашу доработку, которая должна выполниться ПОСЛЕ кода франчайзи:
    
    Если Не Отказ Тогда
        // Наша кастомная логика
        ПроверитьЗаполнениеДополнительныхРеквизитов();
    КонецЕсли;
    
КонецПроцедуры

Как это работает на практике: Платформа видит наше расширение как более приоритетное на выполнение (оно находится ниже в списке/цепочке вызовов). При наступлении события ПриСозданииНаСервере платформа сразу обращается к нашему методу. Строка ПродолжитьВызов() отправляет запрос на выполнение следующего обработчика в цепочке — им как раз оказывается метод &Вместо франчайзи. Франчайзи выполняет свою логику, завершает работу, управление возвращается в нашу процедуру, и следом беспрепятственно выполняется наш собственный код. Конфликта не происходит, исходное расширение не затронуто!

Использование современной альтернативы: &ИзменениеИКонтроль

Начиная с версии платформы 8.3.15, разработчикам доступна более безопасная аннотация — &ИзменениеИКонтроль. Это отличная альтернатива жесткому замещению метода.

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

Настройка зависимостей между расширениями

Рассмотрим более сложную ситуацию: что делать, если вам нужно не просто встроиться в общий вызов, а физически обратиться к экспортным процедурам, функциям или объектам, которые были созданы в расширении франчайзи?

Для реализации этого сценария в платформе «1С:Предприятие» предусмотрен механизм зависимостей расширений. Разберем, как его настроить:

  1. Откройте свойства своего расширения в дереве конфигурации.
  2. Найдите свойство «Используемые расширения».
  3. Добавьте туда имя расширения франчайзи в качестве контролируемой зависимости.

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

Резюме и лучшие практики для разработчиков

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

← На главную