Разработка и Конфигурация · 9 мин
Чем модуль менеджера отличается от модуля объекта в 1С
Чем модуль менеджера отличается от модуля объекта в 1С: назначение, контекст выполнения, типичные процедуры, ошибки разработчиков и рекомендации по выбору.
Модуль объекта и модуль менеджера — два разных контейнера кода у прикладных объектов конфигурации 1С (справочников, документов, регистров и др.). Главное различие: модуль объекта работает с конкретным экземпляром данных (конкретным документом, элементом справочника), а модуль менеджера — с объектом метаданных в целом, без привязки к какой-либо записи.
Модуль объекта исполняется в контексте объекта: внутри него доступны реквизиты и табличные части текущего экземпляра напрямую, а ключевое слово ЭтотОбъект ссылается на сам объект. Модуль менеджера такого контекста не имеет — он выполняется «вне» конкретных данных и предназначен для операций над коллекцией: поиска, создания, печати, получения данных для отчётов.
Путаница между этими модулями — частая причина ошибок вида «Переменная не определена» или неожиданного поведения при записи документа. Ниже разберём, где какой код размещать, как это влияет на производительность и сопровождение.
Что такое модуль объекта
Модуль объекта компилируется и выполняется всякий раз, когда в памяти создаётся объект встроенного языка — ДокументОбъект, СправочникОбъект и т. д. Это происходит при вызове СоздатьЭлемент(), ПолучитьОбъект(), при записи и проведении документа, при открытии формы объекта.
Внутри модуля объекта доступны все реквизиты и табличные части текущего экземпляра без префикса. Например, в модуле документа «РеализацияТоваров» можно напрямую обращаться к Контрагент или Товары. Именно здесь располагаются стандартные обработчики событий: ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаПроверкиЗаполнения, ПриКопировании.
Типичное содержимое модуля объекта: контроль корректности данных перед записью, формирование движений по регистрам, расчёт итогов по табличным частям, реакция на копирование. Всё это логика, привязанная к состоянию конкретного экземпляра.
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Для Каждого СтрокаТовара Из Товары Цикл
// формирование движений по регистру
КонецЦикла;
КонецПроцедуры
Что такое модуль менеджера
Модуль менеджера существует в единственном экземпляре на уровне объекта метаданных и выполняется в контексте менеджера — Документы.РеализацияТоваров, Справочники.Номенклатура. У него нет доступа к реквизитам какого-либо экземпляра: попытка написать Контрагент в модуле менеджера приведёт к ошибке «Переменная не определена».
Назначение модуля менеджера — операции над типом в целом: программное создание объектов, поиск по реквизитам, получение представления, формирование печатных форм, подготовка данных для подборов и отчётов. В типовых конфигурациях здесь размещаются процедуры печати (ДобавитьКомандыПечати, Печать), функции получения данных для обменов и служебные экспортные функции.
Важная особенность: модуль менеджера загружается один раз при первом обращении к менеджеру и переиспользуется. Это делает его подходящим местом для «тяжёлых» функций, которые вызываются многократно, — например, построения макета печатной формы или выполнения запроса.
Функция НайтиПоРеквизиту(Реквизит, Значение) Экспорт
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура
|ГДЕ " + Реквизит + " = &Значение");
Запрос.УстановитьПараметр("Значение", Значение);
// ...
КонецФункции
Сравнение модулей
Контекст конкретного экземпляра; события записи и проведения; создаётся при каждом обращении к объекту
Контекст типа в целом; создание, поиск, печать, служебные функции; единственный экземпляр на тип метаданных
Ключевые различия в контексте выполнения
Разница в контексте определяет всё остальное. В модуле объекта ЭтотОбъект — это сам объект с данными. В модуле менеджера понятия «текущий объект» не существует: чтобы работать с данными, нужно сначала получить ссылку, а затем объект через Ссылка.ПолучитьОбъект().
Из модуля объекта можно вызвать процедуру модуля менеджера через менеджер (Документы.РеализацияТоваров.ИмяПроцедуры()), если она экспортная. Обратный вызов невозможен: менеджер не знает ни о каких экземплярах. Это накладывает архитектурное правило — общая логика выносится в менеджер или общие модули, а модуль объекта обращается к ней.
Также различается время жизни и накладные расходы. Модуль объекта компилируется при каждом создании объекта, поэтому массовая обработка через ПолучитьОбъект() в цикле — дорогая операция. Модуль менеджера компилируется один раз, и вызовы его функций заметно дешевле.
Где размещать процедуры печати и обработки
Команды печати в типовых конфигурациях на базе БСП размещаются именно в модуле менеджера: процедуры ДобавитьКомандыПечати и Печать вызываются подсистемой печати через менеджер, без создания объекта. Если разместить их в модуле объекта, механизм печати их просто не найдёт.
Обработчики записи и проведения, наоборот, должны быть только в модуле объекта — платформа вызывает ПередЗаписью и ОбработкаПроведения именно там. Перенос этих обработчиков в модуль менеджера приведёт к тому, что они никогда не выполнятся.
Для функций, которые нужны и объекту, и внешним потребителям, правильный вариант — разместить экспортную функцию в модуле менеджера или общем модуле и вызывать её из модуля объекта. Так код не дублируется и остаётся доступным извне.
Влияние на производительность и обновление конфигурации
При массовой обработке данных выбор модуля влияет на скорость. Если задача — прочитать данные тысячи документов, правильное решение — запрос в функции модуля менеджера, а не цикл с ПолучитьОбъект(). Запрос не создаёт объекты и не компилирует модуль объекта на каждой итерации.
С точки зрения сопровождения код в модуле менеджера типовой конфигурации обновляется так же, как и модуль объекта, — оба являются частью конфигурации поставщика. Поэтому доработки рекомендуется выносить в собственные общие модули или расширения, оставляя типовые модули нетронутыми. Это касается обоих модулей одинаково.
Как выбрать место для кода
Как проверить правильность размещения кода
Простой тест: попробуйте мысленно ответить на вопрос «нужны ли этому коду данные конкретного объекта?». Если да — это модуль объекта. Если код оперирует ссылками, запросами, макетами и параметрами — это модуль менеджера или общий модуль.
Практическая проверка — синтаксический контроль модуля в конфигураторе (Ctrl+F7 с выбором контекста). Код с обращением к реквизитам объекта в модуле менеджера не пройдёт проверку. Обратная ситуация — вызов несуществующей процедуры менеджера из модуля объекта — тоже выявится на этом этапе.
Дополнительно проверьте поведение в пользовательском режиме: проведите документ, вызовите печать из формы списка и из формы документа. Печатная форма, доступная только из формы документа, — признак того, что процедура печати размещена не в модуле менеджера.
Как проверить результат
Ошибок нет, обращения к реквизитам только в модуле объекта
«Переменная не определена» в модуле менеджера
Кнопка печати видна и работает без открытия документа
Печать доступна только из формы самого документа
Формируются движения по регистрам
Документ проводится без движений — обработчик не в модуле объекта
Часто задаваемые вопросы
Можно ли из модуля менеджера обратиться к данным конкретного документа?
Да, но только явно: сначала получить ссылку (запросом или через параметр), затем либо прочитать данные через точку от ссылки, либо вызвать ПолучитьОбъект(). Прямого доступа к реквизитам, как в модуле объекта, в модуле менеджера нет.
Что быстрее работает — модуль объекта или модуль менеджера?
Модуль менеджера компилируется один раз при первом обращении, а модуль объекта — при каждом создании объекта. Поэтому многократно вызываемые функции выгоднее размещать в модуле менеджера или общем модуле, а массовое чтение данных делать запросами без создания объектов.
Есть ли модуль менеджера у регистров сведений и констант?
У регистров сведений модуль менеджера есть. У констант отдельного модуля менеджера нет — для них существует модуль менеджера значения константы, который исполняется в контексте менеджера значения конкретной константы.
Куда поместить функцию, которая нужна и в модуле объекта, и в других местах конфигурации?
Оптимально — в общий модуль или в модуль менеджера как экспортную. Из модуля объекта её можно вызвать через менеджер (Справочники.Номенклатура.ИмяФункции()) или напрямую из общего модуля. Дублировать код в двух модулях не следует.
Почему команда печати не появляется в форме списка после доработки?
Чаще всего процедуры ДобавитьКомандыПечати и Печать размещены не в модуле менеджера, а в модуле объекта или формы. Подсистема печати вызывает их через менеджер объекта, поэтому перенесите процедуры в модуль менеджера и сделайте их экспортными.
Что важно запомнить
Модуль объекта — код в контексте конкретного экземпляра: запись, проведение, проверка заполнения. Модуль менеджера — код в контексте типа в целом: создание, поиск, печать, служебные функции. У менеджера нет доступа к реквизитам экземпляра, а общую логику лучше выносить в модуль менеджера или общие модули.