К статье
Практический материал

Разработка и Конфигурация · 13 мин

Модуль менеджера в 1С 8.3: где выполняется код и как это устроено

Где выполняется код модуля менеджера в 1С 8.3: на сервере или клиенте. Директивы компиляции, типичные ошибки, примеры кода и проверка результата.

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

Модуль менеджера существует у прикладных объектов, для которых платформа создаёт объект-менеджер: справочников, документов, планов видов характеристик, планов счетов, регистров сведений, регистров накопления, регистров бухгалтерии, регистров расчёта, бизнес-процессов, задач, планов обмена и перечислений. Обратиться к этому модулю из кода можно через менеджер объекта, например Справочники.Номенклатура или Документы.РеализацияТоваровУслуг.

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

Что такое модуль менеджера и зачем он нужен

Модуль менеджера предназначен для размещения процедур и функций, которые работают с объектом конфигурации «в целом», а не с конкретной ссылкой или записью. Типичное содержимое — функции поиска и подбора данных, печатные формы, обработчики получения данных выбора, формирование представлений, служебные операции над коллекцией объектов.

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

Другой частый сценарий — переопределение стандартных обработчиков. Например, в модуле менеджера справочника можно описать обработчик ОбработкаПолученияДанныхВыбора, чтобы изменить состав данных, предлагаемых пользователю при вводе по строке. Этот обработчик тоже выполняется на сервере, поскольку подбор данных — серверная операция.

Где именно выполняется код модуля менеджера

Платформа 1С 8.3 компилирует модули в разных контекстах в зависимости от их типа и директив компиляции. Модуль менеджера — особый случай: он компилируется исключительно в серверном контексте. Это означает, что код модуля исполняется внутри серверного процесса (rphost в клиент-серверном варианте или в процессе сервера приложений), а не на компьютере пользователя.

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

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

Директивы компиляции в модуле менеджера

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

Если при копировании кода из модуля формы в модуль менеджера остались директивы &НаКлиенте или &НаСервере, конфигуратор сообщит об ошибке при проверке модуля. Это одна из частых причин «недоуменных» ошибок у начинающих разработчиков.

Как вызвать метод модуля менеджера из клиентского кода

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

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

Второй вариант предпочтительнее, когда одна и та же серверная логика нужна в нескольких формах: не придётся дублировать обёртки. Общий модуль при этом должен быть серверным, иначе вызов снова упрётся в контекстное ограничение.

Порядок действий при вызове из формы
  1. 1
    Создайте экспортную функцию в модуле менеджера объекта, например Функция ПолучитьДанныеПодбора(Параметры) Экспорт
  2. 2
    В модуле формы добавьте серверную процедуру с директивой &НаСервере, которая вызывает Справочники.Номенклатура.ПолучитьДанныеПодбора(Параметры)
  3. 3
    Из клиентской процедуры формы вызовите эту серверную процедуру
  4. 4
    Проверьте, что все параметры и возвращаемые значения сериализуемы: нельзя передавать между клиентом и сервером несериализуемые типы вроде запроса или построителя отчёта
  5. 5
    Запустите проверку конфигурации и убедитесь в отсутствии ошибок контекста

Пример кода: типовая структура модуля менеджера

Ниже приведён упрощённый пример экспортной функции в модуле менеджера справочника. Обратите внимание: никаких директив компиляции не требуется, весь код по умолчанию серверный.

// Модуль менеджера справочника "Номенклатура"

Функция НайтиПоАртикулу(Артикул) Экспорт

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Артикул = &Артикул";

Запрос.УстановитьПараметр("Артикул", Артикул);

РезультатЗапроса = Запрос.Выполнить();

Если РезультатЗапроса.Пустой() Тогда

Возврат Неопределено;

КонецЕсли;

Выборка = РезультатЗапроса.Выбрать();

Выборка.Следующий();

Возврат Выборка.Ссылка;

КонецФункции

Вызов этой функции из серверного контекста выглядит так: НайденнаяСсылка = Справочники.Номенклатура.НайтиПоАртикулу("АРТ-001");. Из клиентского модуля формы такой вызов напрямую недоступен — только через серверную обёртку, как описано выше.

bsl
&НаСервере
Функция НайтиНоменклатуруНаСервере(Артикул)
    Возврат Справочники.Номенклатура.НайтиПоАртикулу(Артикул);
КонецФункции

&НаКлиенте
Процедура ПодобратьПоАртикулу(Команда)
    Ссылка = НайтиНоменклатуруНаСервере(АртикулСтрокой);
    Если Ссылка = Неопределено Тогда
        ПоказатьПредупреждение(, "Элемент не найден");
    КонецЕсли;
КонецПроцедуры

Модуль менеджера и другие модули объекта: сравнение контекстов

Чтобы правильно выбирать место для кода, полезно сопоставить контексты выполнения разных модулей одного прикладного объекта. Ошибки размещения кода — частая причина лишних серверных вызовов и проблем с производительностью.

МодульКонтекст выполненияТипичное назначение
Модуль менеджераТолько серверОперации над объектом в целом: поиск, печать, обработчики получения данных
Модуль объектаТолько серверЛогика конкретной ссылки: обработка проведения, заполнение, проверка
Модуль формыКлиент и сервер (по директивам)Интерактивная логика, реакция на действия пользователя
Модуль командыКлиент и сервер (по директивам)Обработчики команд интерфейса

Из таблицы видно практическое правило: если логика относится к конкретному экземпляру объекта (проведение документа, заполнение элемента справочника) — ей место в модуле объекта. Если логика работает с объектом «в целом» (поиск по реквизиту, печать, представление) — в модуле менеджера. Смешение этих ролей приводит к тому, что код становится недоступен там, где он нужен.

Куда поместить код

Модуль менеджера

Подходит для функций поиска, печати, обработчиков получения данных выбора и представления. Ограничение: только серверный контекст, нет доступа к данным конкретного объекта через ЭтотОбъект.

Модуль объекта

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

Общий серверный модуль

Подходит для универсальной логики, не привязанной к одному типу объекта. Требует аккуратной настройки флагов компиляции.

Типичные ошибки при работе с модулем менеджера

Первая и самая распространённая ошибка — попытка вызвать метод менеджера из клиентского контекста. Симптом: ошибка «Метод объекта не обнаружен» или сообщение о недоступности вызова в данном контексте. Лечится переносом вызова в серверную процедуру.

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

Третья ошибка — передача несериализуемых типов между клиентом и сервером через обёртки. Например, нельзя вернуть из серверной функции объект Запрос, ПостроительОтчета или ТабличныйДокумент в некоторых сценариях — результат либо не передаётся, либо требует специальной обработки. Возвращайте простые типы: ссылки, структуры, массивы, таблицы значений (с оговорками).

Четвёртая ошибка — размещение в модуле менеджера тяжёлой логики, которая вызывается при каждом обращении к менеджеру. Код модуля компилируется при первом обращении в сеансе, и избыточный объём модуля увеличивает время компиляции и расход памяти сервера.

Типичные ошибки
01
Вызов метода менеджера напрямую из &НаКлиенте — ошибка контекста; нужен серверный посредник
02
Использование ПоказатьПредупреждение() внутри модуля менеджера — серверный код не имеет интерфейса
03
Оставленные директивы &НаКлиенте после копирования кода из формы — ошибка компиляции модуля
04
Возврат несериализуемых типов (Запрос, ПостроительОтчета) из функции, вызываемой с клиента — падение при передаче данных
05
Размещение логики конкретного объекта в менеджере вместо модуля объекта — код недоступен там, где ожидается

Как проверить, что всё работает правильно

После размещения кода в модуле менеджера выполните проверку конфигурации через меню «Конфигурация — Проверка конфигурации» с включённой проверкой модулей в разных контекстах (тонкий клиент, веб-клиент, сервер). Это выявит ошибки компиляции до запуска.

Затем проверьте поведение в режиме предприятия: вызовите функциональность, которая использует метод менеджера, и убедитесь, что нет ошибок в журнале регистрации и диалоге ошибок. Для отладки серверного кода включите в конфигураторе отладку по протоколу HTTP или TCP и установите точку останова внутри модуля менеджера — отладчик остановится именно в серверном контексте.

Контрольные точки

Как проверить результат

Проверка конфигурации
Норма

Нет ошибок компиляции модуля менеджера ни в одном контексте

Тревожный признак

Сообщения о недопустимых директивах или недоступных методах

Вызов из формы
Норма

Клиентская процедура вызывает серверную обёртку, данные возвращаются корректно

Тревожный признак

Ошибка «Метод объекта не обнаружен» или падение при передаче параметров

Отладка
Норма

Точка останова в модуле менеджера срабатывает, стек показывает серверный контекст

Тревожный признак

Точка не срабатывает — возможно, вызов идёт мимо или метод не экспортный

Часто задаваемые вопросы

Можно ли использовать директиву &НаКлиенте в модуле менеджера?

Нет. Модуль менеджера компилируется только на сервере, директивы &НаКлиенте и &НаСервере в нём не поддерживаются. Если такие директивы попали в модуль при копировании кода, их нужно удалить — иначе проверка конфигурации выдаст ошибку.

Почему из формы не видно экспортную функцию модуля менеджера?

Потому что клиентский контекст формы не имеет доступа к серверным методам напрямую. Добавьте в модуль формы процедуру с директивой &НаСервере и вызывайте метод менеджера из неё, либо используйте общий серверный модуль с включённым флагом «Вызов сервера».

Выполняется ли модуль менеджера на сервере в файловой базе?

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

Чем модуль менеджера отличается от модуля объекта?

Модуль объекта содержит логику конкретного экземпляра (проведение документа, заполнение элемента) и имеет контекст ЭтотОбъект. Модуль менеджера работает с типом объекта в целом: поиск, печать, обработчики получения данных. Оба выполняются только на сервере, но вызываются по-разному: модуль объекта — через объект, модуль менеджера — через менеджер (Справочники.Имя, Документы.Имя).

Можно ли в модуле менеджера работать в привилегированном режиме?

Можно. Внутри процедуры или функции вызовите УстановитьПривилегированныйРежим(Истина). Это стандартная практика для операций, которым нужен доступ к данным независимо от прав пользователя. Не забывайте, что привилегированный режим повышает риски: проверяйте входные параметры, чтобы не создать обход ограничений доступа.

Почему отладчик не останавливается в модуле менеджера?

Наиболее вероятные причины: метод не объявлен с ключевым словом Экспорт и вызывается извне, отладка сервера не включена (нужен запуск сервера 1С с ключом -debug), либо предмет отладки не подключён к нужному типу (сервер). Проверьте настройки отладки в конфигураторе и параметры запуска сервера.

Итог

Что важно запомнить

Модуль менеджера в 1С 8.3 — всегда серверный: он компилируется и выполняется только на сервере, директивы контекста в нём не работают. Для вызова из клиентского кода используйте серверные процедуры формы или общие серверные модули, передавайте только сериализуемые типы и проверяйте конфигурацию во всех контекстах перед запуском.