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

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

1С: в чём разница между модулем объекта и модулем менеджера

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

Модуль объекта и модуль менеджера — два разных программных контекста у прикладных объектов конфигурации 1С (справочников, документов, регистров, планов счетов и других). Оба находятся рядом в дереве метаданных, из-за чего начинающие разработчики регулярно путают, куда помещать код. Результат ошибки предсказуем: процедура «не видна» из нужного места, переменная ЭтотОбъект оказывается недоступна, а обработка проведения ведёт себя не так, как ожидалось.

Ключевая разница — в том, с чем работает код. Модуль объекта исполняется в контексте конкретного экземпляра: конкретного документа «Реализация товаров № 000123» или конкретного элемента справочника «Номенклатура». Модуль менеджера работает с объектным типом в целом — со всеми документами «Реализация товаров» сразу, не загружая ни один из них в память как объект.

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

Что такое модуль объекта и когда он исполняется

Модуль объекта — это программный модуль, привязанный к экземпляру прикладного объекта. Он загружается в память вместе с объектом: когда вы открываете документ, вызываете Ссылка.ПолучитьОбъект(), создаёте новый элемент через Справочники.Номенклатура.СоздатьЭлемент() или когда платформа проводит документ. Код модуля объекта «видит» все реквизиты и табличные части конкретного экземпляра напрямую, без обращения через точку к какой-либо переменной.

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

Пример характерного кода модуля объекта:

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

// ЭтотОбъект доступен неявно: обращаемся к реквизитам напрямую

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

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

КонецЦикла;

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

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

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

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

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

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

Пример экспортной функции модуля менеджера:

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

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

Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Документ.РеализацияТоваровУслуг

|ГДЕ Организация = &Организация И Номер = &Номер";

// ...

Возврат Результат;

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

Вызывается такая функция из любого места конфигурации через менеджер: Документы.РеализацияТоваровУслуг.НайтиПоРеквизиту(...). Никакой конкретный документ при этом не загружается.

Сравнение модулей по ключевым признакам

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

ПризнакМодуль объектаМодуль менеджера
Контекст исполненияКонкретный экземпляр объектаМенеджер типа, без экземпляра
Доступ к ЭтотОбъектЕстьНет
Доступ к реквизитам и табличным частям напрямуюЕстьНет, только через параметры
Типовые обработчикиОбработкаПроведения, ПередЗаписью, ПриЗаписи, ОбработкаЗаполненияОбработкаПолученияФормы, ОбработкаПолученияДанныхВыбора
Как вызывается извнеЧерез объект: Объект.Метод()Через менеджер: Документы.ВидДокумента.Метод()
Типичные задачиПроведение, контроль заполнения, бизнес-логика экземпляраПоиск, печать, создание объектов, массовые операции
Загрузка объекта в памятьОбъект уже загруженНе требуется

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

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

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

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

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

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

Общий модуль

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

Типичные сценарии: где какой модуль использовать

Проведение документа и контроль данных

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

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

Печатные формы и массовые операции

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

Частая антипрактика — вызывать Ссылка.ПолучитьОбъект() внутри цикла по ссылкам ради пары реквизитов. Каждый вызов загружает весь объект с табличными частями. Запрос к реквизитам в модуле менеджера решает ту же задачу без лишней нагрузки на сервер.

Обработчики получения формы и данных выбора

Когда нужно подменить форму, которую платформа открывает по умолчанию (например, при выборе элемента в поле ввода показывать свою форму выбора), используется ОбработкаПолученияФормы в модуле менеджера. Аналогично ОбработкаПолученияДанныхВыбора позволяет управлять списком быстрого выбора. Эти механизмы работают на уровне типа, поэтому в модуле объекта их разместить невозможно.

Как определить, куда поместить новую процедуру
  1. 1
    Сформулируйте, с чем работает код: с данными одного экземпляра или с типом/ссылками в целом
  2. 2
    Если нужны реквизиты и табличные части конкретного объекта — модуль объекта или общий модуль с передачей ЭтотОбъект
  3. 3
    Если достаточно ссылок и запросов — модуль менеджера с экспортной процедурой
  4. 4
    Если это обработчик события платформы (ПередЗаписью, ОбработкаПроведения) — только модуль объекта
  5. 5
    Если это ОбработкаПолученияФормы или ОбработкаПолученияДанныхВыбора — только модуль менеджера
  6. 6
    Проверьте вызов: код компилируется и метод доступен в нужной точке вызова

Контекст сервера и тонкий клиент: важное ограничение

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

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

Типичные ошибки и как их избежать

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

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

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

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

Проверка результата и отладка

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

Для обработчиков событий проверка другая: установите точку останова в ОбработкаПроведения и проведите документ в отладке. Если точка не сработала — почти наверняка обработчик размещён не в модуле объекта либо у документа отключено проведение в свойствах. Аналогично для менеджера: откройте элемент через выбор в поле ввода и проверьте срабатывание ОбработкаПолученияДанныхВыбора.

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

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

Компиляция модуля в конфигураторе
Норма

Ошибок нет, метод доступен в точке вызова

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

«Переменная не определена» или «Метод объекта не обнаружен» — код не в том модуле

Срабатывание обработчика события в отладчике
Норма

Точка останова в ОбработкаПроведения срабатывает при проведении

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

Точка не срабатывает — обработчик не в модуле объекта или проведение отключено

Производительность массовой операции
Норма

Обработка ссылок идёт запросами без ПолучитьОбъект()

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

В цикле вызывается ПолучитьОбъект() — лишняя нагрузка на сервер

Итог

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

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

Частые вопросы

Можно ли вызвать процедуру модуля объекта, не создавая объект?

Нет. Процедуры модуля объекта существуют только в контексте загруженного экземпляра. Если объект не нужен для логики — перенесите процедуру в модуль менеджера или общий модуль и передавайте данные параметрами.

Куда поместить функцию печати документа?

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

Почему ОбработкаПроведения не вызывается, хотя код написан?

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

Что лучше для общей логики нескольких документов — модуль менеджера или общий модуль?

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

Доступен ли ЭтотОбъект в модуле менеджера?

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

Можно ли вызвать метод менеджера с клиента в тонком клиенте?

Напрямую — нет, менеджер доступен только на сервере. Из клиентского кода формы вызовите серверную процедуру модуля формы с директивой &НаСервере, а уже в ней обратитесь к методу менеджера.