При разработке конфигураций на платформе 1С:Предприятие 8.3 для клиент-серверной архитектуры начинающие разработчики часто сталкиваются с непониманием логики работы свойств общих модулей. В палитре свойств модуля доступны флаги «Клиент (управляемое приложение)», «Сервер» и «Вызов сервера». Нередко возникает вопрос: зачем платформа позволяет устанавливать все эти флаги одновременно, как система определяет место выполнения кода и как правильно структурировать модули согласно стандартам разработки?
Разберем детально назначение каждого флага, правила компиляции процедур и функций, а также типовые шаблоны проектирования общих модулей.
Рассмотрим, за что отвечает каждый отдельный флаг в свойствах общего модуля:
Проанализируем распространенную ошибку: попытку использовать директивы компиляции (&НаКлиенте, &НаСервере) внутри общих модулей. Важно помнить следующее правило платформы:
Директивы компиляции с амперсандом в общих модулях синтаксически запрещены. Они предназначены исключительно для модулей форм и модулей команд. Если попытаться написать &НаСервере в общем модуле, платформа выдаст синтаксическую ошибку при проверке конфигурации.
В общем модуле контекст выполнения по умолчанию определяется установленными флагами в свойствах этого модуля. Если модуль объявлен одновременно как серверный и клиентский, а нам требуется исключить часть кода из компиляции на определенной стороне, применяются исключительно инструкции препроцессора. Посмотрим на пример:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
Функция ПолучитьДанныеИзБазы(СсылкаНаОбъект) Экспорт
// Этот код скомпилируется только на сервере
Возврат СсылкаНаОбъект.ПолучитьОбъект();
КонецФункции
#КонецЕсли
#Если Клиент Тогда
Процедура ПоказатьСообщениеПользователю(ТекстСообщения) Экспорт
// Этот код скомпилируется только на клиенте
ПоказатьПредупреждение(, ТекстСообщения);
КонецПроцедуры
#КонецЕсли
Если же экспортная процедура или функция написана в клиент-серверном модуле без инструкций препроцессора, она компилируется в двух независимых экземплярах: одна копия существует на сервере, вторая — на клиенте.
Выясним причину, почему одновременная установка флагов «Клиент (управляемое приложение)», «Сервер» и «Вызов сервера» считается грубым антипаттерном в разработке.
Если у модуля включены и клиентский контекст, и серверный контекст с вызовом сервера, то вступает в силу правило приоритета локального контекста. Когда код на тонком клиенте вызывает метод такого модуля, платформа всегда выбирает «ближайший» экземпляр — то есть клиентский. Вызова сервера по сети не происходит. Серверный экземпляр этого метода останется невызванным, а попытка выполнить внутри метода серверные операции (например, обращение к таблицам базы данных) приведет к ошибке времени выполнения на клиенте.
Именно поэтому комбинировать флаги «Клиент» и «Вызов сервера» в одном модуле категорически не рекомендуется стандартами 1С.
Для создания понятной, надежной и производительной системы методисты 1С рекомендуют разделять функционал конфигурации на четыре четких шаблона общих модулей. Разберем каждый из них по шагам:
Клиент)
Устанавливается только флаг «Клиент (управляемое приложение)». Такие модули предназначены для логики отображения, открытия форм, показа диалогов, взаимодействия с торговым оборудованием и файловой системой пользователя.
Сервер)
Устанавливается только флаг «Сервер» (флаг «Вызов сервера» обязательно снят). Здесь размещается вся тяжелая бизнес-логика: проведение документов, расчет итогов, построение сложных запросов, обработка данных. С клиента эти модули вызвать невозможно, что существенно повышает безопасность системы и предотвращает неконтролируемые вызовы логики в обход интерфейса.
ВызовСервера)
Устанавливаются флаги «Сервер» и «Вызов сервера» (флаг «Клиент» обязательно снят). Данные модули выступают тонким фасадом (API) между клиентом и сервером. Они содержат компактные методы, которые клиентское приложение вызывает для получения данных с сервера. Вся тяжелая обработка из них сразу делегируется в чисто серверные модули.
КлиентСервер)
Устанавливаются флаги «Клиент (управляемое приложение)» и «Сервер» (флаг «Вызов сервера» обязательно снят). Сюда помещаются универсальные алгоритмы, которые не зависят от базы данных и контекста исполнения: форматирование строк, проверка корректности ИНН, математические формулы, операции с датами. При вызове с клиента код выполняется на клиенте без сетевых задержек, а при вызове на сервере — выполняется на сервере без передачи данных по сети.
Рассмотрим два критически важных аспекта, которые необходимо учитывать при проектировании модулей с признаком «Вызов сервера»:
Через границу клиент-сервер нельзя передавать объекты, которые могут изменяться и привязаны к контексту сервера. К ним относятся СправочникОбъект, ДокументОбъект, ТаблицаЗначений, НаборЗаписей. Если передать мутабельный объект в метод модуля вызова сервера, платформа сгенерирует исключение: «Ошибка передачи мутабельного значения». В параметрах и результатах таких методов разрешено использовать только сериализуемые типы: примитивные типы (число, строка, дата, булево), ссылки (СправочникСсылка, ДокументСсылка), а также структуры и массивы, состоящие из допустимых типов.
Любая экспортная процедура в модуле с флагом «Вызов сервера» представляет собой открытую точку входа для клиента. Если такой модуль случайно пометить признаком «Привилегированный», клиент сможет запускать серверные операции в обход системы прав (RLS). Поэтому вызовы сервера должны выполняться строго в рамках прав текущего пользователя, а включение привилегированного режима следует делать локально внутри чисто серверных процедур с помощью метода УстановитьПривилегированныйРежим(Истина).
Следуя этим правилам, мы получаем предсказуемое поведение кода, отсутствие лишнего сетевого трафика и надежную архитектуру приложения.