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