Как происходит передача переменных по ссылке между клиентом и сервером в 1С?

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

Разработка в среде 1С:Предприятие 8 часто ставит перед программистом интересные вопросы, касающиеся внутреннего устройства платформы. Один из самых фундаментальных вопросов: как переменная может передаваться «по ссылке» (by reference) между клиентом и сервером, если это физически разные процессы, часто работающие на разных компьютерах с разной оперативной памятью?

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

Механизм Call-by-copy-restore: эмуляция ссылок

Для начала разберем ситуацию, которая кажется естественной: мы передаем переменную в процедуру на сервере, меняем ее там, и на клиенте видим измененное значение. Рассмотрим классический пример:


&НаКлиенте 
Процедура НажатиеКнопки(Элемент)
    Перем_А = 1;
    Инкремент(Перем_А);
    Сообщить(Перем_А); // Будет выведено 2
КонецПроцедуры

&НаСервере
Процедура Инкремент(Параметр)
    Параметр = Параметр + 1;
КонецПроцедуры

Посмотрим на это с технической точки зрения. Поскольку клиент и сервер не имеют общей «кучи» (heap), передать прямой указатель на область памяти невозможно. Вместо этого 1С использует стратегию вызова по копированию-восстановлению (call-by-copy-restore). Проанализируем этот процесс по шагам:

  1. Сериализация на клиенте: Перед вызовом сервера платформа упаковывает (сериализует) значение переменной Перем_А в транспортный пакет (обычно это проприетарный двоичный формат или XML/JSON).
  2. Передача данных: Пакет отправляется по сети на сервер.
  3. Десериализация на сервере: Сервер создает в своей памяти временную переменную Параметр и записывает в нее пришедшее значение.
  4. Выполнение кода: Серверная процедура изменяет значение переменной Параметр.
  5. Обратная сериализация: После завершения процедуры сервер видит, что параметр передан без слова Знач, и упаковывает его новое значение обратно в пакет ответа.
  6. Восстановление на клиенте: Клиент получает ответ и перезаписывает исходную переменную Перем_А новым значением.

Таким образом, мы видим не «живую» ссылку, а качественную имитацию, основанную на синхронизации значений до и после вызова.

Особенности работы с ключевым словом Знач

Ключевое слово Знач (Value) указывает платформе, что параметр должен передаваться только «в одну сторону». Но здесь кроется нюанс, который часто путает начинающих разработчиков, особенно при работе с объектами (массивами, структурами, таблицами значений).

Рассмотрим ситуацию, описанную в обсуждении: почему при использовании Знач в массив все равно могут добавляться элементы? Выясним причину, сравнив два типа вызовов.

Сценарий 1: Вызов внутри одного контекста (Клиент -> Клиент)


&НаКлиенте
Процедура ДобавитьВМассивКлиент(Знач Парам)
    Парам.Добавить(1);
КонецПроцедуры

Здесь Знач означает, что в процедуру передается копия переменной. Но поскольку переменная содержит ссылку на объект «Массив», копия переменной будет содержать ссылку на тот же самый объект в памяти. Метод Добавить() изменяет сам объект, поэтому исходный массив на клиенте изменится.

Сценарий 2: Вызов через границу (Клиент -> Сервер)


&НаСервере
Процедура ДобавитьВМассивСервер(Знач Парам)
    Парам.Добавить(1);
КонецПроцедуры

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

Проблема идентичности объектов при сериализации

Проанализируем еще одну тонкую проблему, упомянутую участниками сообщества. При передаче сложных структур данных между клиентом и сервером теряется «идентичность» (ссылочная целостность внутри набора данных). Рассмотрим пример:


&НаКлиенте
Процедура ПроверитьИдентичность()
    Стр = Новый Структура("Ключ", 1);
    Массив = Новый Массив;
    Массив.Добавить(Стр);
    Массив.Добавить(Стр); // В массиве дважды лежит ОДНА И ТА ЖЕ структура
    
    ОбработатьНаСервере(Массив);
КонецПроцедуры

&НаСервере
Процедура ОбработатьНаСервере(Парам)
    // После десериализации Парам[0] и Парам[1] станут РАЗНЫМИ объектами
    Парам[0].Ключ = 100;
    // Значение в Парам[1].Ключ останется равным 1
КонецПроцедуры

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

Правило «правого параметра»

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


&НаКлиенте
Процедура Команда(Команда)
    А = 10;
    Тест(А, А);
    Сообщить(А); 
КонецПроцедуры

&НаСервере
Процедура Тест(П1, П2)
    П1 = П1 + 1; // П1 = 11
    П2 = П2 + 5; // П2 = 15
КонецПроцедуры

Какое значение будет в переменной А на клиенте? Согласно правилам платформы, при возврате управления значения параметров восстанавливаются последовательно слева направо. Таким образом, сначала в А запишется значение 11, а затем оно будет тут же перезаписано значением 15. Платформа всегда отдает приоритет самому правому изменяемому параметру.

Рекомендации по оптимизации

Понимая, что передача параметров без Знач — это всегда двойная пересылка данных по сети (туда и обратно), мы можем сформулировать важные правила:

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

← На главную