В процессе разработки на платформе 1С:Предприятие часто возникает вопрос о том, где лучше расположить программный код: в модуле объекта или в модуле менеджера. Один из специфических вопросов, который волнует начинающих разработчиков: можно ли передать целый объект (например, СправочникОбъект или ДокументОбъект) в качестве параметра в экспортный метод модуля менеджера. Давайте детально разберем этот вопрос, изучим синтаксические нюансы, ограничения производительности и архитектурные стандарты.
Прежде всего, проанализируем саму постановку вопроса. В 1С:Предприятии модуль менеджера — это не функция и не объект, к которому можно обратиться напрямую. Это контейнер для процедур и функций, относящихся к конкретному типу данных (справочнику, документу и т.д.).
Рассмотрим типичную ошибку в синтаксисе, которую часто совершают новички. Попытка вызвать модуль менеджера как функцию, как показано в примере ниже, приведет к ошибке:
// Ошибочный подход
МойМодульМенеджера(Объект.ПолучитьОбъект());
Правильный подход заключается в вызове конкретной экспортной процедуры или функции, определенной внутри этого модуля. С технической точки зрения, платформа 1С не накладывает никаких ограничений на типы параметров, передаваемых в экспортные методы модулей менеджера. Вы можете передавать туда строки, числа, ссылки, массивы и, конечно же, полноценные объекты.
Посмотрим на пример правильной реализации в модуле менеджера справочника Контрагенты:
// В модуле менеджера справочника Контрагенты
Процедура ВыполнитьСпециальнуюОбработку(ТекущийОбъект) Экспорт
// Здесь ТекущийОбъект имеет тип СправочникОбъект.Контрагенты
ТекущийОбъект.Комментарий = "Обработано в модуле менеджера " + ТекущаяДата();
КонецПроцедуры
Вызов этого метода из внешней обработки или другого модуля будет выглядеть так:
ОбъектКонтрагент = СсылкаНаКонтрагента.ПолучитьОбъект();
Справочники.Контрагенты.ВыполнитьСпециальнуюОбработку(ОбъектКонтрагент);
// Теперь в переменной ОбъектКонтрагент изменен реквизит Комментарий
Выясним, как именно передается объект внутри системы. В рамках одного серверного вызова (когда и вызывающий код, и метод модуля менеджера выполняются на сервере) объект передается по ссылке (как указатель в памяти). Это означает, что:
Записать()).Однако, проанализируем ситуацию с передачей данных между клиентом и сервером. Если вы вызываете серверный метод модуля менеджера с клиента и передаете туда объект, система будет вынуждена сериализовать (упаковать) весь контекст объекта и передать его по сети. Это может существенно замедлить работу, если объект "тяжелый" (например, документ с тысячами строк в табличной части).
Рассмотрим ситуацию, в которой передача объекта в модуль менеджера станет невозможной. Это касается фоновых заданий. Объекты типов СправочникОбъект, ДокументОбъект и другие подобные типы не являются сериализуемыми для передачи между сессиями или в фоновые потоки.
Если вам нужно выполнить обработку объекта в фоновом задании, вы не сможете передать сам объект. Вместо этого следует передать Ссылку (например, СправочникСсылка), а внутри фонового задания, уже в модуле менеджера, получить объект заново с помощью метода ПолучитьОбъект().
Посмотрим на пример правильной логики для фоновых заданий:
// В вызывающем коде
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(СсылкаНаДокумент);
ФоновыеЗадания.Выполнить("Документы.РеализацияТоваровУслуг.ОбработатьДокументФоново", ПараметрыЗадания);
// В модуле менеджера документа
Процедура ОбработатьДокументФоново(СсылкаНаДокумент) Экспорт
Объект = СсылкаНаДокумент.ПолучитьОбъект();
// Логика обработки...
Объект.Записать();
КонецПроцедуры
Проанализируем, когда стоит передавать объект в модуль менеджера, а когда лучше оставить логику в модуле объекта. Согласно стандартам разработки 1С:
ПередЗаписью, ПриЗаписи, ОбработкаПроведения, а также методы заполнения данных. Внутри модуля объекта все реквизиты доступны напрямую (например, просто Наименование = "Новое" вместо Объект.Наименование = "Новое"), что делает код лаконичнее и понятнее.Когда передача объекта в модуль менеджера оправдана:
ДокументОбъект.Зачастую передача всего объекта является избыточной. Рассмотрим более "чистый" с точки зрения архитектуры способ — передачу Структуры. Вместо того чтобы передавать тяжелый объект со всем его контекстом, мы создаем структуру, содержащую только необходимые для расчета данные.
Преимущества передачи структуры:
Пример реализации через структуру:
// В модуле менеджера
Функция РассчитатьСкидку(ДанныеДляРасчета) Экспорт
// ДанныеДляРасчета - это Структура с ключами Сумма, Контрагент, Дата
Если ДанныеДляРасчета.Сумма > 1000 Тогда
Возврат 5;
КонецЕсли;
Возврат 0;
КонецФункции
// Вызов из модуля объекта
Параметры = Новый Структура("Сумма, Контрагент, Дата", СуммаДокумента, Контрагент, Дата);
Скидка = Документы.РеализацияТоваровУслуг.РассчитатьСкидку(Параметры);
Мы выяснили, что передавать объект в модуль менеджера можно, и это не вызывает технических ошибок при соблюдении синтаксиса. Однако всегда стоит учитывать контекст выполнения кода. Для серверных процедур, работающих в рамках одного сеанса, это допустимая практика, особенно в задачах формирования печатных форм. В то же время, для фоновых задач или при необходимости оптимизации трафика между клиентом и сервером, лучше использовать передачу ссылок или структур с данными.
Помните, что использование модуля объекта часто позволяет писать более компактный код за счет прямой доступности реквизитов. Используйте модуль менеджера для тех случаев, когда логика выходит за рамки ответственности одного конкретного экземпляра данных или требуется интеграция с глобальными механизмами системы, такими как подсистема печати.