В процессе разработки на платформе «1С:Предприятие 8» одной из самых частых задач является организация взаимодействия между различными процедурами и функциями. Типичная ситуация: одна процедура создает объект (например, документ), а вторая должна выполнить с этим объектом дополнительные действия. Разберем подробно, как это реализовать правильно, учитывая архитектуру «клиент-сервер» и производительность системы.
Рассмотрим самый простой и логичный способ. Если у нас есть две процедуры, ПроцедураА и ПроцедураБ, и нам нужно передать результат работы первой во вторую, мы должны объявить переменную в той процедуре, которая их вызывает. Это позволяет хранить значение во «внешнем» по отношению к ним контексте.
Проанализируем пример кода, который реализует эту логику:
&НаСервере
Процедура ВыполнитьДействияНаСервере()
Перем ДокументСсылка; // Объявляем переменную для хранения ссылки
// Вызываем первую процедуру, которая создаст документ и вернет ссылку
ПроцедураА_СоздатьДокумент(ДокументСсылка);
// Передаем полученную ссылку во вторую процедуру
ПроцедураБ_ОбработатьДокумент(ДокументСсылка);
КонецПроцедуры
&НаСервере
Процедура ПроцедураА_СоздатьДокумент(ДокументСсылка)
НовыйДок = Документы.ПриходнаяНакладная.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДата();
НовыйДок.Записать();
ДокументСсылка = НовыйДок.Ссылка; // Присваиваем значение переменной
КонецПроцедуры
&НаСервере
Процедура ПроцедураБ_ОбработатьДокумент(ДокументСсылка)
// Здесь мы уже можем работать с полученной ссылкой
Сообщить("Обработан документ: " + ДокументСсылка);
КонецПроцедуры
В данном случае переменная передается по ссылке. Это означает, что изменения, внесенные в переменную внутри ПроцедураА, будут видны в основной процедуре и, соответственно, переданы в ПроцедураБ.
Выясним важную техническую деталь: почему нельзя вызывать эти серверные процедуры по отдельности прямо с клиента? В управляемом приложении каждый вызов сервера — это дорогостоящая операция. Рассмотрим ситуацию, когда пользователь нажимает кнопку на форме:
ПроцедураА_НаСервере(), вернуть управление на клиент, а затем вызвать ПроцедураБ_НаСервере(). В этом случае мы совершаем два «прыжка» между клиентом и сервером.ВыполнитьКомплексДействийНаСервере(), вызвать её один раз с клиента, а уже внутри неё последовательно вызвать все необходимые серверные процедуры.Рассмотрим подробнее, почему это важно. При каждом переходе с клиента на сервер платформа выполняет сериализацию данных. Весь контекст формы (все реквизиты, таблицы, данные) упаковывается в пакет (обычно в формате XML или JSON), передается по сети, распаковывается на сервере, обрабатывается, и затем тот же процесс происходит в обратном направлении. Если процедур 6 (как в нашем примере), то 6 вызовов вместо одного могут замедлить работу системы в несколько раз.
Разберем ситуацию, когда нам удобнее использовать функции. Если процедура предназначена только для генерации значения, логичнее сделать её функцией. Это делает код более читаемым и понятным.
&НаСервере
Процедура ОсновнойЦикл()
Док = СоздатьНовыйДокумент(); // Функция возвращает значение
ОбработатьДокумент(Док);
КонецПроцедуры
&НаСервере
Функция СоздатьНовыйДокумент()
НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДок.Записать();
Возврат НовыйДок.Ссылка;
КонецФункции
Проанализируем технические особенности, которые часто вызывают ошибки у начинающих разработчиков:
1. Передача по ссылке и использование ключевого слова Знач
По умолчанию в 1С параметры передаются в процедуры по ссылке. Если вы измените параметр внутри процедуры, он изменится и «снаружи». Если вам нужно гарантировать, что исходная переменная останется неизменной, используйте Знач в описании параметров процедуры:
Процедура ОбработатьДанные(Знач ВходнойПараметр)
2. Типы данных: Объект против Ссылки
Это критически важный момент. На сервере вы можете работать с типом ДокументОбъект (который имеет метод Записать()). Однако на клиент этот тип передать нельзя — там существует только ДокументСсылка. Если вы вызываете несколько процедур внутри одного серверного вызова, вы можете передавать между ними именно Объект. Это позволит заполнить его в одной процедуре, изменить в другой и записать всего один раз в самом конце, что существенно снизит нагрузку на базу данных.
3. Использование Структуры для большого количества параметров
Если ваши процедуры «объемные» и требуют передачи 5-10 различных параметров, разберем прием «упаковки». Вместо длинного списка аргументов лучше использовать объект Структура.
// Создаем структуру с параметрами
ПараметрыОперации = Новый Структура;
ПараметрыОперации.Вставить("Документ", СсылкаНаДок);
ПараметрыОперации.Вставить("ДатаСреза", ТекущаяДата());
ПараметрыОперации.Вставить("Склад", ВыбранныйСклад);
// Передаем одну структуру во все процедуры
Процедура_1(ПараметрыОперации);
Процедура_2(ПараметрыОперации);
Такой подход позволяет легко добавлять новые параметры в будущем, не меняя заголовки всех процедур в модуле.
&НаСервере против &НаСервереБезКонтекстаПосмотрим на ситуацию со стороны производительности. Если ваша ПроцедураА и ПроцедураБ не используют реквизиты формы напрямую (например, они работают только с переданными им параметрами), крайне рекомендуется использовать директиву &НаСервереБезКонтекста. В этом случае при вызове с клиента платформа не будет передавать данные всей формы на сервер, что сделает вызов максимально быстрым.
Подведем итог. Для эффективной передачи параметров между процедурами мы должны соблюдать следующие правила:
Объекты (а не Ссылки) внутри серверного контекста для минимизации обращений к БД.Структуры для передачи большого набора параметров.&НаСервере и &НаСервереБезКонтекста.Соблюдение этих рекомендаций позволит создавать гибкие, масштабируемые и быстрые решения на платформе 1С.