Чем заменить глобальные переменные при переходе на управляемые формы в 1С?

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

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

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

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

Разберем классический пример переменной глТекущийПользователь или данных об оборудовании (глСерверТО). В обычном приложении к ним обращались из любой точки конфигурации. В управляемом приложении для получения таких условно-постоянных значений стандартным подходом является использование общего модуля с повторным использованием возвращаемых значений.

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

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

Посмотрим на практический пример реализации такого механизма. Сначала создадим функцию в модуле с кэшированием ПользователиПовтИсп:


Функция ТекущийПользователь() Экспорт
    // Значение будет получено из базы или параметров сеанса только при первом обращении
    Возврат ПараметрыСеанса.ТекущийПользователь;
КонецФункции

Теперь создадим функцию-обертку в клиентском модуле ПользователиКлиент:


Функция ТекущийПользователь() Экспорт
    // Первый вызов сделает серверный вызов и закэширует результат на клиенте
    Возврат ПользователиПовтИсп.ТекущийПользователь();
КонецФункции

Аналогично добавим функцию в серверный модуль ПользователиСервер:


Функция ТекущийПользователь() Экспорт
    // На сервере вызов будет брать результат из серверного кэша
    Возврат ПользователиПовтИсп.ТекущийПользователь();
КонецФункции

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

Использование параметров сеанса для серверного контекста

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

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

  1. Ленивая инициализация: не следует инициализировать все параметры сеанса при старте программы в процедуре ПриНачалеРаботыСистемы. Инициализацию нужно выполнять строго в модуле сеанса внутри обработчика УстановкаПараметровСеанса.
  2. Проверка запрашиваемых параметров: платформа передает в обработчик массив ТребуемыеПараметры. Инициализировать нужно только те значения, к которым система обратилась в данный момент. Это исключает замедление старта сеанса.
  3. Контроль объема памяти: каждый параметр сеанса постоянно удерживается в оперативной памяти рабочего процесса сервера для каждого подключенного пользователя. Не сохраняйте в них объемные выборки и таблицы.

Разберем пример правильной инициализации параметра сеанса в модуле сеанса:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    Если ТребуемыеПараметры = Неопределено 
        Или ТребуемыеПараметры.Найти("ТекущийПользователь") <> Неопределено Тогда
        
        УстановитьПривилегированныйРежим(Истина);
        ПараметрыСеанса.ТекущийПользователь = ПользователиСервер.ОпределитьТекущегоПользователя();
        УстановитьПривилегированныйРежим(Ложь);
        
    КонецЕсли;
    
КонецПроцедуры

Механизмы Библиотеки стандартных подсистем (БСП)

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

Вместо создания множества отдельных запросов к серверу БСП собирает данные в единый пакет при входе пользователя. Разберем порядок действий:

  1. В общем модуле ОбщегоНазначенияПереопределяемый находим процедуру ПриДобавленииПараметровРаботыКлиентаПриЗапуске.
  2. Добавляем нужные прикладные значения в переданный параметр Параметры, который представляет собой структуру.
  3. На стороне клиента обращаемся к этим данным без серверных вызовов через методы подсистемы базовой функциональности.

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


Процедура ПриДобавленииПараметровРаботыКлиентаПриЗапуске(Параметры) Экспорт
    
    Параметры.Вставить("ИспользоватьСкидки", Константы.ИспользоватьСкидки.Получить());
    Параметры.Вставить("ОсновнойСклад", ПользователиСервер.ПолучитьОсновнойСкладПользователя());
    
КонецПроцедуры

На стороне клиента в управляемых формах или клиентских общих модулях чтение выполняется следующим образом:

ОсновнойСклад = СтандартныеПодсистемыКлиент.ПараметрКлиента("ОсновнойСклад");

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


СтандартныеПодсистемыКлиент.УстановитьПараметрКлиента("ОсновнойСклад", НовыйСклад);

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

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

  1. Временное хранилище: для передачи тяжелых структур или массивов между сервером, клиентом и контекстами форм вызывается ПоместитьВоВременноеХранилище(). Полученный строковый адрес (GUID) передается в параметрах открытия формы или процедуры. При привязке к УникальныйИдентификатор формы данные автоматически очищаются сборщиком мусора при ее закрытии.
  2. Оповещения форм: для синхронизации состояния открытых окон вместо разделяемых переменных используется метод Оповестить() на клиенте и обработчик ОбработкаОповещения в целевых формах. Это устраняет зависимость интерфейса от глобального состояния памяти.
  3. Хранилище общих настроек: если переменную требуется сохранять между перезапусками системы персонально для пользователя или всей базы, используются системные объекты ХранилищеОбщихНастроек или ХранилищеСистемныхНастроек с методами .Сохранить() и .Загрузить().

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

← На главную