23 December 2011

Базовый принцип программирования управляемой формы в 1С

Programming
Sandbox
Цель статьи – показать применение шаблонов Remote Facade и Data Transfer Object к структуризации кода, управляемой формы в среде 1С 8.2.


Введение


Начнем с небольшого описания понятия «управляемая форма» и связанных концепций платформы 1С. Знатоки платформы могут пропустить этот раздел.

В 2008 году стала доступна новая версия платформы 1С: Предприятие 8.2 (далее Управляемое приложение), которая полностью меняет весь слой работы с интерфейсом. Сюда относится и командный интерфейс, и формы, и оконная система. При этом не только меняется модель разработки пользовательского интерфейса в конфигурации, но и предлагается новая архитектура разделения функциональности между клиентским приложением и сервером.
Управляемое приложение поддерживает следующие типы клиентов:
  • Толстый клиент (обычный и управляемый режим запуска)
  • Тонкий клиент
  • Веб-клиент

В управляемом приложении используются формы, построенные на новой технологии. Они называются Управляемые формы. Для облегчения перехода прежние формы (т.н. Обычные формы) также поддерживаются, но их функциональность не развивается и они доступны только в режиме запуска толстого клиента.
Основные отличия управляемых форм для разработчика:
  • Декларативное, а не «по пикселям» описание структуры. Конкретное размещение элементов выполняется системой автоматически при отображении формы.
  • Вся функциональность формы описывается в виде реквизитов и команд. Реквизиты – это данные, с которыми работает форма, а команды – выполняемые действия.
  • Форма выполняется и на сервере и на клиенте.
  • В контексте клиента, недоступны практически все прикладные типы, и соответственно невозможно изменить данные в информационной базе.
  • Для каждого метода или переменной формы обязательно должна быть указана директива компиляции, определяющая, место выполнения (клиент или сервер) и доступ к контексту формы.

Перечислим директивы компиляции методов формы:
  • &НаКлиенте
  • &НаСервере
  • &НаСервереБезКонтекста
  • &НаКлиентеНаСервереБезКонтекста

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


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

Обозначим проблему


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

Рассмотрим структуру кода (модуль формы) в нескольких формах одной типовой конфигурации и попробуем найти закономерности.
Под структурой будем понимать секции кода (чаще всего это блоки комментариев) выделенные разработчиком для группировки методов и директивы компиляции этих методов.
Пример 1:
Секция обработчиков событий
Метод – наклиенте
Метод – насервере
Метод  - наклиенте
Секция служебных процедур и функций
Вспомогательные функции управления вводом

Пример 2:
Служебные процедуры и функции
Документы оплаты
Ценности
Обработчики событий

Пример 3:
Служебные процедуры на сервере
Служебные процедуры на клиенте
Служебные процедуры на сервере без контекста
Обработчики событий шапки
Обработчики событий команд

Пример 4:
Процедуры общего назначения
Обработчики событий формы
Процедуры подсистемы «контактная информация»

По сути, структура кода отсутствует, или мягче говоря, она аналогична тому, что было в формах 8.1:
  • Неинформативные слова «Общие, Служебные, Вспомогательные».
  • Робкие попытки разделить клиентские и серверные методы.
  • Часто методы группируются по интерфейсным элементам «Работа с табличной частью Товары, Контактной информацией».
  • Произвольное расположение методов и групп кода. Например, Обработчики событий могут быть в одной форме вверху, в другой внизу, в третьей вообще не выделены и т.д.
  • И не будем забывать, что это все в рамках одной конфигурации.
  • Да бывают конфигурации, в которых слова «Общие, Служебные, Вспомогательные» всегда находятся на одних и тех же местах но…

Зачем нужна структура кода?

  • Упрощение сопровождения.
  • Упрощение обучения.
  • Фиксация общих/важных/удачных принципов.
  • …ваш вариант

Почему существующий стандарт разработки от фирмы 1С не помогает?

Посмотрим опубликованные на дисках ИТС и в различных «Пособиях разработчика…» принципы, рекомендуемые при написании управляемой формы.
  • Минимизируйте число серверных вызовов.
  • Максимум вычислений на сервере.
  • Неконтекстные вызовы сервера быстрее контекстных.
  • Программируйте с учетом клиент-серверного взаимодействия.
  • и т.п.

Это лозунги, абсолютно верные, но как их реализовать? Как минимизировать число вызовов, что значит программировать в клиент-серверном режиме?

Шаблоны проектирования или мудрость поколений


Клиент-серверное взаимодействие используется в различных программных технологиях не один десяток лет. Ответ на обозначенные в предыдущем разделе вопросы давно известен и суммирован в двух базовых принципах.

Слово Мартину Фаулеру, его описание данных принципов:
  • каждый объект, потенциально предназначенный для удаленного доступа, должен иметь интерфейс с низкой степенью детализации, что позволит максимально уменьшить количество вызовов, необходимых для выполнения определенной процедуры. … Вместо того, чтобы запрашивать счёт и все его пункты отдельно, надо считать и обновить все пункты счёта за одно обращение. Это влияет на всю структуру объекта.…Запомните: интерфейс удаленного доступа не содержит логики домена.
  • …если бы я был заботливой мамой, то обязательно сказал бы своему ребенку: «Никогда не пиши объекты переноса данных!» В большинстве случаев объекты переноса данных представляют собой не более чем раздутый набор полей … Ценность этого омерзительного монстра состоит исключительно в возможности передавать по сети несколько элементов информации за один вызов — прием, который имеет большое значение для распределенных систем.


Примеры шаблонов в платформе 1С

Прикладной программный интерфейс доступный разработчику при разработке управляемой формы, содержит много примеров данных принципов.
Например метод ОткрытьФорму(), типичный «огрубленный» интерфейс.
ПараметрыОткрытия = Новый Структура("Параметр1, Параметр2, Параметр3", Значение1, Значение2, Значение3);
Форма = ОткрытьФорму(ИмяФормы, ПараметрыОткрытия);

Сравните с принятым в v8.1 стилем.
Форма = ПолучитьФорму(ИмяФормы);
Форма.Параметр1 = Значение1;
Форма.Параметр2 = Значение2;
Форма.Открыть();


В контексте управляемой формы множество «Объектов переноса данных». Можно выделить системные и определяемые разработчиком.
Системные моделируют на клиенте прикладной объект, в виде одного или несколько элементов данных формы. Создать их вне привязки к реквизитам формы нельзя.
  • ДанныеФормыСтруктура
  • ДанныеФормыКоллекция
  • ДанныеФормыСтруктураСКоллекцией
  • ДанныеФормыДерево

Преобразование системных объектов переноса данных в прикладные типы и обратно выполняется методами:
  • ЗначениеВДанныеФормы()
  • ДанныеФормыВЗначение()
  • КопироватьДанныеФормы()
  • ЗначениеВРеквизитФормы()
  • РеквизитФормыВЗначение()

Часто явное преобразование используется при адаптации существующего решения. Методы могут ожидать (использовать особенности) входные параметры, например ТаблицаЗначений, а не ДанныеФормыКоллекция, или метод был определен в контексте прикладного объекта и стал недоступен для прямого вызова из формы.
Пример 1С v8.1:
// на клиенте в контексте формы
ЗаполнитьКэшПользователей(ПодразделениеСсылка)

Пример 1С v8.2:
// на сервере в контексте формы
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
ОбработкаОбъект.ЗаполнитьКэшПользователей(ПодразделениеСсылка);
ЗначениеВРеквизитФормы(ОбработкаОбъект, "Объект");


Объекты переноса данных, структура которых определяется разработчиком это небольшое подмножество типов доступных и на клиенте и на сервере. Наиболее часто в качестве параметров и результатов методов «огрубленного» интерфейса используются:
  • Примитивные типы (строка, число, булево)
  • Структура
  • Соответствие
  • Массив
  • Ссылки на прикладные объекты (уникальный идентификатор и текстовое представление)

Пример: метод принимает список заказов для изменения статуса и возвращает клиенту описание ошибок.
&НаСервереБезКонтекста 
Функция СерверИзменитьСтатусЗаказов(Заказы, НовыйСтатус)
	
	Ошибки = Новый Соответствие(); // [заказ][описание ошибки]
	Для Каждого Заказ Из Заказы Цикл
		НачатьТранзакцию();
		Попытка
			ДокОб = Заказ.ПолучитьОбъект();
			…. другие действия, возможно не только с заказом…	
		Исключение
			ОтменитьТранзакцию();
			Ошибки.Вставить(Заказ, ОписаниеОшибки());
		КонецПопытки;
            КонецЦикла;
	Возврат Ошибки;
	
КонецФункции // СерверИзменитьСтатусЗаказов()


Структурируем код


Главные цели, которые должен отражать модуль управляемой формы и подходы к решению.
  • Четкое разделение клиентского и серверного кода. Не будем забывать, в момент выполнения это два взаимодействующих процесса, в каждом из которых существенно отличается доступный функционал.
  • Четкое выделение интерфейса удаленного доступа, какие методы сервера можно вызывать с клиента, а какие нельзя? Названия методов удаленного интерфейса начинаются с префикса «Сервер». Это позволяет, читая код сразу видеть переход управления на сервер, и упрощает использование контекстной подсказки. Отметим, что официальная рекомендация (ИТС) предлагает именовать методы с постфиксами, например, так ИзменитьСтатусЗаказовНаСервере(). Однако повторим не все серверные методы можно вызывать с клиента, и поэтому более важна логическая доступность, а не место компиляции. Поэтому префиксом «Сервер» отмечаем только методы доступные для клиента, метод-пример назовем СерверИзменитьСтатусЗаказов().
  • Удобочитаемость. Дело вкуса, принимаем порядок, когда модуль начинается с процедур создания формы на сервере и методов удаленного доступа.
  • Сопровождаемость. Должно быть однозначно определено место для добавления нового кода. Важный момент, автоматически создаваемые конфигуратором заготовки методов добавляются в конец модуля. Т.к чаще всего автоматически создаются обработчики событий элементов формы, то соответствующий блок расположен последним, чтобы не перетаскивать каждый обработчик в другое место модуля.

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





////////////////////////////////////////////////////////////////////////////////
// <(c) Автор="<?"", ИмяПользователя>" Дата="<?"", ДатаВремя,"ДФ=dd.MM.yyyy">"/>
// <Описание>
// <?>
// </Описание>

////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ МОДУЛЯ


////////////////////////////////////////////////////////////////////////////////
// НА СЕРВЕРЕ

//******* СОБЫТИЯ НА СЕРВЕРЕ *******

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
//Вставить содержимое обработчика
КонецПроцедуры

//******* ИНТЕРФЕЙС УДАЛЕННОГО ДОСТУПА *******

//******* БИЗНЕС-ЛОГИКА НА СЕРВЕРЕ *******

////////////////////////////////////////////////////////////////////////////////
// ОБЩИЕ МЕТОДЫ КЛИЕНТА И СЕРВЕРА

////////////////////////////////////////////////////////////////////////////////
// НА КЛИЕНТЕ

//******* БИЗНЕС-ЛОГИКА НА КЛИЕНТЕ *******

//******* КОМАНДЫ *******

//******* СОБЫТИЯ НА КЛИЕНТЕ *******

////////////////////////////////////////////////////////////////////////////////
// ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ


Связанные вопросы

В заключение обозначим несколько направлений, о которых полезно подумать при программировании клиент-серверного взаимодействия.
  • Варианты реализации интерфейса удаленного доступа. Асинхронность, степень детализации...
  • Кэширование. В 1С приняли неудачное архитектурное решение, введя кэширование только на уровне вызова методов общих модулей и не предоставив возможности управления (время актуальности, сброс по требованию).
  • Неявные серверные вызовы. Не забывайте о технологических особенностях, многие «безобидные» операции на клиенте провоцируют платформу на обращение к серверу.
  • Предварительная/отложенная загрузка данных.
Tags:1c 8.2шаблоны проектирования
Hubs: Programming
-1
194.3k 81
Comments 11
Top of the last 24 hours