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

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

1С: что выполняется на клиенте, а что на сервере

Разбираем, какой код в 1С выполняется на клиенте, а какой на сервере: контексты, директивы компиляции, вызовы сервера, типичные ошибки и практические рекомендации.

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

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

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

Как устроена клиент-серверная модель в 1С

В клиент-серверном варианте работы инфраструктура состоит из трёх уровней: клиентское приложение, кластер серверов 1С и СУБД. Клиент отвечает за отображение интерфейса и взаимодействие с пользователем, сервер 1С исполняет бизнес-логику и обращается к базе данных, СУБД хранит данные. В файловом варианте роль сервера частично берёт на себя клиентское приложение, но принципы разделения кода сохраняются.

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

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

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

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

ДирективаГде выполняетсяОсобенности
&НаКлиентеКлиентДоступны элементы формы, оповещения, файловые операции; нет прикладных объектов
&НаСервереСерверДоступен контекст формы (реквизиты, данные формы); вызов из клиента — сетевой обмен
&НаСервереБезКонтекстаСерверНет доступа к данным формы; вызов дешевле, данные нужно передавать параметрами
&НаКлиентеНаСервереБезКонтекстаКлиент и серверКомпилируется в обоих контекстах; только общие типы, без формы и прикладных объектов

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

Что выполняется на клиенте

Клиентский контекст отвечает за всё, что связано с интерфейсом и компьютером пользователя. Сюда относятся обработчики событий формы и её элементов: ПриНажатии, ПриИзменении, ПередЗаписью на клиенте, обработчики ожидания, обработка оповещений. Любое действие, которое начинается с клика пользователя, стартует на клиенте.

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

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

Ограничения клиентского контекста

На клиенте нельзя выполнять запросы к базе данных, создавать и записывать прикладные объекты, обращаться к менеджерам справочников и документов для чтения данных. Конструкция Справочники.Номенклатура.НайтиПоКоду() в клиентском коде не скомпилируется. Единственное исключение — получение ссылки и работа с уже переданными на клиент данными.

Что выполняется на сервере

Серверный контекст — это место для всей работы с данными. Здесь выполняются запросы, чтение и запись объектов, проведение документов, движения по регистрам, расчёты итогов, обращения к планам обмена и фоновые задания. Любая операция, требующая доступа к базе, физически возможна только на сервере.

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

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

Сервер с контекстом формы и без

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

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

Как правильно организовать вызовы сервера из клиента

Главное правило оптимизации: минимизировать количество серверных вызовов и объём передаваемых данных. Если при изменении поля нужно получить цену, единицу измерения и ставку НДС — делайте один серверный вызов, возвращающий структуру со всеми тремя значениями, а не три отдельных вызова.

Второе правило: не вызывать сервер в цикле. Если нужно обработать табличную часть из 200 строк с обращением к базе по каждой строке, передавайте данные целиком в одну серверную процедуру, обрабатывайте их там одним запросом и возвращайте результат. Обход строк на клиенте с запросом в каждой итерации — классическая причина «тормозов» формы.

Порядок действий при проектировании обработчика
  1. 1
    Определите, нужны ли данные из базы: если нет — оставьте код на клиенте.
  2. 2
    Если данные нужны, соберите все необходимые параметры в структуру на клиенте.
  3. 3
    Создайте процедуру &НаСервереБезКонтекста (или в общем серверном модуле с флагом «Вызов сервера»), принимающую структуру параметров.
  4. 4
    Выполните всю работу с базой одним запросом или пакетом запросов, верните результат структурой.
  5. 5
    На клиенте примените результат к элементам формы и проверьте поведение на реальной форме.

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

bsl
&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
    ДанныеСтроки = Новый Структура("Номенклатура, Соглашение");
    ЗаполнитьЗначенияСвойств(ДанныеСтроки, Объект);
    Результат = ПолучитьДанныеНоменклатуры(ДанныеСтроки);
    Объект.Цена = Результат.Цена;
    Объект.СтавкаНДС = Результат.СтавкаНДС;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьДанныеНоменклатуры(Параметры)
    // один запрос к базе, возврат структуры
КонецФункции

Типичные ошибки при распределении кода

Самая частая ошибка — попытка использовать серверные типы на клиенте: создание ДокументОбъект в клиентской процедуре, обращение к запросу из кода формы без серверного вызова. Платформа либо не даст скомпилировать модуль, либо выбросит ошибку в рантайме, если код попал на клиента через общий модуль с неправильными флагами.

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

Типичные ошибки
01
Серверный вызов внутри цикла по строкам таблицы — время работы растёт линейно, форма «зависает»; переносите обработку целиком на сервер.
02
Использование &НаСервере вместо &НаСервереБезКонтекста — лишняя сериализация всех данных формы при каждом вызове.
03
Проверки остатков и прав только на клиенте — пользователь с расширенными возможностями может обойти ограничение; дублируйте проверки на сервере.
04
Общий модуль с логикой, где не выставлены флаги контекста, — код оказывается недоступен там, где нужен, или компилируется в обоих контекстах с ошибками.
05
Модальные вызовы (Вопрос, Предупреждение) в синхронном стиле — в тонком и веб-клиенте они запрещены; используйте асинхронные аналоги с описанием оповещения.

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

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

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

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

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

Количество серверных вызовов при типовой операции
Норма

Один-два вызова на действие пользователя

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

Вызовы в цикле, десятки обращений на одно действие

Проверка конфигурации по всем режимам
Норма

Нет ошибок компиляции модулей ни в одном клиенте

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

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

Поведение проверок при записи
Норма

Контроль срабатывает на сервере даже при обходе клиентских проверок

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

Данные записываются без серверной валидации

Итог

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

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

Частые вопросы

Где выполняется код модуля объекта документа?

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

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

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

Что быстрее: &НаСервере или &НаСервереБезКонтекста?

Бесконтекстный вызов быстрее, потому что не сериализует данные формы. Контекстный вызов передаёт на сервер все реквизиты и табличные части формы и возвращает их обратно, что на больших формах даёт заметную задержку. Используйте контекстный вариант только когда действительно нужно изменить данные формы на сервере, например при заполнении табличной части.

Почему общий серверный модуль не виден из клиентского кода?

Проверьте свойства общего модуля: должен быть установлен флаг «Вызов сервера». Без него модуль компилируется только на сервере и недоступен для вызова с клиента. Это осознанное ограничение безопасности — не включайте флаг для модулей, содержащих чувствительную логику, которую не должны инициировать пользователи напрямую.

Где размещать код, который нужен и на клиенте, и на сервере?

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

Как выполнить длительную операцию, не блокируя интерфейс?

Запустите фоновое задание на сервере (в конфигурациях на БСП — через ДлительныеОперации.ВыполнитьВФоне), а на клиенте подключите обработчик ожидания, который периодически проверяет завершение и по готовности забирает результат. Пользователь в это время продолжает работать, а при необходимости видит индикатор выполнения.