При разработке расширений в системе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, написанный в модуле менеджера или модуля объекта расширения, отказывается «видеть» общий модуль, который также находится в этом расширении — для таких задач есть инструменты для разработчика и анализатора метаданных. Ситуация осложняется тем, что при запуске отладки из Конфигуратора (через F5) всё может работать корректно, но при обычном запуске пользователем система выдает ошибку: «Переменная не определена» или «Метод объекта не обнаружен» (в таких случаях может помочь анализ конфигураций и расширений на наличие ошибок). Проанализируем причины этой проблемы и разберем по шагам способы её решения.
Основная причина такого поведения кроется в контекстах исполнения кода и настройках компиляции. В системе 1С один и тот же код может выполняться на сервере, на тонком клиенте или в толстом клиенте. Если вызывающий код (например, в модуле менеджера документа) пытается обратиться к общему модулю, который не скомпилирован для текущего контекста, возникнет ошибка.
Разберем ситуацию на примере 1С:Комплексная автоматизация 2.4 (при работе в которой могут возникать специфичные ситуации, такие как ошибка при получении набора регистра сведений аналитики учета номенклатуры) — для выявления таких сбоев есть система автоматического уведомления о программных ошибках. Модуль менеджера документа почти всегда исполняется на стороне сервера. Если в свойствах общего модуля в расширении не установлена галочка «Сервер», серверный контекст просто не будет знать о существовании такого модуля.
Первым делом нам необходимо проверить настройки самого общего модуля в расширении. Рассмотрим, какие флаги должны быть установлены для корректной работы:
Важно: При установке нескольких флагов (например, «Сервер» и «Клиент») следует быть осторожными с кодом внутри модуля. Код должен быть написан так, чтобы он успешно компилировался в обоих контекстах, либо разделен директивами препроцессора.
Если ваша конфигурация должна поддерживать работу как в тонком, так и в толстом клиенте, проанализируем ситуацию с разделением кода. В модуле менеджера или в месте вызова функции полезно явно указывать, для какого клиента предназначен блок кода. Посмотрим на пример правильного оформления вызова:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Тогда
// Этот код выполнится на сервере или в толстом клиенте
Результат = МойОбщийМодульРасширения.ВыполнитьДействие(Параметры);
#Иначе
// Код для тонкого клиента, если логика отличается
Результат = МойОбщийМодульРасширения.ВыполнитьДействиеНаКлиенте(Параметры);
#КонецЕсли
Такой подход позволяет системе однозначно понимать, в какой момент нужно обращаться к общему модулю, и помогает избежать ошибок компиляции в разных режимах запуска.
Если настройки верны, но ошибка повторяется (как описывал автор темы: «помогает запуск из конфигуратора, но потом снова глючит»), мы имеем дело с кэшированием метаданных (кстати, кэширование в платформе применяется на разных уровнях, например, полезно настраивать кэш обработок подбора для ускорения работы). Для диагностики причин таких ошибок есть пошаговая отладка кода 1С в режиме Предприятие. Платформа 1С сохраняет части расширения в локальном кэше пользователя. При динамическом обновлении или работе с расширениями кэш может стать неактуальным.
Проанализируем шаги по очистке:
/ClearCache.Безопасный режим = Ложь.Рассмотрим «костыльный», но иногда спасительный метод, упомянутый в обсуждении. Если система упорно не видит модуль на этапе компиляции, можно использовать функцию Выполнить() или Вычислить(). Это заставляет платформу скомпилировать строку кода непосредственно в момент исполнения (runtime).
Пример реализации такого обхода:
ЗначениеФункции = Неопределено;
ТекстВызова = "МойОбщийМодуль.ИмяФункции(Параметр1, Параметр2)";
// Используем Выполнить для вызова процедуры или присвоения
Выполнить("ЗначениеФункции = " + ТекстВызова);
Внимание: Мы не рекомендуем использовать этот способ как основной. Во-первых, он замедляет работу системы. Во-вторых, вы теряете возможность проверки синтаксиса на этапе разработки — решить проблему поможет проверка синтаксиса через BSL Language Server. Пользуйтесь этим только для диагностики или в самых крайних случаях.
Выясним еще одну деталь: конфликты имен. Если в основной конфигурации есть модуль с таким же именем, как в расширении, или если вы используете свойство Глобальный у общего модуля расширения, платформа может запутаться в приоритетах.
Рекомендуем придерживаться следующих правил:
ПР_ОбщийМодуль или РаботаСДокументами_Расш).ИмяМодуля.ИмяМетода().Экспорт.Для того чтобы функции расширения стабильно видели общий модуль в любом режиме (включая Толстый клиент в КА 2.4), необходимо:
#Если... для разделения клиент-серверной логики.Следуя этим правилам, вы обеспечите стабильную работу своих доработок и избавите пользователей от внезапных ошибок при открытии документов.