Разработчики при кастомизации типовых конфигураций 1С часто сталкиваются с дилеммой: как правильно доработать интерфейс или модуль формы с помощью механизма расширений, чтобы при очередном обновлении от поставщика ничего «не сломалось»? Типичное опасение заключается в том, что пользователь после обновления может увидеть устаревшую версию формы из расширения, пропустив важные новые элементы, добавленные разработчиками 1С в основную конфигурацию. В этой статье мы подробно разберем, как именно работает механизм объединения форм, что представляет собой «сохраненная форма» в расширении и как современные стандарты разработки помогают избежать конфликтов при обновлениях.
Для того чтобы понять, почему в одних случаях новые элементы поставщика появляются на форме, а в других — «залипает» старый интерфейс, проанализируем ситуацию с точки зрения платформы «1С:Предприятие». При запуске клиентского приложения происходит динамическое построение результирующей управляемой формы. Этот процесс регламентирован платформой и происходит по строгому алгоритму.
Рассмотрим подробнее этапы построения результирующего интерфейса:
Таким образом, если поставщик конфигурации добавил на форму новый реквизит или кнопку, а вы в своем расширении эту форму заимствовали, но визуально не изменяли (или меняли только логику модуля), то вступает в силу Правило 2. Новый элемент поставщика гарантированно отобразится у пользователя в режиме «1С:Предприятие».
Выясним причину, почему разработчики иногда сталкиваются с тем, что форма «залипает» в старом состоянии. Ключевым понятием здесь является сохраненная форма.
Когда вы заимствуете форму в расширение, конфигуратор фиксирует ее структуру, свойства элементов и состав реквизитов на этот конкретный момент времени. Эта копия «замораживается» внутри метаданных расширения и называется сохраненной формой. При обновлении конфигурации поставщика платформа сравнивает текущую форму поставщика и вашу форму в расширении именно с этой «замороженной» точкой отсчета.
Если вы просто заимствовали форму для изменения кода в модуле формы (например, перехватили событие ПриИзменении какого-то реквизита), то визуальная структура формы в расширении совпадает с сохраненной формой. При обновлении платформа видит, что визуальных изменений в расширении нет, и без проблем переносит новые элементы поставщика на форму пользователя.
Проблема возникает в том случае, если вы интерактивно в редакторе формы расширения изменили положение элементов, их видимость, доступность или другие свойства. В этом случае платформа фиксирует расхождение между сохраненной формой и формой расширения. При обновлении это может привести к конфликту по Правилу 4, и изменения поставщика могут перекрыться вашими интерфейсными правками в расширении.
Для того чтобы избежать рассинхронизации сохраненной формы и формы основной конфигурации после обновления, в платформу встроен специальный механизм контроля:
Когда вы открываете форму в конфигураторе расширения после того, как основная конфигурация была обновлена, платформа сверяет структуру. Если обнаружены различия, в верхней части редактора формы появляется предупреждающая желтая полоса с предложением обновить форму в расширении.
Также в командной панели редактора формы доступна специальная кнопка «Обновить расширение формы». Нажатие на эту кнопку перезаписывает сохраненную форму внутри расширения, приводя ее в соответствие с новым актуальным состоянием формы поставщика, при этом сохраняя все ваши доработки модуля и уникальные добавленные элементы.
Хотя интерактивное объединение форм в платформе 1С v8.3 работает достаточно надежно, ведущие разработчики и стандарты БСП (Библиотеки Стандартных Подсистем) рекомендуют использовать полностью программный метод доработки интерфейса. Этот подход сводит вероятность конфликтов при обновлениях к нулю.
Суть метода заключается в том, что форма заимствуется в расширение исключительно ради модуля (без заимствования элементов формы в редактор). Все новые элементы интерфейса создаются динамически в коде модуля формы.
Разберем по шагам, как программно добавить элемент на форму и привязать к нему обработчик события:
ПриСозданииНаСервере с аннотацией &После.Посмотрим на практический пример реализации такого кода:
&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Выясним причину, есть ли уже родительская группа на форме
РодительскаяГруппа = Элементы.Найти("ГруппаТехническиеРеквизиты");
Если РодительскаяГруппа = Неопределено Тогда
РодительскаяГруппа = Элементы.Форма;
КонецЕсли;
// Программно добавляем новое поле ввода на форму
НовоеПоле = Элементы.Добавить("Расш_ДополнительноеОписание", Тип("ПолеФормы"), РодительскаяГруппа);
НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
НовоеПоле.ПутьКДанным = "Объект.ДополнительноеОписание";
НовоеПоле.Заголовок = "Доп. описание (расширение)";
// Устанавливаем действие (подключаем обработчик события ПриИзменении)
НовоеПоле.УстановитьДействие("ПриИзменении", "Расш_ДополнительноеОписаниеПриИзменении");
КонецПроцедуры
После этого в модуле формы расширения мы описываем процедуру-обработчик события, которая будет вызываться на клиенте при изменении созданного поля:
&НаКлиенте
Процедура Расш_ДополнительноеОписаниеПриИзменении(Элемент)
// Описываем логику обработки изменения реквизита
ПоказатьПредупреждение(, "Значение дополнительного описания успешно изменено!");
КонецПроцедуры
При таком подходе визуальная структура формы в расширении остается абсолютно чистой. Вы можете обновлять типовую конфигурацию сколько угодно раз — любые новые кнопки, вкладки и поля поставщика будут беспрепятственно отображаться на форме, а ваш программный код просто добавит нужные элементы поверх актуального интерфейса в момент открытия формы пользователем.
Проанализируем ситуацию, когда одну и ту же форму пытаются изменить сразу несколько независимых расширений. Если в разных расширениях форма была изменена визуально (интерактивно), то может возникнуть конфликт затирания настроек. Платформа применит настройки интерфейса из того расширения, которое выполняется последним по порядку применения (принцип «last-write wins»).
Программный метод изменения формы решает и эту проблему. Если несколько расширений дорабатывают одну форму через метод ПриСозданииНаСервере с аннотацией &После, платформа выполнит их последовательно друг за другом. В результате элементы из всех расширений корректно добавятся на форму без конфликтов и взаимного затирания.
Начиная с версии платформы 8.3.20 и выше, разработчики 1С значительно повысили стабильность работы механизма расширений. Если раньше при возникновении критической ошибки в модуле расширения формы (например, если поставщик удалил реквизит, к которому обращался код вашего расширения) приложение аварийно завершало работу, то теперь поведение изменилось.
Платформа выведет предупреждение пользователю о невозможности применить расширение, но продолжит работу системы, временно отключив проблемные обработчики расширения и выполнив стандартный код формы из основной конфигурации. Это позволяет избежать критической остановки бизнес-процессов организации из-за локальных сбоев при обновлении.
Также, начиная с версии 8.3.22+, в конфигураторе появилась улучшенная проверка применимости расширений. С помощью команды «Проверка применимости расширений» вы можете заранее, еще до запуска предприятия, узнать о том, что поставщик удалил или переименовал методы, к которым обращается ваше расширение.