При разработке на платформе 1С:Предприятие 8 часто возникает необходимость оптимизировать тяжелые вычисления или запросы, результаты которых не меняются в течение некоторого времени. Для этого используется механизм общего модуля с пометкой Повторное использование возвращаемых значений. Однако при его использовании разработчики часто сталкиваются с тем, что кэш либо не срабатывает, либо вызывает ошибки исполнения. Разберем детально, как работает этот механизм, какие типы данных можно передавать в параметры и как система определяет, нужно ли вычислять функцию заново.
Для начала проанализируем ситуацию, когда нам нужно передать в функцию таблицу или массив для поиска. Рассмотрим стандартные ограничения платформы. Если у общего модуля установлено повторное использование возвращаемых значений, на типы параметров экспортируемых функций накладываются жесткие ограничения. Система не позволит использовать любые типы данных. Допустимыми являются только:
Неопределено, NULL, Булево, Число, Строка, Дата.Важно понимать, что такие типы как Массив, ТаблицаЗначений, Соответствие или ДеревоЗначений не могут быть переданы в качестве параметров. Если вы попытаетесь вызвать функцию с такими параметрами, платформа выдаст ошибку или проигнорирует кэширование в зависимости от версии и контекста вызова.
Выясним, как именно система понимает, что переданная структура идентична той, что уже есть в кэше. Рассмотрим два варианта: сравнение по ссылке (экземпляру) и сравнение по содержимому. Платформа 1С выполняет сравнение структур по содержимому. Это означает следующее:
Рассмотрим пример правильной подготовки параметров для кэшируемой функции. Вместо передачи всей таблицы, мы можем передать структуру с конкретными ссылками для поиска:
// В вызывающем коде
ПараметрыПоиска = Новый Структура;
ПараметрыПоиска.Вставить("Номенклатура", СсылкаНаТовар);
ПараметрыПоиска.Вставить("Склад", СсылкаНаСклад);
Результат = МойКэшируемыйМодуль.НайтиЗначение(ПараметрыПоиска);
В данном случае, если мы создадим новый объект Структура с теми же значениями Номенклатура и Склад в другом месте кода, система успешно найдет результат в кэше.
Проанализируем скрытые ограничения, которые не всегда очевидны из официальной документации. Существуют типы, которые формально кажутся простыми, но могут вызвать проблемы в кэшируемых модулях:
УникальныйИдентификатор (UUID): Несмотря на свою природу, он часто не распознается платформой как подходящий тип для параметров кэша. Если вам необходимо передать идентификатор, рекомендуется преобразовать его в строку с помощью функции Строка().
Тип (Type): Передача объекта, полученного функцией Тип("СправочникСсылка.Контрагенты"), может привести к ошибке. В таких случаях надежнее передавать строковое имя типа или использовать ЗначениеВСтрокуВнутр.
Рассмотрим ситуацию, когда общий модуль имеет флаги Сервер, Вызов сервера и повторное использование На время сеанса. В этом случае возникает эффект разделения кэша. Кэш создается отдельно на стороне клиента и отдельно на стороне сервера.
Важное правило: никогда не изменяйте объекты, полученные из кэшируемых функций. Если вы получите структуру из кэша на клиенте и измените её поле, это изменение сохранится в клиентском кэше. Однако при вызове той же функции с сервера (или через другой клиентский контекст), вы получите исходные, неизмененные данные. Это может привести к трудноуловимым ошибкам в логике приложения.
Посмотрим на проблему с другой стороны — что функция возвращает. Если кэширование установлено На время сеанса, возвращаемое значение не должно содержать объекты, время жизни которых ограничено одним серверным вызовом. К ним относятся:
Запрос и МенеджерВременныхТаблиц.СправочникОбъект, ДокументОбъект и т.п. (вместо них всегда возвращайте ссылки).Если вы вернете СправочникОбъект, то при следующем обращении к кэшу в другом вызове вы получите ошибку, так как контекст того объекта уже уничтожен.
Выясним, как долго данные хранятся в оперативной памяти. Кэш в 1С не бесконечен. Существуют стандартные временные лимиты:
Для программной очистки используется метод:
ОбновитьПовторноИспользуемыеЗначения();
Этот метод полезен, если данные в базе данных, на которых основаны расчеты кэша, изменились, и нам нужно гарантировать актуальность результатов.
Проанализируем вопрос вложенных структур. Использование «структуры в структуре» в качестве параметра недопустимо. Платформа проверяет только первый уровень вложенности на соответствие разрешенным типам. Если внутри структуры-параметра окажется другая структура, кэширование не сработает.
Для повышения надежности работы с возвращаемыми значениями рекомендуется использовать Фиксированные коллекции (ФиксированнаяСтруктура, ФиксированныйМассив). Это защитит данные кэша от случайного изменения вызывающим кодом, так как попытка модификации такого объекта вызовет исключение, а не молчаливое изменение данных в памяти сеанса.
Подводя итог, можно сказать, что механизм повторного использования — это мощный инструмент, требующий строгого соблюдения типов данных. Используйте структуры только с простыми полями, избегайте передачи объектов и всегда помните о разделении кэша между клиентом и сервером.