В процессе длительного сопровождения информационных систем на базе 1С, особенно таких сложных, как Управление торговлей 11, ERP или Комплексная автоматизация, часто возникает ситуация «зоопарка» расширений. Разные разработчики в разное время создавали свои расширения для решения локальных задач. В итоге мы получаем конфигурацию, в которой функционирует 4, 5 и более расширений, зачастую заимствующих одни и те же объекты. Это не только замедляет работу системы, но и делает практически невозможной отладку и дальнейшее развитие.
Самая большая сложность при объединении таких расширений заключается не в переносе программного кода (директив &Перед, &После или &Вместо), а в сохранении данных, которые пользователи уже успели внести в добавленные справочники, документы и реквизиты. Разберем подробно, как решить эту задачу и какие подводные камни нас ожидают.
Проанализируем, как платформа 1С хранит данные расширений на уровне системы управления базами данных (СУБД). Каждое расширение — это фактически отдельная логическая сущность. Когда вы добавляете новый реквизит в расширение, платформа создает в SQL-базе соответствующее поле, но его имя содержит уникальный префикс, привязанный к конкретному расширению.
Если мы просто создадим реквизит с таким же именем в новом «объединенном» расширении, платформа создаст для него новую колонку в таблице SQL. Старые данные останутся привязанными к идентификатору старого расширения. Как только старое расширение будет удалено, платформа инициирует команду DROP COLUMN или DROP TABLE в СУБД, и данные будут безвозвратно потеряны. Именно поэтому простое визуальное копирование метаданных не является решением.
Рассмотрим наиболее надежный способ объединения, который минимизирует риски потери данных. Этот метод основан на использовании механизмов выгрузки и загрузки данных в формате XML с обязательным сохранением ссылочной целостности.
.cfe. Создаем новую пустую конфигурацию (или новое расширение) и через механизм «Сравнение и объединение» собираем в него все объекты из исходных расширений. На этом этапе необходимо вручную разрешить конфликты в программных модулях и формах.Проанализируем ситуацию: если у вас в Расширении_1 был справочник ДополнительныеСвойстваНоменклатуры, и на него ссылаются документы из основной конфигурации, то при пересоздании справочника в новом расширении все ссылки могут «побиться», поэтому важно выполнить сравнение и замену UUID объектов.
Чтобы этого избежать, при программном переносе или использовании XML-выгрузки необходимо гарантировать сохранение UUID. Если вы пишете собственную обработку для миграции, обязательно используйте метод УстановитьСсылкуНового(). Посмотрим на пример кода:
// Пример сохранения UUID при переносе данных
НовыйОбъект = Справочники.ДополнительныеСвойства.СоздатьЭлемент();
// Получаем ссылку, которая была в старом расширении (выгруженную ранее)
СтараяСсылка = Справочники.ДополнительныеСвойства.ПолучитьСсылку(НовыйУникальныйИдентификаторИзФайла);
НовыйОбъект.УстановитьСсылкуНового(СтараяСсылка);
// Заполняем реквизиты...
НовыйОбъект.Наименование = "Значение из старого расширения";
НовыйОбъект.Записать();
Выясним причину, по которой некоторые разработчики предпочитают более длинный, но иногда более безопасный путь через основную конфигурацию. Начиная с версии платформы 8.3.24, появился штатный механизм «Перенос в основную конфигурацию».
Если политика компании позволяет (или если это временная мера на копии базы), мы можем:
При объединении нескольких расширений в одно мы неизбежно столкнемся с тем, что разные расширения модифицировали одну и ту же форму. В этом случае поможет объединение модулей с помощью KDiff3. Разберем, как правильно объединять такие изменения:
Проанализируем порядок выполнения кода. В разных расширениях могли быть аннотации &После для одного и того же метода. При слиянии в одно расширение вам придется объединить этот код в один метод. Важно соблюдать последовательность, которая была ранее задана приоритетом (порядком) расширений. Если Расширение_1 имело более низкий приоритет, чем Расширение_2, то его код &После выполнялся первым. В объединенном модуле его фрагмент кода также должен идти выше.
Рассмотрим альтернативный совет, прозвучавший в обсуждении: использование механизма «Дополнительные реквизиты и сведения» (БСП). Если большая часть данных в ваших расширениях — это просто дополнительные поля в существующих справочниках, иногда целесообразнее перенести их в типовой механизм ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.
Преимущества такого подхода:
Для миграции в доп. реквизиты потребуется написать простую обработку, которая прочитает данные из полей расширения и запишет их в табличную часть ДополнительныеРеквизиты соответствующего объекта.
Подводя итог, можно сказать, что объединение расширений или их конвертация в патчи — это не столько задача программирования, сколько задача по аккуратной миграции данных.
Рассмотрим краткий чек-лист перед началом работ:
EnterpriseData или XDTO для переноса, если стандартная «Выгрузка/загрузка XML» не справляется из-за различий в именах пространств имен (Namespace).Layout (расположение элементов на формах) после объединения. Часто «привязки» элементов в расширениях конфликтуют между собой, и формы «разваливаются».УстановитьСсылкуНового() для всех новых справочников, чтобы сохранить связи с документами основной базы.Помните, что платформа 1С постоянно развивается, и механизмы работы с расширениями становятся более гибкими, однако ручной контроль за физическим хранением данных в SQL по-прежнему остается за разработчиком.