При разработке крупных систем на платформе 1С:Предприятие часто возникает необходимость разделить функционал на несколько логических блоков. В связи с этим у разработчиков возникает закономерный вопрос: может ли одно расширение «видеть» объекты другого и можно ли доработать программный код, который уже находится в расширении, с помощью еще одного расширения? Разберем подробно современные механизмы платформы, которые позволяют решать эти задачи.
Проанализируем ситуацию, когда в Расширении_1 создан новый справочник дор_МоиДанные, а в Расширении_2 нам требуется использовать этот справочник как тип реквизита или обратиться к нему в коде. В старых версиях платформы это было невозможно, однако начиная с версии 8.3.14, 1С ввела полноценный механизм зависимостей.
Для того чтобы объекты одного расширения стали доступны в другом, выполним следующие шаги:
Расширения_2 (потомок).Расширение_1 (предок).После этого Расширение_2 будет строиться «поверх» не только основной конфигурации, но и «поверх» Расширения_1. Это позволяет нам выбирать объекты из первого расширения в качестве типов данных, использовать их в запросах и обращаться к их программным модулям. Для наглядного исследования связей и цепочек зависимостей между объектами конфигурации и расширений можно использовать веб-инструмент для анализа зависимостей в 1С.
Важный момент: система строго контролирует порядок загрузки. Если расширение-предок по какой-то причине не подключено или отключено из-за ошибки, расширение-потомок также не будет запущено. Это гарантирует целостность ссылочных данных в базе.
Выясним, как обстоят дела с программным кодом. Рассмотрим два сценария взаимодействия:
Сценарий 1: Вызов процедур и функций. Если в Расширении_1 создан общий модуль с установленным флагом Глобальный или в нем прописаны экспортные методы, то после настройки зависимости мы можем обращаться к ним из Расширения_2 так же, как к методам основной конфигурации.
Рассмотрим пример вызова метода из другого расширения:
// Код в Расширении_2
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Вызываем экспортный метод из общего модуля Расширения_1
дор_ЯдроСервер.ВыполнитьИнициализациюМодуля();
КонецПроцедуры
Сценарий 2: Расширение кода расширения. Здесь мы сталкиваемся с главным ограничением платформы. Мы не можем использовать аннотации &Перед, &После или &Вместо для методов, которые сами являются расширяющими (т.е. помечены аналогичными аннотациями в другом расширении). Платформа запрещает «наслоение» обработчиков друг на друга.
Однако, проанализируем, как обойти это ограничение. Если нам нужно изменить логику метода, который был полностью создан в первом расширении (новый метод), мы можем вызвать его и выполнить свою логику до или после. Если же оба расширения должны модифицировать одну и ту же типовую процедуру (например, ПриЗаписи справочника Номенклатура), они оба должны «цепляться» к типовому объекту основной конфигурации. Порядок их выполнения будет зависеть от их назначения и алфавитного порядка. Для контроля пересечений и выявления объектов, затронутых несколькими расширениями, подойдёт инструмент для анализа доработок в расширениях.
Для правильной работы многоуровневой системы расширений необходимо понимать иерархию назначений, которую использует 1С. Рассмотрим их в порядке приоритета применения:
Если у вас есть цепочка зависимостей, убедитесь, что назначение расширения-потомка не имеет более высокого приоритета, чем назначение расширения-предка, иначе могут возникнуть конфликты при реструктуризации данных.
Если ваша задача — создать «ядро» системы в одном расширении и продавать дополнительные модули в виде других расширений, рекомендуем придерживаться библиотечного подхода. Разберем основные шаги реализации такой архитектуры:
Шаг 1. Использование интерфейсных модулей. Вместо прямой модификации процедур в расширении-ядре, используйте событийную модель. В ядре создайте экспортную процедуру, которая будет проверять наличие установленных модулей-расширений.
Проанализируем пример кода для проверки активности расширения-модуля:
Функция МодульПродажПодключен() Экспорт
ПараметрыОтбора = Новый Структура("Имя, Активно", "дор_МодульПродаж", Истина);
МассивРасширений = РасширенияКонфигурации.Получить(ПараметрыОтбора);
Возврат МассивРасширений.Количество() > 0;
КонецФункции
Шаг 2. Разделение данных и логики. Старайтесь хранить основные структуры данных в базовом расширении (или даже в основной конфигурации, если это возможно), чтобы избежать проблем с обновлением и реструктуризацией при удалении одного из модулей.
Шаг 3. Использование программных подписок. Вместо визуального добавления обработчиков событий в расширениях-потомках, рассмотрите возможность программной подписки на события объектов, созданных в основном расширении. Это делает систему более гибкой и устойчивой к изменениям кода.
Несмотря на мощь механизма зависимостей, существуют технические нюансы, которые могут усложнить разработку:
ОпределяемогоТипа в одном расширении, который включает в себя типы из другого расширения, может работать нестабильно в некоторых релизах платформы.Расширения_А в качестве ведущих измерений в регистрах Расширения_Б. Это накладывает жесткие условия на порядок удаления и обновления этих расширений.Таким образом, отвечая на вопрос «умеет ли 1С в расширение на расширение» — да, умеет, но через механизм зависимостей и вызов экспортных методов, а не через прямое наследование аннотаций программного кода.