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