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

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

Что такое контекст модуля в 1С и как им пользоваться

Что такое контекст модуля в 1С: виды модулей, директивы компиляции, область видимости переменных и процедур, типичные ошибки и практические примеры.

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

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

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

Из чего состоит контекст модуля

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

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

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

Виды модулей и их контексты

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

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

Тип модуляЧто доступно в контекстеГде выполняется
Общий модульТолько объявленные в нём процедуры и глобальный контекстКлиент или сервер (по флагам свойств)
Модуль объектаРеквизиты, табличные части, ДополнительныеСвойстваСервер (в тонком клиенте)
Модуль формыРеквизиты формы, элементы, ЭтаФормаКлиент и сервер (по директивам)
Модуль менеджераМетоды менеджера объектаСервер
Модуль приложенияГлобальные обработчики событий приложенияКлиент

Выбор модуля для размещения кода — это выбор контекста. Бизнес-логику, работающую с данными, принято размещать в модулях объектов и серверных общих модулях. Интерфейсную логику — в модулях форм. Универсальные вспомогательные функции — в общих модулях с подходящими флагами исполнения.

Директивы компиляции: клиент и сервер

В управляемых формах каждая процедура и функция помечается директивой компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста или &НаКлиентеНаСервереБезКонтекста. Директива указывает платформе, в каком контексте исполнения компилировать и выполнять код.

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

Директива &НаСервереБезКонтекста означает, что процедура выполняется на сервере, но данные формы ей не передаются — это ускоряет вызов, потому что не тратится время на сериализацию формы. Такие процедуры принимают нужные значения параметрами и возвращают результат. Это стандартный приём для операций, которым не нужно читать или менять реквизиты формы.

bsl
&НаСервереБезКонтекста
Функция ПолучитьЦенуНоменклатуры(Номенклатура, ДатаЦены)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ Цена ИЗ РегистрСведений.Цены.СрезПоследних(&Дата, Номенклатура = &Номенклатура)";
    Запрос.УстановитьПараметр("Дата", ДатаЦены);
    Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
    Выборка = Запрос.Выполнить().Выбрать();
    Возврат ?(Выборка.Следующий(), Выборка.Цена, 0);
КонецФункции

Область видимости: экспорт и локальные объявления

По умолчанию процедуры, функции и переменные модуля видны только внутри него — это локальный контекст. Чтобы сделать процедуру или переменную доступной из других модулей, используется ключевое слово Экспорт. Например, процедуры общего модуля с Экспорт можно вызывать из любого места конфигурации через имя модуля: ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Наименование").

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

Типичные ошибки
01
Обращение к запросу или объекту данных из процедуры &НаКлиенте — ошибка компиляции, потому что клиентский контекст не включает работу с базой данных
02
Хранение промежуточных данных в экспортных переменных модуля формы между серверными вызовами — значения теряются при пересоздании контекста
03
Вызов модуля объекта из формы напрямую — модуль объекта недоступен в контексте формы, нужно получать объект через ссылку на сервере
04
Размещение серверной логики в общем модуле с флагом «Клиент» — код либо не скомпилируется, либо будет недоступен там, где ожидается

Контекст формы и передача данных между клиентом и сервером

Модуль формы — самый сложный с точки зрения контекста, потому что он компилируется дважды: в клиентской и в серверной части. Реквизиты формы — единственный «мост» данных между этими контекстами. Когда клиентская процедура вызывает серверную, платформа передаёт реквизиты формы на сервер, там они доступны как свойства ЭтаФорма или напрямую по имени.

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

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

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

Контекст модуля объекта и обработчики событий

Модуль объекта выполняется в серверном контексте при загрузке, записи, проведении и других операциях с объектом. Его контекст — это сами данные объекта: реквизиты доступны по имени без префикса, табличные части перебираются напрямую. Здесь размещают обработчики ОбработкаПроверкиЗаполнения, ПередЗаписью, ПриЗаписи, ОбработкаПроведения.

Ключевое ограничение: из модуля объекта нельзя обращаться к форме и нельзя выводить интерактивные диалоги. Методы Сообщить() и ВызватьИсключение работают, но сообщение пользователь увидит только после завершения серверной операции. Если нужна интерактивность — логика должна быть в форме, а модуль объекта должен лишь возвращать результат или отказываться от операции через параметр Отказ.

Ещё одна особенность — объект ДополнительныеСвойства в контексте модуля объекта. Это структура, через которую в объект передают произвольные данные извне (например, из обработки загрузки), минуя форму. Типовые конфигурации активно используют этот механизм, и при доработках важно не затирать заполненные там значения.

Практические рекомендации по работе с контекстами

Главное правило — минимизировать количество серверных вызовов и объём передаваемых данных. Каждая клиентская процедура, которая в цикле обращается к серверным функциям, генерирует сетевой трафик и замедляет работу. Правильный подход: собрать на клиенте параметры, один раз вызвать серверную процедуру, получить результат и обработать его на клиенте.

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

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

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

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

Проверка модуля в конфигураторе
Норма

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

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

Ошибки компиляции указывают на обращение к объектам вне контекста

Вызов серверной процедуры из клиентской
Норма

Данные передаются и возвращаются, форма обновляется

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

Ошибка сериализации или пустые реквизиты формы на сервере

Работа общего модуля
Норма

Процедуры доступны из нужных мест (клиент/сервер)

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

«Метод объекта не обнаружен» — не совпадают флаги исполнения модуля

Часто задаваемые вопросы

Чем контекст модуля отличается от глобального контекста?

Глобальный контекст — это встроенные функции и объекты платформы (Запрос, Справочники, Документы, функции работы со строками), доступные в любом модуле. Контекст модуля — это то, что объявлено в конкретном модуле плюс унаследованные от типа модуля объекты (реквизиты формы, данные объекта). Глобальный контекст одинаков везде, контекст модуля — индивидуален.

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

Чаще всего две причины: у процедуры нет ключевого слова Экспорт, либо флаги исполнения общего модуля не совпадают с контекстом вызова. Например, из клиентской процедуры формы нельзя напрямую вызвать процедуру общего модуля, у которого установлен только флаг «Сервер», — нужен промежуточный серверный вызов.

Что такое «вызов сервера» и почему его нужно минимизировать?

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

Можно ли из модуля объекта обратиться к форме документа?

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

Когда использовать &НаСервереБезКонтекста вместо &НаСервере?

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

Что происходит с переменными модуля формы между серверными вызовами?

Переменные, объявленные в клиентской части модуля формы, живут, пока открыта форма. Но полагаться на них для передачи данных на сервер нельзя — на сервер они не передаются. Для обмена данными между клиентом и сервером предназначены реквизиты формы, а переменные модуля подходят только для временного хранения в рамках одной стороны.

Итог

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

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