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

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

Директивы компиляции в 1С: назначение, виды и практика применения

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

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

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

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

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

Платформа предоставляет пять основных директив для модулей управляемых форм и команд. Каждая задаёт собственный контекст исполнения со своими ограничениями.

  • &НаКлиенте — код исполняется на клиенте. Доступны элементы формы, диалоги, файловые операции на компьютере пользователя. Недоступны запросы к базе данных напрямую и большинство прикладных типов.
  • &НаСервере — код исполняется на сервере с доступом к данным формы. Можно работать с реквизитами формы, преобразовывать их в прикладные объекты, выполнять запросы.
  • &НаСервереБезКонтекста — серверный метод без передачи данных формы. Реквизиты формы недоступны, зато вызов дешевле: не сериализуются данные формы в обе стороны.
  • &НаКлиентеНаСервереБезКонтекста — универсальная директива: метод компилируется и на клиенте, и на сервере, но без контекста формы. Используется для вспомогательных расчётов, не зависящих от данных формы.
  • &НаКлиентеНаСервере — встречается в модулях команд; метод доступен в обоих контекстах с учётом ограничений.

Директива ставится строго перед ключевым словом Процедура или Функция. Пропуск директивы в модуле управляемой формы — ошибка компиляции: платформа не сможет определить контекст.

Как выбрать директиву для конкретной задачи

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

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

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

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

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

&НаКлиенте

Процедура РассчитатьСкидку(Команда)

СуммаСкидки = РассчитатьСкидкуНаСервере(Объект.СуммаДокумента);

Объект.Скидка = СуммаСкидки;

КонецПроцедуры

&НаСервереБезКонтекста

Функция РассчитатьСкидкуНаСервере(Сумма)

// запрос к регистру скидок

Возврат Сумма * 0.05;

КонецФункции

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

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

Расплата за скорость — отсутствие доступа к реквизитам и элементам формы. Если внутри метода без контекста понадобилось значение реквизита, его придётся передавать параметром. Попытка обратиться к Объект или Элементы из такого метода вызовет ошибку компиляции.

Инструкции препроцессору: вторая группа директив

Помимо директив контекста, в 1С существуют инструкции препроцессору #Если ... #Тогда ... #КонецЕсли, которые тоже относят к механизму управления компиляцией. Они позволяют включать или исключать фрагменты кода в зависимости от среды исполнения: #Если Сервер Тогда, #Если ТонкийКлиент Тогда, #Если ВебКлиент Тогда, #Если МобильныйКлиент Тогда.

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

1c
#Если ВебКлиент Тогда
    ПоместитьФайлВоВременноеХранилище();
#Иначе
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Показать(Новый ОписаниеОповещения("ПослеВыбора", ЭтотОбъект));
#КонецЕсли

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

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

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

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

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

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

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

Ошибок компиляции нет ни для одного контекста

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

Сообщения о недоступности типа или неопределённой процедуре

Запуск сценария в нужном клиенте
Норма

Операция выполняется без обращений в лишних серверных вызовах

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

Ошибки времени выполнения или заметные паузы из-за каскада вызовов

Состав серверных вызовов
Норма

Одна клиентская команда вызывает сервер один-два раза

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

Каждый обращение к данным порождает отдельный вызов в цикле

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

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

Типичные ошибки
01
Запрос к базе в методе &НаКлиенте — ошибка компиляции; решение: вынести запрос в серверный метод
02
Серверный вызов внутри цикла по строкам таблицы — резкое падение производительности; решение: собрать данные и вызвать сервер один раз
03
Использование &НаСервере там, где достаточно &НаСервереБезКонтекста, — лишняя сериализация данных формы на каждый вызов
04
Обращение к реквизитам формы из метода без контекста — ошибка; решение: передать значения параметрами
05
Дублирование логики в клиентских и серверных методах вместо &НаКлиентеНаСервереБезКонтекста — рассинхронизация кода при доработках

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

Удобный приём при доработке типовых форм: сначала напишите всю логику на клиенте, затем вынесите на сервер только обращения к базе. Так проще увидеть границу контекстов и не перетащить на сервер интерфейсные операции.
ПЗ
Практическое замечание

Ограничения и границы самостоятельной доработки

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

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

Итог

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

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

Частые вопросы о директивах компиляции 1С

Что будет, если не указать директиву перед процедурой в модуле формы?

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

Можно ли вызвать серверную процедуру из клиентской?

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

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

Метод с этой директивой живёт в модуле формы и доступен только ей, тогда как общий модуль доступен всей конфигурации. Если вспомогательная функция нужна нескольким формам, правильнее вынести её в общий модуль с соответствующими флагами контекста.

Почему код работает в тонком клиенте, но падает в веб-клиенте?

Веб-клиент поддерживает не все возможности платформы: часть операций с файлами, COM-объекты и некоторые типы недоступны. Используйте инструкции препроцессору #Если ВебКлиент для разделения таких фрагментов и проверяйте модуль с флагом компиляции под веб-клиент.

Нужны ли директивы в модулях объектов и менеджеров?

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

Как уменьшить количество серверных вызовов в форме?

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