Почему не работает условие препроцессора #ИначеЕсли Клиент в файловой базе 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

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

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

Постановка проблемы и анализ исходного кода

Представим типовой сценарий. Разработчик создает внешнюю обработку под обычные формы (например, для конфигурации «Управление торговым предприятием», редакция 2) и пишет в модуле формы следующий обработчик нажатия кнопки:


Процедура Кнопка1Нажатие(Элемент)
#Если Сервер Тогда
    А = 0;
#ИначеЕсли Клиент Тогда
    Б = 0;
#КонецЕсли
КонецПроцедуры

Казалось бы, логика очевидна: при нажатии кнопки на форме мы находимся в клиентском контексте, поэтому должна сработать ветка Б = 0. Однако при тестировании в файловой базе платформа упорно выполняет ветку А = 0. При этом в клиент-серверном варианте (на SQL-сервере) тот же самый код отрабатывает абсолютно корректно и уходит в ветку клиента. Выясним, почему так происходит.

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

Прежде чем перейти к файловому режиму, важно устранить частую терминологическую путаницу. Разработчики часто называют конструкции с символом решетки # директивами компиляции, хотя на самом деле это инструкции препроцессора.

Давайте разберем их ключевые отличия:

  1. Директивы компиляции начинаются с символа коммерческого 'at' & (например, &НаКлиенте, &НаСервере). Они указывают компилятору, в каком контексте должна быть скомпилирована и выполнена процедура или функция целиком. Применяются они в основном в управляемых формах и командах.
  2. Инструкции препроцессора начинаются с символа решетки # (например, #Если Сервер Тогда). Препроцессор обрабатывает модуль до момента его фактической компиляции. Он буквально «вырезает» из текста программы участки кода, условия для которых ложны, и передает компилятору только оставшийся «чистый» текст.

В обычных формах (Толстый клиент) концепция директив компиляции & не применяется в модулях форм напрямую так же, как в управляемых формах. Вместо этого разработчики часто вынуждены использовать инструкции препроцессора # для разграничения кода.

Особенности препроцессора в файловом варианте (Толстый клиент)

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

Согласно официальной документации «1С:Предприятия», для обеспечения совместимости кода в файловом варианте предопределенные символы препроцессора Сервер, Клиент, ТолстыйКлиентОбычноеПриложение определены всегда. Это означает, что для препроцессора в файловой базе оба флага — и Сервер, и Клиент — одновременно принимают значение Истина.

Теперь проанализируем, как препроцессор обрабатывает наше условие:

  1. Препроцессор видит строку #Если Сервер Тогда. Поскольку в файловой базе значение Сервер равно Истина, препроцессор принимает решение оставить строку А = 0; для компиляции.
  2. Так как это единая условная конструкция #Если ... #ИначеЕсли ... #КонецЕсли, и первое условие уже выполнилось (вернуло истину), препроцессор, следуя правилам логики ветвления, полностью отбрасывает и игнорирует все последующие ветки (включая #ИначеЕсли Клиент).
  3. В итоге компилятор получает «урезанный» код, из которого ветка клиента была удалена еще на этапе препроцессинга. В исполняемый код попадает только А = 0;.

Что будет, если разделить условия?

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


#Если Сервер Тогда
    А = 0;
#КонецЕсли

#Если Клиент Тогда
    Б = 0;
#КонецЕсли

Если мы запустим этот код в файловой базе (в режиме толстого клиента), препроцессор обработает оба условия независимо. Так как оба флага равны Истина, в итоговый скомпилированный код попадут обе строчки. Программа выполнит и А = 0, и Б = 0.

В клиент-серверном же варианте компиляция происходит раздельно для клиентского приложения и сервера приложений. На клиенте скомпилируется только Б = 0, а на сервере — только А = 0.

Как правильно писать код согласно стандартам «1С»

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

Рассмотрим, как правильно решить эту задачу по рекомендациям стандартов ИТС:

  1. Разделение через общие модули: Если вам необходимо выполнять разный код на клиенте и на сервере, создайте два отдельных общих модуля. Например:
    • РаботаСКлиентомКлиент — модуль с установленным флагом «Клиент» в свойствах.
    • РаботаСКлиентомСервер — модуль с установленным флагом «Сервер» (и, при необходимости, «Вызов сервера»).
    В таком случае платформа сама будет управлять контекстом вызова без использования препроцессора в теле процедур.
  2. Использование явных процедур в модуле формы: Вместо написания препроцессорных условий внутри одной процедуры, разделите код на две самостоятельные процедуры:
    
    Процедура ВыполнитьДействиеНаСервере()
        // Серверная логика
        А = 0;
    КонецПроцедуры
    
    Процедура Кнопка1Нажатие(Элемент)
        // Клиентская логика
        Б = 0;
        
        // При необходимости вызываем серверный метод
        ВыполнитьДействиеНаСервере();
    КонецПроцедуры
    

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

← На главную