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

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

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

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

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

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

Путаница между этими модулями — частая причина ошибок вида «Переменная не определена» или неожиданного поведения при записи документа. Ниже разберём, где какой код размещать, как это влияет на производительность и сопровождение.

Что такое модуль объекта

Модуль объекта компилируется и выполняется всякий раз, когда в памяти создаётся объект встроенного языка — ДокументОбъект, СправочникОбъект и т. д. Это происходит при вызове СоздатьЭлемент(), ПолучитьОбъект(), при записи и проведении документа, при открытии формы объекта.

Внутри модуля объекта доступны все реквизиты и табличные части текущего экземпляра без префикса. Например, в модуле документа «РеализацияТоваров» можно напрямую обращаться к Контрагент или Товары. Именно здесь располагаются стандартные обработчики событий: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаПроверкиЗаполнения, ПриКопировании.

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

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Для Каждого СтрокаТовара Из Товары Цикл

// формирование движений по регистру

КонецЦикла;

КонецПроцедуры

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

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

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

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

Функция НайтиПоРеквизиту(Реквизит, Значение) Экспорт

Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура

|ГДЕ " + Реквизит + " = &Значение");

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

// ...

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

Сравнение модулей

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

Контекст конкретного экземпляра; события записи и проведения; создаётся при каждом обращении к объекту

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

Контекст типа в целом; создание, поиск, печать, служебные функции; единственный экземпляр на тип метаданных

Ключевые различия в контексте выполнения

Разница в контексте определяет всё остальное. В модуле объекта ЭтотОбъект — это сам объект с данными. В модуле менеджера понятия «текущий объект» не существует: чтобы работать с данными, нужно сначала получить ссылку, а затем объект через Ссылка.ПолучитьОбъект().

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

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

Где размещать процедуры печати и обработки

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

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

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

Типичные ошибки
01
Обращение к реквизитам объекта в модуле менеджера — ошибка «Переменная не определена» при компиляции
02
Размещение процедур печати в модуле объекта — команды печати не появляются в форме списка
03
Перенос ОбработкаПроведения в модуль менеджера — документ перестаёт формировать движения
04
Дублирование одной и той же функции в обоих модулях — рассинхронизация логики при доработках

Влияние на производительность и обновление конфигурации

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

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

Маршрут решения

Как выбрать место для кода

Код должен срабатывать при записи, проведении или проверке заполнения конкретного объектаРазмещайте его в модуле объекта
Код создаёт, ищет объекты или формирует печатные формы без привязки к экземпляруРазмещайте его в модуле менеджера
Функция нужна из разных мест конфигурации и не привязана к типу объектаВыносите её в общий модуль

Как проверить правильность размещения кода

Простой тест: попробуйте мысленно ответить на вопрос «нужны ли этому коду данные конкретного объекта?». Если да — это модуль объекта. Если код оперирует ссылками, запросами, макетами и параметрами — это модуль менеджера или общий модуль.

Практическая проверка — синтаксический контроль модуля в конфигураторе (Ctrl+F7 с выбором контекста). Код с обращением к реквизитам объекта в модуле менеджера не пройдёт проверку. Обратная ситуация — вызов несуществующей процедуры менеджера из модуля объекта — тоже выявится на этом этапе.

Дополнительно проверьте поведение в пользовательском режиме: проведите документ, вызовите печать из формы списка и из формы документа. Печатная форма, доступная только из формы документа, — признак того, что процедура печати размещена не в модуле менеджера.

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

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

Синтаксический контроль модуля
Норма

Ошибок нет, обращения к реквизитам только в модуле объекта

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

«Переменная не определена» в модуле менеджера

Команды печати в форме списка
Норма

Кнопка печати видна и работает без открытия документа

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

Печать доступна только из формы самого документа

Проведение документа
Норма

Формируются движения по регистрам

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

Документ проводится без движений — обработчик не в модуле объекта

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

Можно ли из модуля менеджера обратиться к данным конкретного документа?

Да, но только явно: сначала получить ссылку (запросом или через параметр), затем либо прочитать данные через точку от ссылки, либо вызвать ПолучитьОбъект(). Прямого доступа к реквизитам, как в модуле объекта, в модуле менеджера нет.

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

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

Есть ли модуль менеджера у регистров сведений и констант?

У регистров сведений модуль менеджера есть. У констант отдельного модуля менеджера нет — для них существует модуль менеджера значения константы, который исполняется в контексте менеджера значения конкретной константы.

Куда поместить функцию, которая нужна и в модуле объекта, и в других местах конфигурации?

Оптимально — в общий модуль или в модуль менеджера как экспортную. Из модуля объекта её можно вызвать через менеджер (Справочники.Номенклатура.ИмяФункции()) или напрямую из общего модуля. Дублировать код в двух модулях не следует.

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

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

Итог

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

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