Каждый разработчик на платформе «1С:Предприятие 8» рано или поздно сталкивается с досадной ошибкой: «Метод объекта не обнаружен». Особенно часто это происходит при попытке вызвать экспортную функцию или процедуру из вновь созданного общего модуля. Вроде бы и ключевое слово Экспорт на месте, и имя модуля написано без ошибок, но система упорно отказывается видеть нужный метод.
В этой статье мы подробно разберем, почему возникает эта ошибка, как работает механизм компиляции общих модулей в клиент-серверной архитектуре и как правильно настроить свойства модуля, чтобы навсегда избавиться от этой проблемы.
Рассмотрим типичный сценарий, с которым столкнулся автор темы на форуме. Разработчик создал общий модуль с именем КДВЗадачи, написал в нем экспортную функцию для наложения штампа на скан-копию документа и попытался вызвать ее из управляемой формы элемента справочника.
Код в общем модуле выглядел следующим образом:
&НаСервере
Функция НанестиШтампНаСканКопиюОригинала(ДокументСсылка) Экспорт
// Логика наложения штампа
КонецФункции
При попытке вызвать этот метод из клиента управляемой формы:
КДВЗадачи.НанестиШтампНаСканКопиюОригинала(Объект.Ссылка);
Платформа выдала ошибку: «Метод объекта не обнаружен (НанестиШтампНаСканКопиюОригинала)».
Выясним причину такого поведения системы. Здесь кроется сразу две критические ошибки, связанные с пониманием контекста выполнения кода в 1С.
Первое и самое важное правило, которое необходимо запомнить: в общих модулях использование директив компиляции (таких как &НаСервере, &НаКлиенте, &НаСервереБезКонтекста) недопустимо и является грубой ошибкой!
Эти директивы предназначены исключительно для модулей управляемых форм и команд. В общих модулях контекст исполнения определяется не директивами в коде, а свойствами (галочками) самого общего модуля в дереве метаданных конфигуратора.
Когда вы ставите директиву &НаСервере в общем модуле, платформа либо игнорирует её (в зависимости от режима совместимости), либо компилирует код некорректно, что приводит к непредсказуемому поведению и ошибкам инициализации методов.
Проанализируем, что происходит, когда у общего модуля одновременно взведены флаги «Клиент (управляемое приложение)» и «Сервер» в свойствах модуля:
&НаСервере перед функцией, этот метод физически скомпилируется только в серверном экземпляре модуля.КДВЗадачи, не находит там функцию НанестиШтампНаСканКопиюОригинала и закономерно возвращает ошибку «Метод объекта не обнаружен». При этом наличие флага «Вызов сервера» в свойствах модуля не спасает ситуацию, так как клиентский экземпляр перекрывает обращение.В зависимости от того, какие задачи выполняет ваш общий модуль, существует два архитектурно верных решения.
Если ваша функция работает с базой данных, выполняет запросы, изменяет документы или совершает иные «тяжелые» операции, она должна выполняться исключительно на сервере. Для этого выполните следующие шаги:
КДВЗадачи в конфигураторе.&НаСервере перед вашей функцией. Код должен выглядеть так:
Функция НанестиШтампНаСканКопиюОригинала(ДокументСсылка) Экспорт
// Чистый серверный код без директив компиляции
КонецФункции
При такой настройке платформа понимает, что модуль существует только на сервере. Когда вы вызовете его с клиента, система автоматически осуществит вызов сервера (так как взведен соответствующий флаг), выполнит код на сервере и вернет результат на клиент.
Если общий модуль должен работать и на клиенте, и на сервере (например, это модуль каких-то общих расчетов или работы со строками), но часть кода внутри функции может быть выполнена только на сервере:
&НаСервере.
Функция НанестиШтампНаСканКопиюОригинала(ДокументСсылка) Экспорт
#Если Сервер Тогда
// Этот блок кода выполнится только на сервере (например, запросы к БД)
Возврат ВыполнитьНаложениеШтампаНаСервере(ДокументСсылка);
#Иначе
// Этот блок выполнится на клиенте
ВызватьИсключение "Данная операция не может быть выполнена на клиенте!";
#КонецЕсли
КонецФункции
Важный совет по стандартам разработки 1С: Если логика работы функции на клиенте и сервере кардинально отличается, лучшим решением по стандартам разработки будет разделение кода на два отдельных общих модуля: КДВЗадачиКлиент (свойства: только Клиент) и КДВЗадачиСервер (свойства: Сервер, Вызов сервера).
Если вы уже убрали директивы компиляции и правильно настроили свойства модуля, но ошибка сохраняется, проанализируем еще несколько неочевидных причин:
КДВЗадачи.ИмяМетода() вызовет ошибку. К методам глобальных модулей обращаются напрямую: ИмяМетода(), без указания имени модуля через точку.Если), весь модуль целиком не сможет скомпилироваться платформой. В этом случае попытка вызвать любую рабочую функцию из этого модуля приведет к ошибке «Метод объекта не обнаружен». Перед запуском обязательно делайте проверку конфигурации (сочетание клавиш Ctrl + F7).Следуя этим правилам и понимая разницу между контекстом выполнения на клиенте и сервере, вы сможете легко проектировать надежную архитектуру ваших прикладных решений и избегать досадных ошибок компиляции кода.