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