Как лучше хранить массив данных в управляемой форме 1С

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

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

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

---

Понимание контекста: почему обычный массив в реквизите — это не всегда хорошо

Прежде чем перейти к конкретным способам реализации, давайте проанализируем, как платформа управляемого приложения работает с данными. Любой реквизит управляемой формы, созданный в редакторе, участвует в так называемом контексте формы.

Когда вы выполняете контекстный вызов сервера (например, вызываете процедуру с директивой &НаСервере), платформа автоматически упаковывает (сериализует) все реквизиты формы, передает их по сети на сервер приложений, выполняет код, а затем сериализует измененные данные обратно на клиент. Если вы сохраните массив из сотен или тысяч элементов непосредственно в реквизите формы, этот массив будет «путешествовать» между клиентом и сервером при каждом вашем клике, вызывающем серверную процедуру. Это приводит к избыточному трафику и снижению отзывчивости интерфейса.

Поэтому к выбору способа хранения нужно подходить осознанно. Разберем основные рабочие варианты.

---

Способ 1. Использование реквизита формы типа «Произвольный» и Фиксированного массива

Если вам необходимо иметь постоянный доступ к массиву как на клиенте, так и на сервере в рамках контекста формы, стандартная логика подсказывает использовать реквизит формы произвольного типа.

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

Разберем по шагам, как это реализовать:

  1. В редакторе формы на вкладке «Реквизиты» создадим новый реквизит (например, с именем КэшСтавок).
  2. В колонке «Тип» укажем значение Произвольный.
  3. При получении данных заполним этот реквизит на сервере:

&НаСервере
Процедура ЗаполнитьКэшСтавокНаСервере()
    
    // Получаем обычный массив данных (например, из веб-сервиса)
    ИсходныйМассив = ПолучитьСтавкиИзИнтернета(); 
    
    // Преобразуем его в ФиксированныйМассив и записываем в реквизит формы
    ЭтаФорма.КэшСтавок = Новый ФиксированныйМассив(ИсходныйМассив);
    
КонецПроцедуры

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

Недостатки: Весь массив сериализуется и гоняется по сети туда-обратно при каждом контекстном серверном вызове.

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

---

Способ 2. Клиентские переменные модуля формы (&НаКлиенте Перем)

Один из самых изящных и незаслуженно забытых способов кэширования — объявление локальной переменной в самом верху модуля управляемой формы с директивой компиляции &НаКлиенте.

Давайте посмотрим на практический пример реализации такой схемы:


&НаКлиенте
Перем КэшСтавокЦБ; // Переменная существует только в памяти клиента

&НаКлиенте
Функция ПолучитьСтавкуЗаДату(ЦелеваяДата)
    
    // Ленивая инициализация кэша
    Если КэшСтавокЦБ = Неопределено Тогда
        КэшСтавокЦБ = ПолучитьМассивСтавокССервера();
    КонецЕсли;
    
    // Логика поиска значения в массиве
    Возврат НайтиСтавкуВМассиве(КэшСтавокЦБ, ЦелеваяДата);
    
КонецФункции

Почему это работает эффективно?
Переменная КэшСтавокЦБ создается в оперативной памяти клиентского приложения (в веб-клиенте или тонком клиенте) в момент открытия формы и уничтожается строго при ее закрытии. Платформа никогда не передает эту переменную на сервер при контекстных вызовах. Это идеальный вариант, когда массив нужен исключительно на клиенте (например, для интерактивных расчетов, заполнения визуальных элементов или подсказок).

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


&НаСервереБезКонтекста
Функция РассчитатьСуммуНаСервере(Знач МассивСтавок, Знач СуммаДокумента)
    // Серверная обработка данных без передачи всего контекста формы
    Возврат СуммаДокумента * ПолучитьКоэффициент(МассивСтавок);
КонецФункции

---

Способ 3. Временное хранилище с привязкой к Уникальному Идентификатору формы

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

Идея заключается в том, что сам массив физически лежит в оперативной памяти сервера приложений 1С, а на клиенте в реквизите формы хранится лишь очень короткая текстовая строка — адрес этого хранилища (выглядит как "e1cib/tempstorage/...").

Давайте разберем по шагам, как правильно управлять жизненным циклом такого кэша:


&НаСервере
Процедура ПолучитьИСохранитьДанныеНаСервере()
    
    МассивСтавок = ПолучитьДанныеЦентробанка();
    
    // Помещаем массив во временное хранилище, жестко привязывая его к UID нашей формы
    АдресХранилища = ПоместитьВоВременноеХранилище(МассивСтавок, ЭтаФорма.УникальныйИдентификатор);
    
    // Сохраняем только строковый адрес в реквизит формы (тип Строка)
    ЭтаФорма.АдресКэшаСтавок = АдресХранилища;
    
КонецПроцедуры

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


&НаСервере
Процедура ОбработатьДанныеНаСервере()
    
    Если ЗначениеЗаполнено(ЭтаФорма.АдресКэшаСтавок) Тогда
        МассивСтавок = ПолучитьИзВременногоХранилища(ЭтаФорма.АдресКэшаСтавок);
        // Выполняем полезную работу с массивом
    КонецЕсли;
    
КонецПроцедуры

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

---

Способ 4. Сохранение данных между сеансами работы (для внешних обработок)

Если речь идет о внешней обработке, которая запускается пользователем регулярно, делать сетевой запрос к сайту Центробанка при каждом открытии формы — плохая практика. Платформа предоставляет возможность кэшировать настройки формы.

Для этого мы можем задействовать штатный механизм сохранения данных:

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

&НаСервере
Процедура ПриСохраненииДанныхВНастройкахНаСервере(Настройки)
    
    // Вручную упаковываем наш массив в структуру сохраняемых настроек
    Если ЭтаФорма.КэшСтавок <> Неопределено Тогда
        Настройки.Вставить("СохраненныйМассивСтавок", ЭтаФорма.КэшСтавок);
    КонецЕсли;
    
КонецПроцедуры

&НаСервере
Процедура ПриЗагрузкеДанныхИзНастроекНаСервере(Настройки)
    
    // Извлекаем сохраненный массив при открытии формы
    СохраненныеДанные = Неопределено;
    Если Настройки.Свойство("СохраненныйМассивСтавок", СохраненныеДанные) Тогда
        ЭтаФорма.КэшСтавок = СохраненныеДанные;
    КонецЕсли;
    
КонецПроцедуры

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

---

Способ 5. Использование глобальных параметров приложения БСП

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

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

Давайте проанализируем пример использования этого механизма:


&НаКлиенте
Процедура ИнициализироватьКэшБСП()
    
    ИмяПараметра = "МояВнешняяОбработка.МассивСтавокЦБ";
    
    Если ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
        // Получаем массив один раз за весь сеанс работы программы
        МассивДанных = ПолучитьМассивСтавокССервера();
        ПараметрыПриложения.Вставить(ИмяПараметра, МассивДанных);
    КонецЕсли;
    
    // Теперь массив доступен из любой формы и обработки по ключу ИмяПараметра
    МойМассив = ПараметрыПриложения[ИмяПараметра];
    
КонецПроцедуры

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

---

Резюме: какую стратегию хранения выбрать?

Выбор оптимального способа зависит от архитектурных особенностей вашей задачи:

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

← На главную