При переходе с файловой базы данных на клиент-серверный вариант работы разработчики часто сталкиваются с неожиданным поведением системы. Код, который годами стабильно функционировал в локальном режиме, внезапно начинает вызывать критические ошибки. Одной из самых распространенных проблем является ошибка «Метод объекта не обнаружен» при попытке вызвать экспортную функцию из модуля объекта другой обработки или документа.
В этой статье мы подробно разберем, почему возникает эта проблема, как на работу кода влияют различные режимы работы платформы 1С (файловый и клиент-серверный), в чем разница между Тонким и Толстым клиентом, и как правильно оформлять модули объектов в соответствии со стандартами разработки фирмы «1С».
Рассмотрим классический пример некорректного кода, который часто приводит к ошибке в клиент-серверном режиме. Представим, что у нас есть управляемая форма, из клиентского контекста которой вызывается экспортный метод модуля внешней или встроенной обработки.
Код в модуле управляемой формы:
&НаКлиенте
Функция ПолучитьНастройкиСервераHTTP(СерверОбменаДанных)
// Попытка создания объекта обработки на клиенте
Обработка1 = Обработки.Обработка1.Создать();
СтруктураHTTP = Обработка1.ПолучитьСтруктуруHTTP();
КонецФункции
Код в модуле объекта Обработка1:
&НаСервере
Функция ПолучитьСтруктуруHTTP() Экспорт
// Возврат структуры с настройками подключения
Возврат Новый Структура("Адрес, Порт", "192.168.1.1", 8080);
КонецФункции
В файловой базе данный код может успешно выполняться. Однако при переносе информационной базы на сервер «1С:Предприятия» (под управление SQL) при вызове метода ПолучитьСтруктуруHTTP() система выдает ошибку:
Метод объекта не обнаружен (ПолучитьСтруктуруHTTP)
При этом отладчик в режиме реального времени показывает, что переменная Обработка1 успешно инициализирована и имеет тип ОбработкаОбъект.Обработка1, но сама функция остается недоступной.
---
Выясним причину, почему поведение системы так кардинально отличается в зависимости от режима работы базы данных:
1cv8.exe). Память у них общая. Платформа «прощает» разработчику многие архитектурные ошибки, поскольку физически все методы и данные находятся в одном адресном пространстве компьютера. Вызовы между условным клиентом и условным сервером происходят мгновенно без сериализации данных.1cv8c.exe или 1cv8.exe) и сервер «1С:Предприятия» (рабочий процесс rphost) — это физически разные процессы, которые чаще всего запущены на разных компьютерах. Общение между ними происходит по сети. Передача любых данных требует строгой сериализации (упаковки в транспортный формат) и десериализации. Если метод был исключен платформой из компиляции на стороне клиента, то клиент физически не может вызвать его напрямую, так как в его адресном пространстве этого метода не существует.---
Ключевая ошибка в приведенном коде модуля объекта — использование директивы компиляции &НаСервере. Разберем подробнее, почему это ломает логику работы системы.
В платформе 1С существуют два принципиально разных механизма управления контекстом исполнения кода:
&): К ним относятся &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста.
Важное правило: Директивы компиляции предназначены исключительно для модулей управляемых форм и модулей команд. Использовать их в модулях объектов (справочников, документов, обработок), модулях менеджеров или в общих модулях категорически запрещено!
Когда вы указываете директиву &НаСервере перед функцией в модуле объекта, платформа при компиляции этого модуля на стороне клиента просто «вырезает» (игнорирует) данную функцию. В результате на клиенте объект создается, но нужного метода в нем нет.
#): К ним относятся конструкции вида #Если Сервер Тогда ... #КонецЕсли, #Если Клиент Тогда ....
Эти инструкции осуществляют условную компиляцию кода на этапе сборки модулей. Именно их необходимо использовать в общих модулях и модулях объектов для разделения клиентского и серверного кода.
---
Поведение системы также зависит от того, под каким клиентом запущено приложение:
Создать() для обработки на клиенте. Любое обращение к объектам баз данных должно происходить строго в серверном контексте. Следовательно, в Тонком клиенте модуль объекта обработки всегда компилируется и выполняется исключительно на сервере.&НаСервере, то для толстого клиента эта функция «исчезает» из области видимости, так как толстый клиент компилирует этот модуль у себя локально и игнорирует серверные директивы управляемых форм.---
Рассмотрим, как правильно переписать код, чтобы он стабильно работал в любом режиме (файловом, клиент-серверном, под тонким и толстым клиентами).
По правилам разработки управляемого приложения, создание прикладных объектов и манипуляции с ними должны происходить на сервере. Модуль управляемой формы должен лишь инициировать этот процесс.
Шаг 1. Перепишем модуль управляемой формы. Вызовем серверную функцию формы вместо создания объекта на клиенте:
&НаКлиенте
Процедура ВыполнитьПолучениеНастроек()
// Вызываем серверный контекст формы
СтруктураHTTP = ПолучитьСтруктуруHttpНаСервере();
// Дальнейшая работа с полученной структурой
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСтруктуруHttpНаСервере()
// Создаем объект обработки на сервере, где доступны все ее методы
ОбработкаОбъект = Обработки.Обработка1.Создать();
Возврат ОбработкаОбъект.ПолучитьСтруктуруHTTP();
КонецФункции
Шаг 2. Удалим некорректную директиву компиляции &НаСервере из модуля объекта Обработка1:
// Модуль объекта Обработка1
// Убираем директиву &НаСервере. Функция теперь компилируется в контексте вызова.
Функция ПолучитьСтруктуруHTTP() Экспорт
Возврат Новый Структура("Адрес, Порт", "192.168.1.1", 8080);
КонецФункции
Если ваша конфигурация должна поддерживать работу как в управляемом режиме (Тонкий клиент), так и в обычном (Толстый клиент), необходимо защитить код модуля объекта от попыток некорректного выполнения на стороне клиента.
Для этого весь исполняемый код модуля объекта помещают в специальную обертку препроцессора. Это гарантирует, что тяжелый серверный код не попытается выполниться на клиенте в толстом приложении, а платформа не выдаст ложных ошибок при компиляции.
Разберем пример правильного оформления модуля объекта Обработка1:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Данный блок кода будет скомпилирован только на сервере
// или в контексте толстого клиента/внешнего соединения.
Функция ПолучитьСтруктуруHTTP() Экспорт
// Пример безопасного формирования структуры
ПараметрыПодключения = Новый Структура;
ПараметрыПодключения.Вставить("Сервер", "api.service.ru");
ПараметрыПодключения.Вставить("Порт", 443);
ПараметрыПодключения.Вставить("ИспользоватьSSL", Истина);
Возврат ПараметрыПодключения;
КонецФункции
#Иначе
// Если код попытаются вызвать на тонком клиенте (что недопустимо)
ВызватьИсключение "Недопустимый вызов объекта на клиенте!";
#КонецЕсли
Чтобы избежать подобных ошибок компиляции и видимости методов в будущем, рекомендуем строго придерживаться следующих правил:
&) вне модулей форм и команд.#).&НаСервереБезКонтекста).