Перейти к содержимому

❓ 1.17 Инструкции препроцессора и директивы компиляции в 1С: в чем разница и как они работают вместе?

ИТС: Платформа — Глава 4. Встроенный язык — https://its.1c.ru/db/v8327doc

ИТС: Различие инструкций препроцессора и директив компиляции — https://its.1c.ru/db/v8327doc/bookmark/dev/TI000000116

Инструкции препроцессора и директивы компиляции нужны для того, чтобы в скомпилированном модуле остался только тот код, который действительно должен присутствовать в конкретном контексте.

Но действуют они на разных уровнях.


В коде 1С часто встречается такое:

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Если НЕ МобильныйАвтономныйСервер Тогда
#Если МобильныйКлиент Тогда

Это инструкции препроцессора.

Они:

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

📌 То есть препроцессор работает именно с текстом модуля.


Кроме инструкций препроцессора, в 1С есть и директивы компиляции.

Примеры:

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

Директивы компиляции действуют не на произвольный текст, а на структурные единицы программного кода:

  • процедуры
  • функции
  • объявления переменных

📌 То есть директивы определяют, какие методы и переменные попадут в конкретный экземпляр модуля.


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

Заголовок раздела «Различие инструкций препроцессора и директив компиляции»

Инструкции препроцессора:

  • работают с исходным текстом модуля
  • исключают ненужные фрагменты до компиляции

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

  • работают со структурными единицами кода
  • влияют на состав конкретного экземпляра модуля на этапе компиляции

Инструкции препроцессора работают с текстом модуля,
а директивы компиляции — с методами и объявлениями переменных.


Как директивы компиляции и инструкции препроцессора работают вместе

Заголовок раздела «Как директивы компиляции и инструкции препроцессора работают вместе»

На практике эти два механизма часто используются одновременно.

Логика такая:

  1. сначала для конкретного контекста определяется, какие инструкции препроцессора считаются истинными
  2. затем из исходного текста модуля исключаются неподходящие фрагменты
  3. после этого оставшийся код компилируется с учетом директив компиляции

То есть итоговый состав модуля зависит сразу от двух вещей:

  • какой текст остался после препроцессора
  • какие методы допускаются в данном контексте директивами компиляции

Допустим, в модуле формы есть такой код:

&НаКлиенте
Процедура РаботаСФайлами()
#Если ВебКлиент Тогда
// код для веб-клиента
#Иначе
// код для других клиентских приложений
#КонецЕсли
КонецПроцедуры

Что здесь происходит:

  • директива &НаКлиенте означает, что процедура может существовать в клиентском экземпляре модуля
  • инструкции препроцессора внутри процедуры определяют, какой именно текст останется для конкретного типа клиента

В результате:

  • в веб-клиенте в модуле останется только ветка #Если ВебКлиент Тогда
  • в других клиентских приложениях останется только ветка #Иначе

📌 То есть сама процедура будет клиентской, но её содержимое может отличаться в зависимости от типа клиента.


Теперь рассмотрим другую ситуацию:

#Если НаСервере Тогда
&НаКлиенте
Процедура Клиентская()
КонецПроцедуры
#КонецЕсли

Здесь директива компиляции и инструкция препроцессора работают в разных направлениях.

Что получится:

  • на сервере исходный текст процедуры после препроцессора останется
  • но сама процедура не будет скомпилирована, потому что директива &НаКлиенте не допускает её существование на сервере
  • на клиенте процедура тоже не появится
  • потому что клиентский вариант не пройдет через инструкцию #Если НаСервере Тогда, и исходный текст будет исключен ещё до компиляции

📌 В итоге процедура не будет доступна ни на клиенте, ни на сервере.


Эти примеры показывают главное:

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

Поэтому при чтении кода в 1С важно смотреть сразу на оба уровня:

  • что исключает препроцессор
  • что допускает директива компиляции

Методы, помеченные директивами:

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

могут попадать одновременно в разные экземпляры программного модуля.

Из-за этого один и тот же исходный метод может присутствовать сразу в нескольких контекстах, если это допускается типом модуля и директивой компиляции.

1С работает в разных режимах и контекстах, и один и тот же исходный код может вести себя по-разному в зависимости от того, где и как он компилируется и выполняется.
Поэтому, чтобы писать корректные решения, разработчик должен понимать, в каком контексте будет существовать и работать его код.