Разработка и Конфигурация · 13 мин
Что такое контекст модуля в 1С и как им пользоваться
Что такое контекст модуля в 1С: виды модулей, директивы компиляции, область видимости переменных и процедур, типичные ошибки и практические примеры.
Контекст модуля в 1С — это набор переменных, процедур и функций, объявленных в конкретном модуле, а также условия, при которых этот код выполняется: на клиенте, на сервере, в толстом или тонком клиенте. Когда разработчик пишет код в модуле, платформа формирует для него контекст исполнения, и именно контекст определяет, какие объекты доступны, какие директивы нужны и где физически будет работать код.
Понимание контекста критично, потому что одна и та же процедура в разных модулях ведёт себя по-разному. Код в модуле формы «видит» реквизиты формы и элементы интерфейса, а код в модуле объекта работает с данными документа или справочника, но не имеет доступа к интерфейсу. Попытка обратиться из модуля объекта к форме или из клиентского контекста к запросу к базе данных приведёт к ошибке компиляции или выполнения.
В типовых и самописных конфигурациях ошибки с контекстом — один из самых частых источников проблем у начинающих разработчиков: процедура «не видна» из другого модуля, экспортная переменная не инициализируется, серверный вызов падает из-за недоступного объекта. Все эти ситуации сводятся к непониманию того, в каком контексте выполняется код.
Из чего состоит контекст модуля
Контекст любого модуля складывается из трёх частей. Первая — раздел объявления переменных: здесь описываются переменные уровня модуля, которые доступны всем процедурам и функциям этого модуля. Вторая — раздел процедур и функций, то есть сам исполняемый код. Третья — раздел основной программы: операторы, которые выполняются один раз при инициализации модуля (например, при создании формы или обращении к общему модулю).
Кроме собственных объявлений, в контекст модуля входят унаследованные от платформы объекты. Для модуля формы это реквизиты формы, элементы управления, команды и свойства самой формы. Для модуля объекта — реквизиты и табличные части объекта, стандартные свойства вроде Ссылка, ЭтоНовый(), ДополнительныеСвойства. Для общего модуля унаследованного контекста нет — доступно только то, что объявлено внутри, плюс глобальный контекст платформы (функции работы со строками, датами, запросами и т.д.).
Важно понимать, что контекст формируется в момент компиляции и инициализации модуля, а не в момент написания кода. Если процедура обращается к переменной, которая не объявлена ни в модуле, ни в унаследованном контексте, конфигуратор выдаст ошибку «Переменная не определена» ещё на этапе проверки модуля.
Виды модулей и их контексты
В конфигурации 1С существует несколько типов модулей, и у каждого свой контекст. Общие модули — самые «чистые»: они не привязаны к объектам и служат библиотеками процедур. Модуль объекта (документа, справочника) выполняется при работе с конкретным объектом данных и имеет доступ к его реквизитам напрямую, без обращения через переменную.
Модуль формы работает с интерфейсной частью: реквизитами формы, элементами, командами. Модуль менеджера объекта используется для операций над объектами в целом (например, печать, создание на основании) и выполняется на сервере. Модуль приложения и модуль сеанса отвечают за старт и завершение работы системы. Модуль команды содержит обработчик выполнения команды.
| Тип модуля | Что доступно в контексте | Где выполняется |
|---|---|---|
| Общий модуль | Только объявленные в нём процедуры и глобальный контекст | Клиент или сервер (по флагам свойств) |
| Модуль объекта | Реквизиты, табличные части, ДополнительныеСвойства | Сервер (в тонком клиенте) |
| Модуль формы | Реквизиты формы, элементы, ЭтаФорма | Клиент и сервер (по директивам) |
| Модуль менеджера | Методы менеджера объекта | Сервер |
| Модуль приложения | Глобальные обработчики событий приложения | Клиент |
Выбор модуля для размещения кода — это выбор контекста. Бизнес-логику, работающую с данными, принято размещать в модулях объектов и серверных общих модулях. Интерфейсную логику — в модулях форм. Универсальные вспомогательные функции — в общих модулях с подходящими флагами исполнения.
Директивы компиляции: клиент и сервер
В управляемых формах каждая процедура и функция помечается директивой компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста или &НаКлиентеНаСервереБезКонтекста. Директива указывает платформе, в каком контексте исполнения компилировать и выполнять код.
Клиентский контекст (&НаКлиенте) даёт доступ к элементам формы, диалогам, файловой системе пользователя, но не позволяет напрямую выполнять запросы к базе данных и обращаться к объектам данных (ДокументОбъект, СправочникОбъект). Серверный контекст (&НаСервере) работает с данными, запросами, объектами, но «не видит» интерфейс пользователя напрямую — только реквизиты формы, которые передаются между клиентом и сервером.
Директива &НаСервереБезКонтекста означает, что процедура выполняется на сервере, но данные формы ей не передаются — это ускоряет вызов, потому что не тратится время на сериализацию формы. Такие процедуры принимают нужные значения параметрами и возвращают результат. Это стандартный приём для операций, которым не нужно читать или менять реквизиты формы.
&НаСервереБезКонтекста
Функция ПолучитьЦенуНоменклатуры(Номенклатура, ДатаЦены)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Цена ИЗ РегистрСведений.Цены.СрезПоследних(&Дата, Номенклатура = &Номенклатура)";
Запрос.УстановитьПараметр("Дата", ДатаЦены);
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Возврат ?(Выборка.Следующий(), Выборка.Цена, 0);
КонецФункцииОбласть видимости: экспорт и локальные объявления
По умолчанию процедуры, функции и переменные модуля видны только внутри него — это локальный контекст. Чтобы сделать процедуру или переменную доступной из других модулей, используется ключевое слово Экспорт. Например, процедуры общего модуля с Экспорт можно вызывать из любого места конфигурации через имя модуля: ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Наименование").
Переменные уровня модуля с Экспорт встречаются реже и требуют осторожности: их значение сохраняется, пока живёт контекст модуля (например, пока открыта форма). В клиент-серверной архитектуре это часто приводит к ошибкам, когда разработчик рассчитывает, что переменная «помнит» значение между серверными вызовами, а контекст к этому моменту уже пересоздан.
Контекст формы и передача данных между клиентом и сервером
Модуль формы — самый сложный с точки зрения контекста, потому что он компилируется дважды: в клиентской и в серверной части. Реквизиты формы — единственный «мост» данных между этими контекстами. Когда клиентская процедура вызывает серверную, платформа передаёт реквизиты формы на сервер, там они доступны как свойства ЭтаФорма или напрямую по имени.
Тонкость в том, что на сервере форма существует как объект УправляемаяФорма, и её контекст включает реквизиты, но не включает элементы интерфейса в привычном смысле — на сервере можно менять свойства элементов (видимость, доступность), но нельзя, например, показать диалог. Обратный вызов с сервера на клиент невозможен: серверный код должен вернуть результат, а клиентская процедура — обработать его.
Для передачи сложных данных (таблиц значений, результатов запросов) между сервером и клиентом используют сериализуемые типы: структуры, массивы, таблицы значений через реквизиты формы. Попытка вернуть с сервера несериализуемый объект (например, СправочникОбъект) приведёт к ошибке — такие объекты существуют только в серверном контексте.
- 1Откройте модуль и посмотрите директиву компиляции перед процедурой (&НаКлиенте, &НаСервере и т.д.)
- 2Для общего модуля откройте его свойства и проверьте флаги «Сервер», «Клиент (обычное приложение)», «Клиент (управляемое приложение)»
- 3В отладчике поставьте точку останова и посмотрите заголовок окна отладки — там указано, клиентский или серверный это код
- 4Выполните проверку модуля (Конфигуратор — Проверка конфигурации), чтобы выявить обращения к недоступным в данном контексте объектам
Контекст модуля объекта и обработчики событий
Модуль объекта выполняется в серверном контексте при загрузке, записи, проведении и других операциях с объектом. Его контекст — это сами данные объекта: реквизиты доступны по имени без префикса, табличные части перебираются напрямую. Здесь размещают обработчики ОбработкаПроверкиЗаполнения, ПередЗаписью, ПриЗаписи, ОбработкаПроведения.
Ключевое ограничение: из модуля объекта нельзя обращаться к форме и нельзя выводить интерактивные диалоги. Методы Сообщить() и ВызватьИсключение работают, но сообщение пользователь увидит только после завершения серверной операции. Если нужна интерактивность — логика должна быть в форме, а модуль объекта должен лишь возвращать результат или отказываться от операции через параметр Отказ.
Ещё одна особенность — объект ДополнительныеСвойства в контексте модуля объекта. Это структура, через которую в объект передают произвольные данные извне (например, из обработки загрузки), минуя форму. Типовые конфигурации активно используют этот механизм, и при доработках важно не затирать заполненные там значения.
Практические рекомендации по работе с контекстами
Главное правило — минимизировать количество серверных вызовов и объём передаваемых данных. Каждая клиентская процедура, которая в цикле обращается к серверным функциям, генерирует сетевой трафик и замедляет работу. Правильный подход: собрать на клиенте параметры, один раз вызвать серверную процедуру, получить результат и обработать его на клиенте.
Второе правило — не смешивать контексты в одной процедуре. Если коду нужно и показать диалог, и выполнить запрос, разделите его: клиентская часть собирает данные и показывает результат, серверная — работает с базой. Директива &НаКлиентеНаСервереБезКонтекста подходит только для чистых функций, которые используют исключительно переданные параметры и глобальные функции платформы.
При доработке типовых конфигураций проверяйте, в каком контексте объявлены вызываемые процедуры общих модулей. Если модуль помечен только флагом «Сервер», его нельзя вызвать из клиентской процедуры напрямую — потребуется серверная «прослойка» в форме или отдельный вызов сервера.
Как проверить результат
Ошибок «переменная не определена» и «процедура не обнаружена» нет
Ошибки компиляции указывают на обращение к объектам вне контекста
Данные передаются и возвращаются, форма обновляется
Ошибка сериализации или пустые реквизиты формы на сервере
Процедуры доступны из нужных мест (клиент/сервер)
«Метод объекта не обнаружен» — не совпадают флаги исполнения модуля
Часто задаваемые вопросы
Чем контекст модуля отличается от глобального контекста?
Глобальный контекст — это встроенные функции и объекты платформы (Запрос, Справочники, Документы, функции работы со строками), доступные в любом модуле. Контекст модуля — это то, что объявлено в конкретном модуле плюс унаследованные от типа модуля объекты (реквизиты формы, данные объекта). Глобальный контекст одинаков везде, контекст модуля — индивидуален.
Почему процедура общего модуля «не видна» из формы?
Чаще всего две причины: у процедуры нет ключевого слова Экспорт, либо флаги исполнения общего модуля не совпадают с контекстом вызова. Например, из клиентской процедуры формы нельзя напрямую вызвать процедуру общего модуля, у которого установлен только флаг «Сервер», — нужен промежуточный серверный вызов.
Что такое «вызов сервера» и почему его нужно минимизировать?
Вызов сервера — это обращение из клиентской процедуры к серверной. При каждом вызове данные сериализуются, передаются по сети, выполняется код, результат возвращается обратно. Одиночный вызов незаметен, но вызовы в цикле при обработке сотен строк таблицы могут замедлить операцию в десятки раз. Данные лучше передавать пакетом одним вызовом.
Можно ли из модуля объекта обратиться к форме документа?
Нет, контекст модуля объекта не включает форму. Объект и форма существуют независимо: объект может записываться вообще без формы (из обмена, обработки, фонового задания). Если нужно повлиять на интерфейс, объект должен вернуть информацию через ДополнительныеСвойства или параметры, а форма — обработать её в своих обработчиках.
Когда использовать &НаСервереБезКонтекста вместо &НаСервере?
Используйте «БезКонтекста», когда процедуре не нужны реквизиты формы: она получает всё необходимое через параметры и возвращает результат. Такой вызов быстрее, потому что платформа не сериализует всю форму. Если процедура читает или меняет реквизиты формы — нужна директива &НаСервере с контекстом.
Что происходит с переменными модуля формы между серверными вызовами?
Переменные, объявленные в клиентской части модуля формы, живут, пока открыта форма. Но полагаться на них для передачи данных на сервер нельзя — на сервер они не передаются. Для обмена данными между клиентом и сервером предназначены реквизиты формы, а переменные модуля подходят только для временного хранения в рамках одной стороны.
Что важно запомнить
Контекст модуля — это область видимости и среда выполнения кода: переменные, процедуры и доступные объекты конкретного модуля. Контекст определяется типом модуля и директивами компиляции. Клиент работает с интерфейсом, сервер — с данными; обмен между ними идёт через реквизиты формы и параметры серверных вызовов. Большинство ошибок «переменная не определена» и «метод не обнаружен» — это нарушение границ контекста.