Как обратиться к общему модулю расширения из документа в 1С?

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

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

Прямой синтаксис вызова общего модуля расширения

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

  1. Модуль не должен быть глобальным (обращение выполняется по имени модуля через точку).
  2. Вызываемая процедура или функция обязательно должна иметь ключевое слово Экспорт.
  3. Режим совместимости конфигурации должен быть не ниже версии 8.3.9.

Посмотрим на пример вызова экспортного метода из модуля расширения:


Взносы = Расш1_ЗупРасчет.Расш_ЗупРассчитать(
    МенеджерВременныхТаблиц, 
    Объект.Ссылка, 
    Объект.Организация, 
    Объект.ПериодРегистрации
);

Ограничения общих модулей в расширениях

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

  1. Запрет глобальных серверных модулей: собственные общие модули расширения не могут иметь одновременно установленные флаги Глобальный и Сервер.
  2. Запрет привилегированного режима: собственные общие модули расширения не могут быть отмечены как Привилегированный. Код выполняется только в контексте текущих прав пользователя.
  3. Ограничения заимствования: нельзя заимствовать типовые глобальные серверные модули из основной конфигурации. Попытка применить такое расширение приведет к ошибке обновления базы данных.

Настройка контекста исполнения (Клиент / Сервер)

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

  1. Если вызов функции выполняется из клиентского контекста (например, из обработчика события формы &НаКлиенте), а расчет происходит на сервере, у общего модуля обязательно должен быть установлен флаг Вызов сервера.
  2. Если флаг Вызов сервера не установлен, попытка вызова чисто серверного модуля с клиента приведет к исключению времени выполнения.
  3. Для оптимизации производительности разделяйте логику: код интерфейса помещайте в клиентские модули, а ресурсоемкие выборки данных и расчеты — в серверные модули.

Архитектурно правильный подход: перехват методов вместо правки основной конфигурации

Рассмотрим важный архитектурный аспект. Если вы правите код в модуле основной конфигурации ради вызова модуля расширения, теряется главное преимущество расширений — сохранение типовой конфигурации на полной поддержке («на замке»).

Рекомендуется использовать механизм перехвата событий с помощью аннотаций. Разберем правильную последовательность действий:

  1. Заимствуем документ или его форму в расширение.
  2. В модуле заимствованного объекта перехватываем типовой метод с помощью аннотаций &Перед, &После или &Вместо.
  3. Внутри перехваченной процедуры вызываем методы своего общего модуля.

Посмотрим на пример перехвата метода с использованием аннотации &Вместо и вызовом типовой логики через ПродолжитьВызов():


&Вместо("РассчитатьВзносы")
Процедура Расш1_РассчитатьВзносы()
    // Вызов исходного типового метода
    ПродолжитьВызов();
    
    // Вызов собственного алгоритма из модуля расширения
    Расш1_ЗупРасчет.Расш_ЗупРассчитать(
        МенеджерВременныхТаблиц, 
        Объект.Ссылка, 
        Объект.Организация, 
        Объект.ПериодРегистрации
    );
КонецПроцедуры

Безопасный динамический вызов из основной конфигурации

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

Для предотвращения сбоев применим безопасный динамический вызов:


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

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

← На главную