Почему обращение к реквизиту через квадратные скобки считается «извратом» и как писать код правильно

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

В практике разработки на платформе 1С:Предприятие часто возникает дилемма: обратиться к свойству объекта напрямую через точку (Объект.ИмяРеквизита) или использовать строковый индекс (Объект["ИмяРеквизита"]). На первый взгляд, результат одинаков, но опытные разработчики часто называют второй вариант «извратом». В этой статье мы подробно разберем, почему возникла такая оценка, в каких ситуациях этот подход действительно вреден, а когда он является единственно правильным решением.

Разберем техническую суть конструкции

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

Проблема рефакторинга и поиска ссылок

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

  1. Поиск ссылок: Если мы используем стандартный инструмент конфигуратора «Найти ссылки», система покажет все места, где используется Объект.ИмяРеквизита. Однако строковое значение "ИмяРеквизита" внутри кавычек найдено не будет. Это создает риск того, что при анализе использования поля вы пропустите важные участки кода.
  2. Переименование: Представим, что бизнес-задача изменилась, и реквизит Сумма нужно переименовать в СуммаДокумента. При использовании механизма «Переименовать» в конфигураторе, платформа автоматически исправит все обращения через точку. Но строки в кавычках останутся прежними. В итоге программа упадет с ошибкой Runtime error уже у пользователя, так как поле "Сумма" перестанет существовать.

Вывод: Использование строк там, где имя реквизита известно заранее, — это «мина замедленного действия» для поддержки кода, которую поможет найти статический анализатор кода.

Производительность и быстродействие системы

Выясним причину, по которой обращение через точку работает быстрее. При прямом обращении Объект.Реквизит адрес свойства в памяти сопоставляется практически мгновенно. В случае с квадратными скобками Объект["Реквизит"] платформе приходится выполнять следующие действия:

В рамках одной операции разница незаметна. Но если мы проанализируем ситуацию с обработкой тысяч строк в цикле, накладные расходы на поиск в таблице свойств могут существенно замедлить алгоритм. Посмотрим на пример кода, который часто встречается в «универсальных» обработках:


Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    // Медленное обращение, если имя известно
    Сумма = СтрокаТЧ["Цена"] * СтрокаТЧ["Количество"]; 
КонецЦикла;

В данном случае правильнее будет написать СтрокаТЧ.Цена, так как структура табличной части «Товары» нам известна в момент написания кода.

Отсутствие статической проверки и подсказок

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

Когда обращение через скобки — это НЕ «изврат»

Важно понимать, что существуют ситуации, когда этот механизм необходим. Это так называемый «полиморфизм» или создание универсальных алгоритмов. Разберем по шагам такие случаи:

  1. Универсальные печатные формы или обработки: Когда ваша процедура должна уметь работать с разными типами документов (используя модификатор управляемых форм), у которых имена реквизитов могут совпадать по смыслу.
  2. Обход метаданных: Если мы программно перебираем все реквизиты объекта.

Рассмотрим пример правильного использования динамического обращения:


Процедура ЗаполнитьРеквизит(Объект, ИмяРеквизита, Значение) Экспорт
    // Здесь имя реквизита приходит извне, мы не знаем его заранее
    // Это правильное использование квадратных скобок
    Попытка
        Объект[ИмяРеквизита] = Значение;
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка заполнения",,, Объект, "Нет такого реквизита!");
    КонецПопытки;
КонецПроцедуры

Альтернативные подходы и стандарты разработки

Чтобы код соответствовал стандартам 1С (БСП) и был надежным, рекомендуем использовать следующие приемы:

1. Использование функции ЗаполнитьЗначенияСвойств()

Если ваша задача — скопировать данные из одного объекта в другой (например, из документа в обработку), не нужно перебирать имена в скобках. Используйте встроенный метод:


// Копирует все совпадающие по именам поля
ЗаполнитьЗначенияСвойств(Получатель, Источник);

Это работает значительно быстрее и безопаснее с точки зрения платформы.

2. Использование функций БСП

В типовых конфигурациях для получения значений реквизитов без загрузки всего объекта в память используется метод ОбщегоНазначения.ЗначениеРеквизитаОбъекта(). Это не только избавляет от «магических строк» в основном коде, но и оптимизирует работу с БД через SQL-запросы.

3. Проверка через Метаданные

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


ИмяПоля = "Сумма";
Если Объект.Метаданные().Реквизиты.Найти(ИмяПоля) <> Неопределено Тогда
    Объект[ИмяПоля] = 100;
КонецЕсли;

Резюме

Подведем итог: использование Объект["Имя"] считается «извратом» только в том случае, если имя реквизита константно. Если вы знаете, что обращаетесь к полю «Склад», пишите Объект.Склад. Это обеспечит вам быструю работу программы, легкость рефакторинга и отсутствие скрытых ошибок. Квадратные скобки оставляйте исключительно для универсальных механизмов, где имя поля определяется в процессе работы программы.

← На главную