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