Как исправить ошибку «Метод объекта не обнаружен» при вызове функции общего модуля в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Каждый разработчик на платформе «1С:Предприятие 8» рано или поздно сталкивается с досадной ошибкой: «Метод объекта не обнаружен». Особенно часто это происходит при попытке вызвать экспортную функцию или процедуру из вновь созданного общего модуля. Вроде бы и ключевое слово Экспорт на месте, и имя модуля написано без ошибок, но система упорно отказывается видеть нужный метод.

В этой статье мы подробно разберем, почему возникает эта ошибка, как работает механизм компиляции общих модулей в клиент-серверной архитектуре и как правильно настроить свойства модуля, чтобы навсегда избавиться от этой проблемы.

Анализ исходной ситуации: в чем классическая ошибка разработчика?

Рассмотрим типичный сценарий, с которым столкнулся автор темы на форуме. Разработчик создал общий модуль с именем КДВЗадачи, написал в нем экспортную функцию для наложения штампа на скан-копию документа и попытался вызвать ее из управляемой формы элемента справочника.

Код в общем модуле выглядел следующим образом:


&НаСервере
Функция НанестиШтампНаСканКопиюОригинала(ДокументСсылка) Экспорт
    // Логика наложения штампа
КонецФункции

При попытке вызвать этот метод из клиента управляемой формы:

КДВЗадачи.НанестиШтампНаСканКопиюОригинала(Объект.Ссылка);

Платформа выдала ошибку: «Метод объекта не обнаружен (НанестиШтампНаСканКопиюОригинала)».

Выясним причину такого поведения системы. Здесь кроется сразу две критические ошибки, связанные с пониманием контекста выполнения кода в 1С.

Причина №1: Использование директив компиляции в общем модуле

Первое и самое важное правило, которое необходимо запомнить: в общих модулях использование директив компиляции (таких как &НаСервере, &НаКлиенте, &НаСервереБезКонтекста) недопустимо и является грубой ошибкой!

Эти директивы предназначены исключительно для модулей управляемых форм и команд. В общих модулях контекст исполнения определяется не директивами в коде, а свойствами (галочками) самого общего модуля в дереве метаданных конфигуратора.

Когда вы ставите директиву &НаСервере в общем модуле, платформа либо игнорирует её (в зависимости от режима совместимости), либо компилирует код некорректно, что приводит к непредсказуемому поведению и ошибкам инициализации методов.

Причина №2: Механизм двух экземпляров (клиент и сервер)

Проанализируем, что происходит, когда у общего модуля одновременно взведены флаги «Клиент (управляемое приложение)» и «Сервер» в свойствах модуля:

  1. При запуске приложения платформа компилирует два абсолютно независимых экземпляра одного и того же общего модуля: один экземпляр создается для работы на клиенте, второй — для работы на сервере.
  2. Если внутри модуля ошибочно прописана директива &НаСервере перед функцией, этот метод физически скомпилируется только в серверном экземпляре модуля.
  3. В клиентском экземпляре модуля эта функция просто отсутствует.
  4. Когда вы вызываете метод с клиента (из управляемой формы), система обращается к клиентскому экземпляру общего модуля КДВЗадачи, не находит там функцию НанестиШтампНаСканКопиюОригинала и закономерно возвращает ошибку «Метод объекта не обнаружен». При этом наличие флага «Вызов сервера» в свойствах модуля не спасает ситуацию, так как клиентский экземпляр перекрывает обращение.

Варианты правильного решения проблемы

В зависимости от того, какие задачи выполняет ваш общий модуль, существует два архитектурно верных решения.

Вариант А: Модуль должен быть чисто серверным (Рекомендуемый подход)

Если ваша функция работает с базой данных, выполняет запросы, изменяет документы или совершает иные «тяжелые» операции, она должна выполняться исключительно на сервере. Для этого выполните следующие шаги:

  1. Откройте свойства общего модуля КДВЗадачи в конфигураторе.
  2. Установите флаг «Сервер».
  3. Установите флаг «Вызов сервера» (это позволит вызывать методы модуля напрямую из клиентского кода управляемых форм).
  4. Полностью снимите флаг «Клиент (управляемое приложение)».
  5. В тексте модуля полностью удалите директиву &НаСервере перед вашей функцией. Код должен выглядеть так:

Функция НанестиШтампНаСканКопиюОригинала(ДокументСсылка) Экспорт
    // Чистый серверный код без директив компиляции
КонецФункции

При такой настройке платформа понимает, что модуль существует только на сервере. Когда вы вызовете его с клиента, система автоматически осуществит вызов сервера (так как взведен соответствующий флаг), выполнит код на сервере и вернет результат на клиент.

Вариант Б: Использование инструкций препроцессора для универсальных модулей

Если общий модуль должен работать и на клиенте, и на сервере (например, это модуль каких-то общих расчетов или работы со строками), но часть кода внутри функции может быть выполнена только на сервере:

  1. В свойствах общего модуля оставьте флаги «Клиент» и «Сервер».
  2. Удалите директиву компиляции &НаСервере.
  3. Для разделения контекста внутри кода используйте инструкции препроцессора (обратите внимание, они начинаются с символа «#»), а не директивы компиляции:

Функция НанестиШтампНаСканКопиюОригинала(ДокументСсылка) Экспорт
    #Если Сервер Тогда
        // Этот блок кода выполнится только на сервере (например, запросы к БД)
        Возврат ВыполнитьНаложениеШтампаНаСервере(ДокументСсылка);
    #Иначе
        // Этот блок выполнится на клиенте
        ВызватьИсключение "Данная операция не может быть выполнена на клиенте!";
    #КонецЕсли
КонецФункции

Важный совет по стандартам разработки 1С: Если логика работы функции на клиенте и сервере кардинально отличается, лучшим решением по стандартам разработки будет разделение кода на два отдельных общих модуля: КДВЗадачиКлиент (свойства: только Клиент) и КДВЗадачиСервер (свойства: Сервер, Вызов сервера).

Другие скрытые причины ошибки «Метод объекта не обнаружен»

Если вы уже убрали директивы компиляции и правильно настроили свойства модуля, но ошибка сохраняется, проанализируем еще несколько неочевидных причин:

Следуя этим правилам и понимая разницу между контекстом выполнения на клиенте и сервере, вы сможете легко проектировать надежную архитектуру ваших прикладных решений и избегать досадных ошибок компиляции кода.

← На главную