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