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

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

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

Разбор синтаксиса и принципиальная возможность

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

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


// Ошибочный подход
МойМодульМенеджера(Объект.ПолучитьОбъект());

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

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


// В модуле менеджера справочника Контрагенты
Процедура ВыполнитьСпециальнуюОбработку(ТекущийОбъект) Экспорт
    // Здесь ТекущийОбъект имеет тип СправочникОбъект.Контрагенты
    ТекущийОбъект.Комментарий = "Обработано в модуле менеджера " + ТекущаяДата();
КонецПроцедуры

Вызов этого метода из внешней обработки или другого модуля будет выглядеть так:


ОбъектКонтрагент = СсылкаНаКонтрагента.ПолучитьОбъект();
Справочники.Контрагенты.ВыполнитьСпециальнуюОбработку(ОбъектКонтрагент);
// Теперь в переменной ОбъектКонтрагент изменен реквизит Комментарий

Передача по ссылке и влияние на производительность

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

  1. Копирование данных всего объекта не происходит, передается только адрес в памяти, что работает очень быстро.
  2. Любые изменения реквизитов объекта внутри метода модуля менеджера будут видны в вызывающем коде сразу после завершения работы метода (даже если внутри метода не было команды Записать()).

Однако, проанализируем ситуацию с передачей данных между клиентом и сервером. Если вы вызываете серверный метод модуля менеджера с клиента и передаете туда объект, система будет вынуждена сериализовать (упаковать) весь контекст объекта и передать его по сети. Это может существенно замедлить работу, если объект "тяжелый" (например, документ с тысячами строк в табличной части).

Критическое ограничение: фоновые задания и фоновые вызовы

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

Если вам нужно выполнить обработку объекта в фоновом задании, вы не сможете передать сам объект. Вместо этого следует передать Ссылку (например, СправочникСсылка), а внутри фонового задания, уже в модуле менеджера, получить объект заново с помощью метода ПолучитьОбъект().

Посмотрим на пример правильной логики для фоновых заданий:


// В вызывающем коде
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(СсылкаНаДокумент);
ФоновыеЗадания.Выполнить("Документы.РеализацияТоваровУслуг.ОбработатьДокументФоново", ПараметрыЗадания);

// В модуле менеджера документа
Процедура ОбработатьДокументФоново(СсылкаНаДокумент) Экспорт
    Объект = СсылкаНаДокумент.ПолучитьОбъект();
    // Логика обработки...
    Объект.Записать();
КонецПроцедуры

Архитектурный выбор: Модуль объекта против Модуля менеджера

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

  1. Модуль объекта предназначен для логики, тесно связанной с конкретным экземпляром данных. Это обработчики событий ПередЗаписью, ПриЗаписи, ОбработкаПроведения, а также методы заполнения данных. Внутри модуля объекта все реквизиты доступны напрямую (например, просто Наименование = "Новое" вместо Объект.Наименование = "Новое"), что делает код лаконичнее и понятнее.
  2. Модуль менеджера предназначен для операций над сущностью в целом (например, печать, поиск, аналитические расчеты).

Когда передача объекта в модуль менеджера оправдана:

Альтернативный подход: Передача Структуры

Зачастую передача всего объекта является избыточной. Рассмотрим более "чистый" с точки зрения архитектуры способ — передачу Структуры. Вместо того чтобы передавать тяжелый объект со всем его контекстом, мы создаем структуру, содержащую только необходимые для расчета данные.

Преимущества передачи структуры:

Пример реализации через структуру:


// В модуле менеджера
Функция РассчитатьСкидку(ДанныеДляРасчета) Экспорт
    // ДанныеДляРасчета - это Структура с ключами Сумма, Контрагент, Дата
    Если ДанныеДляРасчета.Сумма > 1000 Тогда
        Возврат 5;
    КонецЕсли;
    Возврат 0;
КонецФункции

// Вызов из модуля объекта
Параметры = Новый Структура("Сумма, Контрагент, Дата", СуммаДокумента, Контрагент, Дата);
Скидка = Документы.РеализацияТоваровУслуг.РассчитатьСкидку(Параметры);

Подведем итоги

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

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

← На главную