В среде 1С начинающие разработчики часто путают директивы компиляции и инструкции препроцессора. Да, эти конструкции являются инструментами для управления тем, какой код и в каком месте будет исполняться. Но несмотря на схожие задачи, они работают на разных этапах и имеют разный синтаксис.

Введение

Директивы компиляции определяют, в каком контексте (на стороне клиента или сервера) будет скомпилирована и выполнена конкретная процедура или функция. Пишутся перед объявлением метода и начинаются с символа &.

Если директива не указана, по умолчанию применяется &НаСервере.

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

  • &НаКлиенте – указывает, что процедура или функция выполняется в клиентском контексте. Доступны только данные формы и клиентские объекты.

Что можно: открывать окна, задавать вопросы пользователю, работать с файлами на локальном диске, открыть форму.

Что нельзя: обращаться к базе данных напрямую (запросы, чтение объектов).

&НаКлиенте

Процедура НазваниеПроцедуры()

//Код выполняемый в клиентском контексте

КонецПроцедуры
код
  • &НаСервере — код выполняется на сервере. Имеет полный доступ к базе данных и контексту формы.

Что можно: выполнять тяжелые запросы, изменять данные в БД, проводить документы.

Что нельзя: выводить предупреждения, открывать формы или обращаться к файловой системе пользователя.

&НаСервере

Процедура НазваниеПроцедуры()

//Код выполняемый на сервере

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

Процедура НазваниеПроцедуры(ПередаваемыйПараметр)

//Код выполняемый на сервере

КонецПроцедуры
код
  • &НаКлиентеНаСервереБезКонтекста – редкая директива для универсальных алгоритмов (например, простая математика или проверка формата строки), которые должны работать везде без обращения к данным формы.
& НаСервереБезКонтекста

Процедура НазваниеПроцедуры(ПередаваемыйПараметр)

//Код выполняемый и на клиенте и на сервере

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

Инструкции препроцессора – управляют «сборкой» исходного текста модуля еще до начала компиляции. Они позволяют включать или исключать целые блоки кода в зависимости от условий среды. Начинаются с символа #.

если сервер тогда

Основные инструкции препроцессора

  • #Если … #ИначеЕсли … #КонецЕсли — условная компиляция в зависимости от окруженияпозволяет исключить части кода, которые недоступны в определенном контексте.
#Если ВебКлиент Тогда

// код для вебR09;клиента

#Иначе

// другой код

#КонецЕсли
код
  • #Область и #КонецОбласти — не влияют на логику работы. Их задача — «порядок» в коде. Они позволяют сворачивать логические блоки (например «ОбработчикиСобытий», «СлужебныеПроцедурыИФункци»).
#Область НазваниеОбласти

// код

#КонецОбласти
код
  • #Вставка и #КонецВставки/ #Удаление и #КонецУдаления – используется в расширениях конфигурации для модификации кода в процедурах с аннотацией &ИзменениеИКонтроль: добавляет или удаляет часть кода.
&ИзменениеИКонтроль

#Удаление

// старый код

#КонецУдаления

#Вставка

// новый код

#КонецВставки
код
ХарактеристикаДирективы компиляции (&)Инструкции препроцессора (#)
УровеньПрименяются к конкретному методу (процедуре/функции).Могут применяться к любому фрагменту кода, переменным или методам.
МодулиВ основном используются в модулях управляемых форм и команд.Используются во всех типах модулей (общие, модули объекта, менеджера и т.д.).
СмыслУказывают платформе, куда отправить выполнение метода.Буквально удаляют ненужный код из текста перед компиляцией.

Возможные ошибки при использовании Инструкций препроцессора в модуле менеджера

В модулях объектов и менеджеров контекст определяется платформой автоматически. В 99% случаев в современном управляемом приложении модуль менеджера исполняется на сервере. Однако для обеспечения универсальности и корректной работы в «толстом клиенте» используются инструкции препроцессора. Они физически вырезают куски кода из компиляции в определенных режимах.

В этом режиме платформа может пытаться скомпилировать модуль менеджера на клиенте, даже если он не предназначен для клиентского выполнения. Это приводит к ошибкам, потому что:

•    на клиенте недоступны многие объекты и методы, работающие с базой данных;

•    код может содержать вызовы, которые имеют смысл только на сервере.

Модуль менеджера компилируется на клиенте в следующих случаях:

•    объект явно создаётся и вызывается в клиентском коде,

•    платформа неявно обращается к модулю менеджера для вызова обработчиков событий на клиенте,

•    при проверке конфигурации в режиме «Толстый клиент, управляемое приложение» система анализирует возможность компиляции модулей на клиенте.

Ошибка «Пустого метода» (Метод не обнаружен)

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

Создадим на форме документа «Реализация товаров и услуг» команду, и в обработчике На Сервере вызовем в ней процедуру из модуля менеджера с условием «#Если ТолстыйКлиентУправляемоеПриложение Тогда …..#КонецЕсли».

Модуль формы:

код

Модуль Менеджера:

код

При попытке выполнить команду в режиме предприятия, мы получим Ошибку:

схема

Почему это происходит: Для вызова с сервера код внутри «#Если ТолстыйКлиентУправляемоеПриложение» просто не существует. Платформа не видит экспортируемую процедуру.

Как правильно: Добавить условие предпроцессора «#Если Сервер»

код

Синтаксический «Разрыв» процедуры

Ошибка возникает, когда открывающая часть процедуры попадает в блок препроцессора, а закрывающая — нет (или наоборот).

#Если Сервер Тогда

Процедура РассчитатьОстатокТест(МассивТоваров) Экспорт
#КонецЕсли
                               ////текст процедуры

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

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

Отсутствие кода в одной из ветвей компиляции

Не стоит объявлять переменные внутри предпроцессоров. Всегда инициализируйте переменные либо в обеих ветках препроцессора, либо до их начала.

Процедура РассчитатьОстатокТест(МассивТоваров) Экспорт

  #Если Сервер Тогда

  МассивСообщений = Новый Массив;

  #КонецЕсли

 
  МассивСообщений.Добавить("Тест процедуры");  // Ошибка на клиенте: Переменная 'МассивСообщений' не определена
 

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

Выводы

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

СЛОВАРЬ

ТерминРасшифровка
Директива компиляцииСпециальная конструкция 1С, которая указывает платформе, где будет выполняться процедура или функция: на клиенте, на сервере или в другом поддерживаемом контексте .
Инструкция препроцессораУказание, которое обрабатывается до компиляции и позволяет включать или исключать части кода в зависимости от условий среды .
Клиентский контекстРежим выполнения кода на стороне пользователя; здесь доступны формы, интерфейс и локальные действия, но нет прямого доступа к базе данных .
Серверный контекстРежим, в котором код выполняется на сервере и может работать с данными базы, запросами и объектной логикой .
Сервер без контекстаСерверное выполнение без доступа к реквизитам и элементам формы; подходит для вычислений и служебных операций .
ПрепроцессорМеханизм предварительной обработки текста модуля, который вырезает или оставляет куски кода еще до компиляции .
Условная компиляцияСпособ собрать разные варианты кода для разных условий выполнения, например для веб-клиента, тонкого клиента или сервера .
ОбластьСлужебная инструкция для группировки кода без изменения логики работы; используется для удобства чтения и сворачивания блоков .
ВставкаИнструкция для расширений, позволяющая добавить фрагмент кода в отмеченное место базового модуля .
УдалениеИнструкция для расширений, позволяющая убрать фрагмент исходного кода в пределах заданного блока .
Контекст формыНабор данных и элементов, доступных конкретной форме в момент выполнения кода .
Модуль формыМодуль, в котором обычно работают директивы компиляции для управления клиентским и серверным выполнением .
Модуль менеджераМодуль, где платформа определяет контекст выполнения автоматически, но при этом важно учитывать правила компиляции и препроцессора .
ЭкспортПризнак процедуры или функции, позволяющий вызывать ее из других модулей .
Пустой методСитуация, когда процедура фактически не попадает в компиляцию из-за условий препроцессора, и платформа не находит ее при вызове .
Синтаксический разрывОшибка, возникающая, когда начало и конец процедуры оказываются по разные стороны условной компиляции