Директивы компиляции в модуле формы
У новичков часто возникают сложности при использовании директив компиляции в модуле управляемых форм, таких как &НаКлиенте, &НаСервере, &НаСервереБезКонтекста и &НаКлиентеНаСервереБезКонтекста.
Поэтому в статье разберем, какие директивы компиляции использовать при написании кода в модуле управляемых форм.
С выходом платформы «1С:Предприятие 8.2» появилось деление процедур и функций на клиентские и серверные при использовании тонкого клиента и WEB-клиента. На стороне клиента описывается один функционал, который выполняется на компьютере пользователя, а на стороне сервера описывается другой функционал, который выполняется на сервере.
Опишем подробно работу прикладного решения в клиент-серверном режиме
Файловый режим по сути тоже работает как клиент-серверный вариант, но с небольшими отличиями. В файловом варианте эмулируется сервер в рамках одного процесса с запущенной программой 1С:Предприятие.
Общение клиентской части с серверной осуществляется с помощью серверных вызовов. Серверный вызов — это обращение клиентской части к серверной с целью выполнения каких-либо действий на стороне сервера или получения данных от сервера.
Когда пользователь открывает управляемую форму, она создается на стороне сервера и на стороне пользователя, при этом у пользователя она визуально открывается. Процедуры и функции, описанные в модуле формы, исполняются или в контексте клиента, или в контексте сервера.
Поэтому все процедуры и функции, а также переменные должны иметь явное указание на то, в каком контексте они будут использоваться, а для этого в начале процедуры или функции, а также переменной необходимо указать директиву компиляции.
Модули управляемых форм поддерживают 4 директивы компиляции:
- &НаКлиенте – процедура или функция исполняется на стороне клиента, используя только те данные, которые есть на форме.
- &НаСервере – процедура или функция исполняется на стороне сервера, но при этом доступен контекст формы, т.е., серверная процедура может использовать данные формы.
- &НаСервереБезКонтекста – процедура или функция исполняется на стороне сервера, но контекст формы недоступен, т.е., серверная процедура ничего «не знает» ни о существовании формы, ни тем более о данных, которые размещены на форме.
- &НаКлиентеНаСервереБезКонтекста – процедура или функция может исполняться на стороне клиента и сервера, но контекст формы ни на стороне клиента, ни на стороне сервера доступен не будет, то есть процедура или функция ничего не будет «знать» о существовании формы и тем более о данных, которые размещены на форме. Нельзя также напрямую обратиться к базе данных, и не важно, необходимо изменить данные в базе данных или просто прочитать данные для просмотра.
Если по ошибке разработчик не указал директиву компиляции, то процедура или функция будет выполняться на стороне сервера, как будто указана директива &НаСервере.
Принцип работы управляемой формы заключается в действиях пользователя: нажал кнопку, ввел значение, открыл закладку и т.д. На все эти действия срабатывают события с директивой компиляции &НаКлиенте. Из этих процедур можно вызвать другие процедуры или функции с директивой компиляции &НаКлиенте, &НаСервере, &НаСервереБезКонтекста и &НаКлиентеНаСервереБезКонтекста.
Таким образом можно осуществить обработку данных на стороне клиента или на стороне сервера.
Какую директиву компиляции использовать и почему
Уточним один очень важный момент: доступ к базе данных есть только на серверной части, то есть клиентская часть не может напрямую обратиться к базе данных.
Поэтому необходимо из клиентских процедур вызывать серверные процедуры или функции с директивой компиляции &НаСервере, &НаСервереБезКонтекста. После выполнения серверных процедур или функций исполнение кода возвращается в клиентскую процедуру, откуда был осуществлен серверный вызов.
Демонстрационная база
Рассмотрим несколько примеров.
С сайта 1С:ИТС скачем демонстрационную конфигурацию «Управляемое приложение» по ссылке https://its.1c.ru/db/metod8dev#content:5028:hdoc.
В конфигурации открываем форму документа РасходТовара.
Нас будет интересовать событие ПриИзменении у реквизита Товар. В коде обратим внимание на оператор получения актуальной цены из регистра сведений ЦеныТоваров.
Запустим в режиме Отладки и проверим работоспособность данного механизма.
&НаКлиенте
Попробуем обратиться к базе данных из клиентской части, используя директиву компиляции &НаКлиенте.
Напоминаем, клиентская часть напрямую не может обратиться к базе данных, и не важно, необходимо изменить данные в базе данных или просто прочитать данные для просмотра. Клиентские процедуры и функции могут использовать только те данные, которые есть на форме.
Давайте в этом убедимся.
Перейдем в функцию ПолучитьЦенуТовара(), скопируем ее и вставим ниже, а оригинал закомментируем.
В демо конфигурации данная функция предваряется директивой компиляции &НаСервереБезКонтекста. К ней мы вернемся чуть позже.
Изменим ее на директиву компиляции &НаКлиенте и имя.
Из процедуры ТоварыТоварПриИзменении() вызовем процедуру ПолучитьЦенуТовараНаКлиенте()
Выполним проверку модуля.
В результате получим служебное сообщение о том, что на стороне тонкого клиента переменная РегистрыСведений не определена, то есть тонкий клиент ничего не знает о существовании регистра сведений ЦеныТоваров. Тонкому клиенту вообще не известна переменная РегистрыСведений. Это означает, что из процедуры с директивой компиляции &НаКлиенте нельзя получить данные из базы данных, используя объектный доступ.
Попробуем получить актуальную цену, используя запрос.
Закомментируем код. Вызовем конструктор запроса с обработкой результата.
Выполним проверку модуля.
В результате получим служебное сообщение о том, что на стороне тонкого клиента тип Запрос не определен, то есть тонкий клиент не работает с данным типом. Это означает, что из процедуры с директивой компиляции &НаКлиенте нельзя получить данные из базы данных, используя табличный доступ.
В результате проведения данных экспериментов мы убедились, что из тонкого клиента нельзя напрямую обратиться к базе данных. И не важно, используем ли мы объектный доступ или табличный.
Закомментируем нерабочий код.
Из функции с директивой компиляции &НаКлиенте нельзя получить цену из базы данных, поэтому, используя только данные из формы, вычислим цену способом деления суммы на количество.
Выполним проверку модуля. Синтаксических ошибок не обнаружено!
Вывод. Из процедур или функций с директивой компиляции &НаКлиенте, нельзя обратиться к базе данных, но им доступен контекст формы, то есть все данные, которые есть на форме.
&НаСервере
Попробуем обратиться к базе данных, используя функцию с директивой компиляции &НаСервере.
Процедура или функция с директивой компиляции &НаСервере исполняется на стороне сервера, но при этом ей доступен контекст формы, то есть серверная процедура может использовать данные формы.
Еще раз скопируем исходную функцию и вставим ниже. Изменим директиву компиляции и имя.
Из процедуры ТоварыТоварПриИзменении() вызовем процедуру ПолучитьЦенуТовараНаСервере()
Запустим в режиме отладки и проверим, что будет доступно из функции с директивой &НаСервере.
Из формы нам доступен основной реквизит Объект, со всеми своими реквизитами. Поэтому параметр Дата меняем на Объект.Дата и ВидЦен на Объект.ВидЦен. Доступны элементы формы, но некоторые свойства элементов формы будут недоступны. В нашем примере на стороне сервера не будет доступно свойство ТекущиеДанные у ТаблицыФормы Товары. Данное свойство предоставляет доступ к данным текущей строки, которую выбрал пользователь в таблице формы, а это уже не просто данные на форме, а интерактив, который должен отлавливаться только на стороне клиента.
Обратите внимание на то, что из серверной функции или процедуры нельзя вызвать клиентскую процедуру или функцию.
Выполним проверку модуля. В результате получим служебное сообщение о том, что на стороне сервера не определена процедура или функция ПолучитьТекущуюСтрокуТовары(). Это еще раз подтверждает, что из серверной части вызвать клиентскую процедуру или функцию нельзя.
После всех проверок получаем готовую рабочую функцию с директивой компиляции &НаСервере.
Здесь стоит уточнить, что при использовании директивы компиляции &НаСервере данные формы специальным образом упаковываются и передаются по сети серверу, где распаковываются и используются в вызываемой процедуре или функции. Поэтому по сети передается избыточный трафик. А это очень критично для сетей с низкой скоростью или с дорогим трафиком. Это еще и излишняя нагрузка на клиентскую и серверную части при упаковке и распаковке данных формы.
Если нет необходимости передавать данные формы серверной части, то лучше использовать директиву компиляции &НаСервереБезКонтекста.
Вывод. Из процедур или функций с директивой компиляции &НаСервере, можно обратиться к базе данных, а также доступен контекст формы, то есть все данные, которые есть на форме, но по сети передается избыточный трафик и есть определенная лишняя нагрузка на клиентскую и серверную части.
&НаСервереБезКонтекста
Попробуем обратиться к базе данных, используя функцию с директивой компиляции &НаСервереБезКонтекста.
Напоминаем, процедура или функция исполняется на стороне сервера, но контекст формы недоступен, то есть, серверная процедура ничего «не знает» о существовании формы и тем более о данных, которые размещены на форме.
Раскомментируем функцию ПолучитьЦенуТовара() с директивой компиляции &НаСервереБезКонтекста.
Именно такой вариант представлен в демоверсии, как самый оптимальный.
При вызове данной функции данные формы не упаковываются на стороне клиента, не передаются по сети, не распаковываются на стороне сервера. Все необходимые данные для двух параметров метода ПолучитьПоследнее() регистра сведений ЦеныТоваров, подготавливаются на стороне клиента и передаются на сервер без лишних данных. Все это уменьшает трафик в сети и нагрузку на клиентскую и серверную части, хотя в данном примере такой нагрузкой можно пренебречь, но при решении сложных технических задач этот нюанс нужно учитывать.
В функции с директивой компиляции &НаСервереБезКонтекста не доступен контекст формы, поэтому обратиться к основному реквизиту формы Объект мы не сможем. Также не доступны элементы формы и их свойства.
Вывод. Из процедур или функций с директивой компиляции &НаСервереБезКонтекста можно обратиться к базе данных, но при этом им не доступен контекст формы, то есть никакие данные формы не доступны. По сети передается оптимальный трафик и нет лишней нагрузки на клиентскую и серверную части.
&НаКлиентеНаСервереБезКонтекста
Рассмотрим последнюю директиву компиляции &НаКлиентеНаСервереБезКонтекста.
Процедура или функция может исполняться на стороне клиента или сервера, но контекст формы ни на стороне клиента, ни на стороне сервера доступен не будет, то есть процедура или функция ничего не будет знать о существовании формы или о данных, которые размещены на форме, нельзя также напрямую обратиться к базе данных, и не важно, необходимо изменить данные в базе данных или просто прочитать данные для просмотра. Процедура или функция с данной директивой является универсальной, поэтому код в ней должен одинаково корректно работать и на стороне сервера, и на стороне клиента.
В модуле формы обратим внимание на процедуру ЗаполнитьДополнительныеДанныеСтроки(), которая предваряется директивой компиляции &НаКлиентеНаСервереБезКонтекста. Данная процедура проверяет, если сумма по строке отличается от рассчитанной суммы путем умножения количества на цену, в этом случае сумма в таблице формы подсвечивается оранжевым цветом.
Такую проверку нужно осуществлять в момент изменения информации пользователем в таблице формы, то есть на стороне клиента. А также в момент открытия формы, когда она первоначально создается на стороне сервера.
К данной процедуре обращаются и из клиентской части, и из серверной.
Процедуры и функции с директивой компиляции &НаКлиентеНаСервереБезКонтекста нужно использовать для исключения дублирующего кода, когда он должен выполняться на стороне клиента и на стороне сервера.
Вывод. Из процедур или функций с директивой компиляции &НаКлиентеНаСервереБезКонтекста, нельзя обратиться к базе данных и им не доступен контекст формы, то есть никакие данные формы не доступны. Такие процедуры или функции используются для исключения дублирующих участков кода на клиентской и серверной частях.
Подводим итоги
В модулях управляемых форм можно использовать 4 директивы компиляции:
- &НаКлиенте – из процедур или функций нельзя обратиться к базе данных, но им доступен контекст формы, то есть все данные, которые есть на форме.
- &НаСервере – из процедур или функций можно обратиться к базе данных, а также доступен контекст формы, то есть все данные, которые есть на форме, но по сети передается избыточный трафик и есть определенная лишняя нагрузка на клиентскую и серверную части.
- &НаСервереБезКонтекста – из процедур или функций можно обратиться к базе данных, но при этом им не доступен контекст формы, то есть никакие данные формы не доступны. По сети передается оптимальный трафик и нет лишней нагрузки на клиентскую и серверную части.
- &НаКлиентеНаСервереБезКонтекста – из процедур или функций нельзя обратиться к базе данных и им не доступен контекст формы, то есть никакие данные формы не доступны. Такие процедуры или функции используются для исключения дублирующих участков кода на клиентской и серверной частях.
Ваганов Сергей, эксперт в области разработки прикладных решений на платформе 1С:Предприятие, преподаватель-методист CORS Academy и автор курса «Разработчик 1С с нуля до профессионала»
Подписывайтесь:
CORS Клуб – сообщество и образовательная среда для специалистов из IT-сферы https://cors.su/klub/
Канал руководителей IT компаний и подразделений, CIO, СDO, CDTO https://t.me/cio_channel
CIO. Сообщество IT руководителей https://vk.com/cio_club