В приложениях 1С, разработанных для работы в толстом клиенте, была распространена практика использования переменных вне тела функций или процедур. Многие к ней привыкли и пользовались простым способом передачи данных между процедурами и функциями.
В тонком клиенте такой способ возможен только между клиентскими процедурами и функциями. Для сокращения изложения далее под словом процедура будем подразумевать или процедуру или функцию, суть дела от этого не меняется. Но платформа не предоставляет такой возможности для серверных процедур. И это правильный подход, который позволяет эффективно использовать вычислительные ресурсы. Однако иногда все-таки было бы удобно использовать механизм межпроцедурного обмена данными через переменные.
Концепции и реализации такого механизма и посвящена данная публикация. Изложить концепцию можно с помощью следующих аналогий:
- обычный (классический) контейнер можно представить в виде ящика, в который можно в любой момент положить какой-либо предмет, извлечь предмет или посмотреть на предмет. Можно еще вытряхнуть все предметы в мусорную корзину )
- виртуальный контейнер аналогичен запаяному стеклянному сосуду с различными предметами внутри. Можно посмотреть, сколько предметов внутри, посмотреть на сам предмет. Но чтобы добавить в него новый предмет, извлечь предмет или проделать еще какие-либо операции над предметом, придется сосуд разбить, вынуть все предметы, выполнить над ними все необходимые манипуляции и запаять в новый сосуд. Причем, раз уж разбивать, удобнее это делать для изменения нескольких предметов сразу. То есть при выполнении манипуляций над предметами, сосуды все время заменяются (контейнер является виртуальным). Постоянным остаётся только то, что предметы запаяны в какой-либо сосуд.
После этой преамбулы перейдем к сути реализации.
В качестве якорей, который держат виртуальные контейнеры, используются параметры сеанса с типом "фиксированное соответствие". Пусть, например одним из якорей будет параметр сеанса с именем "КонтейнерПеременных1". Получать информацию о содержимом виртуального контейнера можно практически мгновенно по ключу соответствия. А чтобы изменить что-либо в контейнере, необходимо выполнить следующие операции:
Соответствие = Новый Соответствие(ПараметрыСеанса.КонтейнерПеременных1);
//.... здесь выполняем манипуляции над Соответствием ...
ПараметрыСеанса.КонтейнерПеременных1 = Новый ФиксированноеСоответствие(Соответствие);
При количестве элементов до нескольких тысяч операции преобразования из фиксированного соответствия в соответствие и обратно выполняются достаточно быстро. Но, все-таки дольше, чем просто получить данные по ключу. И время, необходимое для изменения состояния контейнера, пропорционально количеству элементов в контейнере. Поэтому можно использовать несколько контейнеров - небольшие, состояние которых изменяется часто и большие, которые изменяются редко, но содержат много элементов, данные которых в основном считываются.
Для хранения в контейнере примитивных типов (в том числе ссылок на объекты базы данных) приведенного выше кода достаточно. Если предполагается хранить сложные типы, например таблицу значений, будем сохранять в контейнере только адрес, полученный с помощью функции ПоместитьВоВременноеХранилище(). При пересоздании виртуального контейнера в новый контейнер этот адрес успешно скопируется, а во временном хранилище как лежали какие-либо данные, так и будут продолжать лежать.
Еще о деталях реализации:
Ключ элемента соответствия является "именем" переменной. Таким образом, "именем" переменной может быть произвольная строка, уникальный идентификатор, ссылка на объект базы данных, в общем объект произвольного типа.
Значением элемента фиксированного соответствия является структура со свойстами:
- Время - время создания переменной. Может быть использовано для автоматической "сборки мусора";
- Тип - информация о типе переменной;
- URI - служебное свойство для преобразования информации о типе в Тип конфигурации;
- Область - свойство управления временем жизни переменной. Тип свойства - произвольный.
- Значение или Адрес. Переменные простых типов сохраняются в Значение, для сложных типов
- в свойстве Адрес сохранятся адрес, который вернула функция ПоместитьВоВременноеХранилище().
Изменение переменных возможно поодиночке или пакетное. Скорость пакетного изменения практически не зависит от количества переменных в пакете, поэтому выполняется намного быстрее нескольких одиночных.
Проведенные тесты показывают (см. скриншот к публикации), что при количестве переменных в контейнере до ста, время на изменение переменной является несущественным. А в ряде случаев в контейнере можно разместить тысячу переменных и это не скажется на общей производительности решения. Много это или мало ? Если использовать механизм контейенров в для хранения данных, то есть пытаться заменить им коллекции (таблицы значений, массивы), то ничего хорошего, кроме разочарования от медленной работы приложения мы не получим. Но если рассматривать элементы контейнера именно как переменные (которые "содержат" те же таблицы значений и массивы), то даже сотня элементов - это много ! В реальных прикладных решениях на толстом клиенте, в которых использовались переменные вне тела процедур для передачи данных между ними, в одном модуле не встретишь и десятка таких переменных. С учетом стека вызова различных модулей друг из друга, глобальных переменных для всего приложения, общее количество переменных меньше сотни даже в больших типовых решениях ! Предложенный механизм виртуальных контейнеров переменных позволяет эффективно применять элементы соответствия в качестве глобальных переменных. Поскольку элементы соответствия имеют необходимые качества переменных: имя и значение, позволяют читать и изменять значение, добавлять новые "переменные" и уничтожать ненужные, освобождая занимаемые ими ресурсы. Для автоматизации уничтожения переменных используется одно из их свойств "Область". А то, что в качестве "имени" переменной или "области" можно использовать значение произвольного типа, делает это особенно удобным. Например, если для области использовать значение уникального идентификатора формы, то при закрытии формы можно уничтожить все созданные во время работы формы "переменные" и освободить занимаемые ими ресурсы.