Разработка и Конфигурация · 11 мин
Директивы компиляции в 1С: назначение, виды и практика применения
Что такое директивы компиляции в 1С: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста. Как выбирать директиву, типичные ошибки и проверка результата.
Директива компиляции — это инструкция в модуле формы или команды, которая указывает платформе 1С, где именно должен исполняться процедура или функция: на клиенте, на сервере или в обоих контекстах. Она записывается перед объявлением метода в виде амперсанда с ключевым словом, например &НаСервере, и напрямую определяет, какие объекты, типы и вызовы доступны внутри кода.
Потребность в директивах возникла с появлением управляемых форм и тонкого клиента. В обычных формах весь код исполнялся на клиенте, а в управляемом приложении логика разделена: интерфейс живёт на клиенте, данные и запросы — на сервере. Компилятору нужно явно знать, в каком окружении собирать каждый метод, иначе вызов серверной функции из клиентского кода или обращение к недоступному типу приведёт к ошибке ещё на этапе проверки модуля.
Понимание директив критично для любого разработчика, который дорабатывает управляемые формы: от правильного выбора зависят производительность (число серверных вызовов), безопасность (нельзя доверять клиенту прямые запросы к базе) и сама работоспособность кода. Ниже разберём все виды директив, правила выбора и типичные ошибки.
Какие директивы компиляции существуют в 1С
Платформа предоставляет пять основных директив для модулей управляемых форм и команд. Каждая задаёт собственный контекст исполнения со своими ограничениями.
&НаКлиенте— код исполняется на клиенте. Доступны элементы формы, диалоги, файловые операции на компьютере пользователя. Недоступны запросы к базе данных напрямую и большинство прикладных типов.&НаСервере— код исполняется на сервере с доступом к данным формы. Можно работать с реквизитами формы, преобразовывать их в прикладные объекты, выполнять запросы.&НаСервереБезКонтекста— серверный метод без передачи данных формы. Реквизиты формы недоступны, зато вызов дешевле: не сериализуются данные формы в обе стороны.&НаКлиентеНаСервереБезКонтекста— универсальная директива: метод компилируется и на клиенте, и на сервере, но без контекста формы. Используется для вспомогательных расчётов, не зависящих от данных формы.&НаКлиентеНаСервере— встречается в модулях команд; метод доступен в обоих контекстах с учётом ограничений.
Директива ставится строго перед ключевым словом Процедура или Функция. Пропуск директивы в модуле управляемой формы — ошибка компиляции: платформа не сможет определить контекст.
Как выбрать директиву для конкретной задачи
Выбор определяется двумя вопросами: нужны ли данные формы и где физически должны выполняться операции. Обращение к базе данных, запросы, работа с прикладными объектами (СправочникОбъект, ДокументОбъект) возможны только на сервере. Работа с элементами интерфейса, оповещениями пользователя, файловой системой клиента — только на клиенте.
Как выбрать директиву
Типовой приём — разделение одной бизнес-операции на два метода. Клиентский обработчик команды собирает ввод пользователя, затем вызывает серверную процедуру, которая работает с базой, и результат возвращается на клиент для отображения. Такой шаблон минимизирует число серверных вызовов: один вызов вместо серии обращений.
&НаКлиенте
Процедура РассчитатьСкидку(Команда)
СуммаСкидки = РассчитатьСкидкуНаСервере(Объект.СуммаДокумента);
Объект.Скидка = СуммаСкидки;
КонецПроцедуры
&НаСервереБезКонтекста
Функция РассчитатьСкидкуНаСервере(Сумма)
// запрос к регистру скидок
Возврат Сумма * 0.05;
КонецФункции
Чем &НаСервереБезКонтекста отличается от &НаСервере на практике
При вызове метода &НаСервере платформа сериализует все данные формы, передаёт их на сервер, а после выполнения — обратно. На формах с большими табличными частями это заметная нагрузка. Метод &НаСервереБезКонтекста получает только явно переданные параметры, поэтому вызов легче и быстрее.
Расплата за скорость — отсутствие доступа к реквизитам и элементам формы. Если внутри метода без контекста понадобилось значение реквизита, его придётся передавать параметром. Попытка обратиться к Объект или Элементы из такого метода вызовет ошибку компиляции.
Инструкции препроцессору: вторая группа директив
Помимо директив контекста, в 1С существуют инструкции препроцессору #Если ... #Тогда ... #КонецЕсли, которые тоже относят к механизму управления компиляцией. Они позволяют включать или исключать фрагменты кода в зависимости от среды исполнения: #Если Сервер Тогда, #Если ТонкийКлиент Тогда, #Если ВебКлиент Тогда, #Если МобильныйКлиент Тогда.
Типичный сценарий — код, который должен работать и в тонком, и в веб-клиенте, но использует возможности, недоступные в веб-клиенте (например, прямой доступ к локальным файлам). С помощью инструкций препроцессору разработчик изолирует такие фрагменты, и модуль успешно компилируется в обеих средах.
#Если ВебКлиент Тогда
ПоместитьФайлВоВременноеХранилище();
#Иначе
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Показать(Новый ОписаниеОповещения("ПослеВыбора", ЭтотОбъект));
#КонецЕслиВажно понимать разницу: директивы с амперсандом определяют контекст целого метода, а инструкции препроцессору — набор строк, которые попадут в скомпилированный модуль для конкретной среды. Комбинируя оба механизма, можно писать переносимый код без дублирования модулей.
Как проверить, что директивы выбраны правильно
Первичная проверка — синтаксический контроль модуля в конфигураторе (меню «Конфигурация → Проверка конфигурации» либо команда проверки модуля). Ошибки вида «Процедура или функция с указанным именем не определена» или недоступность типа в данном контексте почти всегда означают неверную директиву.
Вторая проверка — функциональная: запуск прикладного решения в том клиенте, под который ведётся разработка, и выполнение сценария целиком. Особое внимание уделите веб-клиенту, если он используется: часть кода, спокойно компилирующегося для тонкого клиента, там окажется недоступной.
Как проверить результат
Ошибок компиляции нет ни для одного контекста
Сообщения о недоступности типа или неопределённой процедуре
Операция выполняется без обращений в лишних серверных вызовах
Ошибки времени выполнения или заметные паузы из-за каскада вызовов
Одна клиентская команда вызывает сервер один-два раза
Каждый обращение к данным порождает отдельный вызов в цикле
Типичные ошибки при работе с директивами
Самая частая ошибка — попытка выполнить запрос к базе данных в клиентском методе. Компилятор это остановит, но новички часто «лечат» проблему переносом всего кода на сервер, теряя доступ к интерфейсу. Правильное решение — разделить метод на клиентскую и серверную части.
Отдельная группа проблем — неявные серверные вызовы. Некоторые операции в клиентском коде (например, обращение к данным реквизита составного типа или вызов методов прикладных объектов) незаметно порождают обращение к серверу. В циклах это приводит к «эффекту тормозов», который трудно диагностировать без понимания устройства контекстов.
Удобный приём при доработке типовых форм: сначала напишите всю логику на клиенте, затем вынесите на сервер только обращения к базе. Так проще увидеть границу контекстов и не перетащить на сервер интерфейсные операции.
Ограничения и границы самостоятельной доработки
Директивы компиляции применимы только в модулях управляемых форм и команд. В общих модулях контекст задаётся флагами свойств модуля («Сервер», «Клиент (управляемое приложение)», «Вызов сервера»), а не директивами перед методами. Путаница между этими механизмами — частый источник вопросов: в общем модуле директива &НаСервере перед процедурой не требуется и не используется.
Также помните о безопасности: нельзя переносить на клиент проверки прав, ценообразование или иные критичные проверки «для удобства». Клиентскому коду нельзя доверять — все значимые проверки и изменения данных должны дублироваться или выполняться на сервере, иначе подкованный пользователь сможет обойти ограничения.
Что важно запомнить
Директива компиляции задаёт контекст исполнения метода формы: клиент, сервер или сервер без контекста. Запросы и объекты базы — только на сервере, интерфейс — только на клиенте. Для производительности минимизируйте серверные вызовы и используйте &НаСервереБезКонтекста там, где данные формы не нужны.
Частые вопросы о директивах компиляции 1С
Что будет, если не указать директиву перед процедурой в модуле формы?
Модуль управляемой формы не пройдёт проверку: платформа требует явного указания контекста для каждого метода. В модулях обычных форм директивы не нужны, так как там единственный контекст — клиентский.
Можно ли вызвать серверную процедуру из клиентской?
Да, это штатный механизм: клиентский метод вызывает процедуру с директивой &НаСервере или &НаСервереБезКонтекста, передавая параметры. Обратный вызов — с сервера на клиент — напрямую невозможен; серверный метод должен вернуть результат, а клиентский код его обработает.
Чем &НаКлиентеНаСервереБезКонтекста отличается от общего модуля?
Метод с этой директивой живёт в модуле формы и доступен только ей, тогда как общий модуль доступен всей конфигурации. Если вспомогательная функция нужна нескольким формам, правильнее вынести её в общий модуль с соответствующими флагами контекста.
Почему код работает в тонком клиенте, но падает в веб-клиенте?
Веб-клиент поддерживает не все возможности платформы: часть операций с файлами, COM-объекты и некоторые типы недоступны. Используйте инструкции препроцессору #Если ВебКлиент для разделения таких фрагментов и проверяйте модуль с флагом компиляции под веб-клиент.
Нужны ли директивы в модулях объектов и менеджеров?
Нет. Модули объектов, менеджеров, наборов записей всегда исполняются на сервере, поэтому директивы там не применяются. Директивы имеет смысл указывать только в модулях управляемых форм и команд, где контекст неоднозначен.
Как уменьшить количество серверных вызовов в форме?
Собирайте все необходимые серверу данные в структуру и выполняйте один вызов вместо нескольких; выносите обращения к базе из циклов; используйте &НаСервереБезКонтекста, когда данные формы не нужны. Косвенный признак проблемы — форма «подвисает» при открытии или пересчёте.