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