В процессе разработки на платформе «1С:Предприятие 8» многие программисты сталкиваются с ситуацией, когда процедура, определенная в глобальном общем модуле с директивой #Если Сервер Тогда, оказывается недоступна для вызова из клиентской процедуры того же самого модуля. При этом флаг «Вызов сервера» в свойствах модуля установлен, а сама процедура помечена как Экспорт. Давайте подробно разберем, почему платформа ведет себя именно так, и как правильно организовать архитектуру решения задачи.
Для начала проанализируем, что происходит «под капотом» платформы при запуске приложения. Когда мы помечаем общий модуль флагами «Клиент (управляемое приложение)» и «Сервер», система фактически создает две независимые копии этого модуля в оперативной памяти. Одна копия компилируется в памяти клиентского компьютера (или терминального сеанса), а другая — в оперативной памяти сервера 1С (процесс rphost).
Если модуль помечен как Глобальный, его экспортные методы попадают в глобальное пространство имен платформы. Это означает, что к ним можно обращаться напрямую, без указания имени модуля. Однако здесь кроется главная особенность: поиск метода в глобальном контексте происходит только внутри текущей среды исполнения.
Рассмотрим ситуацию по шагам:
#Если Клиент Тогда.#Если Сервер Тогда, в клиентскую версию модуля просто не попадают. Для клиента их не существует.Логично предположить, что флаг «Вызов сервера» должен решить проблему, инициируя удаленный вызов процедуры на стороне сервера. Однако в случае с глобальными модулями этот флаг игнорируется платформой по умолчанию. Это фундаментальное ограничение архитектуры 1С.
Механизм «Вызов сервера» предназначен для того, чтобы клиент мог «дотянуться» до экспортных методов неглобального серверного модуля. В случае же с глобальным модулем, платформа считает, что вы пытаетесь использовать глобальный контекст текущей среды. Если вы находитесь на клиенте, вы ограничены клиентским глобальным контекстом.
Проанализируем пример некорректной структуры кода в глобальном модуле (назовем его ГлобальныйМодуль, установлены галки Клиент, Сервер, Вызов сервера):
Процедура КлиентскийМетод() Экспорт
// Платформа попытается найти СерверныйМетод() в глобальном контексте клиента.
// Ошибка: метод не найден, так как Вызов сервера для глобальных модулей не работает.
СерверныйМетод();
КонецПроцедуры
#Если Сервер Тогда
Процедура СерверныйМетод() Экспорт
// Какая-то логика на сервере
КонецПроцедуры
#КонецЕсли
Рассмотрим типовую задачу: нам нужно использовать ПодключитьОбработчикОжидания для периодической проверки данных на сервере (например, для получения оповещений пользователем). Как мы знаем, процедура-обработчик ожидания обязана находиться либо в модуле управляемого приложения, либо в модуле формы, либо в глобальном клиентском общем модуле.
Правильная архитектура в данном случае требует разделения ответственности между двумя модулями. Разберем по шагам создание такой структуры:
ОповещенияКлиентГлобальный).
ОповещенияСервер).
Посмотрим на пример кода, который реализует эту схему:
В модуле ОповещенияКлиентГлобальный:
Процедура ОбработчикПроверкиОповещений() Экспорт
// Вызываем серверный метод НЕглобального модуля
// Здесь механизм "Вызов сервера" отработает штатно
ДанныеДляПользователя = ОповещенияСервер.ПолучитьНовыеСообщения();
Если ДанныеДляПользователя.Количество() > 0 Тогда
// Логика отображения оповещения пользователю
КонецЕсли;
КонецПроцедуры
В модуле ОповещенияСервер:
Функция ПолучитьНовыеСообщения() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ..."; // Ваша логика запроса
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Стоит отметить, почему в Толстом клиенте подобный код (смешанный в одном глобальном модуле) иногда может «работать», хотя и выдает предупреждения. В файловом варианте Толстого клиента границы между контекстами клиента и сервера сильно размыты — они фактически выполняются в одном процессе. Платформа может «видеть» методы, которые формально не должны быть доступны. Однако полагаться на это поведение нельзя, так как при переходе на клиент-серверный вариант или использовании Тонкого клиента код неминуемо перестанет работать.
Для обеспечения стабильной работы и соблюдения стандартов разработки 1С, всегда придерживайтесь следующих правил: