К статье
Практический материал

Разработка и Конфигурация · 12 мин

Модуль приложения 1С: где выполняется код

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

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

Ответ на вопрос зависит от типа модуля, настроек его свойств и директив компиляции, указанных перед процедурами и функциями. Общий модуль с флагом «Сервер» исполняется в процессе сервера 1С, модуль формы с директивой &НаКлиенте — в контексте клиентского приложения, а модуль объекта — только на сервере (за редкими исключениями в файловом режиме).

Ниже разберём все типы модулей, способы точно определить контекст исполнения, типичные ошибки и практические приёмы проверки.

Какие среды исполнения существуют в платформе 1С

Платформа 1С:Предприятие 8 работает по клиент-серверной архитектуре. Код может исполняться в трёх основных средах: тонкий клиент, веб-клиент и сервер 1С:Предприятия. В файловом режиме работы роль сервера частично выполняет сам клиентский процесс, но логическое разделение контекстов сохраняется — платформа всё равно проверяет директивы компиляции.

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

Толстый клиент в режиме обычного приложения — отдельный исторический случай: там многие ограничения сняты, и код может работать в «смешанном» режиме. Однако современные конфигурации ориентированы на управляемые формы и тонкий клиент, поэтому дальше речь пойдёт именно о них.

Общие модули: настройка места исполнения через свойства

Общий модуль — самый наглядный пример управления контекстом. В палитре свойств общего модуля есть флаги, которые напрямую определяют, где он будет скомпилирован и выполнен:

  • Клиент (обычное приложение) — модуль доступен в толстом клиенте обычного приложения;
  • Клиент (управляемое приложение) — модуль компилируется на тонком и веб-клиенте;
  • Сервер — модуль выполняется на сервере 1С;
  • Внешнее соединение — модуль доступен при подключении через COM-соединение;
  • Вызов сервера — разрешает вызывать серверные процедуры модуля с клиента.

Если у модуля установлены оба флага — «Клиент» и «Сервер», — платформа скомпилирует его дважды, по разу для каждой среды. Внутри такого модуля можно разделять код директивами компиляции #Если Сервер Тогда ... #КонецЕсли, чтобы разные ветки исполнялись в разных средах.

Флаг «Вызов сервера» критичен для клиент-серверного взаимодействия: без него попытка обратиться к серверному общему модулю из клиентского кода завершится ошибкой «Обращение к процедуре объекта как к функции» или «Переменная не определена». При этом каждый вызов с клиента на сервер — это сетевой обмен, поэтому частые мелкие вызовы заметно замедляют работу.

Модули форм и команд: директивы компиляции

В модулях управляемых форм и команд место исполнения задаётся не свойствами, а директивами перед каждой процедурой и функцией. Директива обязательна — процедура без неё в модуле управляемой формы не скомпилируется.

ДирективаГде выполняетсяОсобенности
&НаКлиентеТонкий или веб-клиентДоступен интерфейс, недоступны запросы и объекты БД
&НаСервереСерверЕсть контекст формы (реквизиты, данные формы)
&НаСервереБезКонтекстаСерверНет данных формы; быстрее, дешевле по ресурсам
&НаКлиентеНаСервереБезКонтекстаКлиент и серверКод компилируется в обеих средах; только в модулях команд

Практическое правило: всё, что связано с интерфейсом (предупреждения, открытие форм, работа с файлами на компьютере пользователя), размещается в &НаКлиенте. Всё, что связано с данными (запросы, чтение и запись объектов, расчёты по базе), — в &НаСервере или &НаСервереБезКонтекста. Между ними данные передаются через параметры процедур.

Как вызывается серверный код из клиентской процедуры

Типовой шаблон обмена выглядит так: клиентская процедура собирает параметры, вызывает серверную функцию, та возвращает простые сериализуемые значения (строки, числа, структуры, массивы), и клиент использует результат для обновления интерфейса. Передать на клиент объект типа «СправочникОбъект» или результат запроса нельзя — платформа выдаст ошибку о недопустимом типе параметра.

bsl
&НаКлиенте
Процедура РассчитатьСкидку(Команда)
	Скидка = ПолучитьСкидкуНаСервере(Объект.Контрагент);
	Объект.ПроцентСкидки = Скидка;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСкидкуНаСервере(Контрагент)
	// запрос к базе данных
	Возврат РезультатСкидки;
КонецФункции

Модули объектов, менеджеров и модуль сеанса

Модуль объекта (документа, справочника, обработки) выполняется только на сервере. Это логично: модуль объекта работает с данными при записи, проведении, удалении — все эти операции происходят в серверном контексте. Директивы компиляции в модуле объекта не используются и не требуются.

Модуль менеджера (например, общего назначения прикладного объекта) также исполняется на сервере. Туда выносят функции получения данных: поиск по реквизитам, формирование печатных форм, подбор значений по умолчанию.

Модуль сеанса — особый случай: он выполняется на сервере в момент установки соединения, до открытия какого-либо интерфейса. Его событие «УстановкаПараметровСеанса» может вызываться многократно в течение инициализации, поэтому код в нём должен быть максимально быстрым и отказоустойчивым. Ошибка в модуле сеанса делает вход в базу невозможным для всех пользователей.

Как точно определить, где выполняется конкретный код

Есть несколько надёжных способов проверить контекст исполнения, не догадываясь по косвенным признакам.

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

В отладчике самый наглядный признак — окно подключённых предметов отладки. Если точка останова срабатывает в процессе сервера, вы увидите соответствующее подключение; если код клиентский — сработает отладка клиентского приложения. Автоматическое подключение к серверу включается в настройках отладки, и без него серверные точки останова просто игнорируются.

Косвенный признак — текст ошибки. «Процедура или функция с указанным именем не определена» при заведомо существующей процедуре почти всегда означает, что вызываемый код скомпилирован в другой среде: например, клиент пытается вызвать серверный общий модуль без флага «Вызов сервера».

Контрольные точки

Как проверить результат

Вызов серверного общего модуля с клиента
Норма

Код выполняется, данные возвращаются

Тревожный признак

Ошибка «Переменная не определена» — нет флага «Вызов сервера»

Директива процедуры в модуле формы
Норма

Директива указана, модуль компилируется без ошибок

Тревожный признак

Ошибка компиляции «Ожидается директива компиляции»

Передача данных с сервера на клиент
Норма

Передаются примитивные типы, структуры, массивы

Тревожный признак

Ошибка о недопустимом типе параметра при передаче объекта БД

Типичные ошибки при выборе места исполнения

Типичные ошибки
01
Размещение запроса к базе в клиентской процедуре — код не компилируется или падает с ошибкой; запросы доступны только на сервере.
02
Серверная процедура с контекстом формы там, где хватило бы «без контекста» — каждый вызов тащит на сервер всё состояние формы, что замедляет работу.
03
Десятки мелких серверных вызовов в цикле на клиенте — каждый вызов это сетевой обмен; правильнее собрать данные одним вызовом.
04
Флаг «Привилегированный режим» на модуле без необходимости — пользователи получают обход прав доступа к данным.
05
Дублирование одной и той же логики в клиентском и серверном модулях вместо одного модуля с обоими флагами — код расходится при доработках.

Отдельная группа проблем связана с асинхронной моделью. В тонком и веб-клиенте модальные вызовы (Вопрос, Предупреждение без обработчика) запрещены в большинстве режимов совместимости, а работа с файлами выполняется асинхронно через описания оповещений. Код, написанный «по-старому» синхронно, в веб-клиенте просто не заработает.

Как выбрать правильное место для нового кода

Маршрут решения

Как выбрать действие

Коду нужен запрос к базе, запись объекта или проведениеРазмещайте на сервере: общий серверный модуль или &НаСервереБезКонтекста
Код работает с интерфейсом, файлами пользователя, диалогамиРазмещайте на клиенте: &НаКлиенте или клиентский общий модуль
Функция чистая, без обращения к БД и интерфейса (расчёты, строки, даты)Общий модуль с флагами «Клиент» и «Сервер» — код будет доступен везде без серверных вызовов
Операция массовая и длительнаяСервер, при необходимости — фоновое задание через ДлительныеОперации, чтобы не блокировать клиента

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

При сомнениях ориентируйтесь на стандарты разработки типовых конфигураций: клиентские общие модули имеют постфикс «Клиент», серверные — без постфикса или «ВызовСервера», модули с двойным контекстом — «КлиентСервер». Такая именование сразу подсказывает, где выполняется код, ещё до открытия свойств.

Итог

Что важно запомнить

Место исполнения модуля в 1С задаётся типом модуля, его свойствами и директивами компиляции. Общие модули настраиваются флагами «Клиент»/«Сервер»/«Вызов сервера», процедуры форм — директивами &НаКлиенте и &НаСервере, модули объектов и сеанса всегда серверные. Проверить контекст проще всего через свойства модуля и отладчик, а главная ошибка — попытка выполнить серверную логику на клиенте и наоборот.

Частые вопросы

Почему возникает ошибка «Переменная не определена» при вызове общего модуля?

Чаще всего вызываемый общий модуль не скомпилирован в той среде, откуда идёт вызов. Если вызов идёт с клиента в серверный модуль, проверьте флаг «Вызов сервера» в свойствах модуля. Если модуль клиентский, а вызывается с сервера — установите флаг «Сервер» или перенесите вызов в клиентский контекст.

Чем &НаСервере отличается от &НаСервереБезКонтекста?

Процедура &НаСервере имеет доступ к данным формы (реквизитам, объекту формы), но при каждом вызове состояние формы сериализуется и передаётся на сервер — это дорого. &НаСервереБезКонтекста работает без данных формы, вызов легче и быстрее, поэтому для операций, которым не нужны реквизиты формы, следует выбирать именно его.

Можно ли выполнить код модуля объекта на клиенте?

Нет, модуль объекта в управляемом приложении всегда выполняется на сервере — при записи, проведении и других операциях с данными. Если нужна логика, доступная и на клиенте, её выносят в общий модуль с флагами «Клиент» и «Сервер».

Как понять в отладчике, на сервере или клиенте сработала точка останова?

Откройте в конфигураторе меню «Отладка → Подключение» и посмотрите список подключённых предметов отладки: там указан тип процесса — клиентское приложение или сервер. Также убедитесь, что в настройках отладки включено автоматическое подключение к серверным процессам, иначе серверные точки останова не сработают.

Почему код с функцией Вопрос() не работает в тонком клиенте?

Синхронные модальные вызовы запрещены в тонком и веб-клиенте при современных режимах совместимости. Вместо Вопрос() используйте асинхронный метод ПоказатьВопрос() с описанием оповещения — обработчик продолжения выполнится уже на клиенте после ответа пользователя.

Где выполняется модуль команды формы?

Зависит от директивы обработчика. Команда может иметь клиентскую часть (&НаКлиенте) для подготовки и серверную (&НаСервере) для работы с данными. Допустима и директива &НаКлиентеНаСервереБезКонтекста — тогда код компилируется в обеих средах, но не имеет доступа ни к контексту формы, ни к специфике каждой среды.