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