Иерархия библиотек. Автоматическое обновление или как отказаться от переопределяемых модулей

04.03.19

База данных - Обновление 1С

В статье рассмотрен один из вариантов библиотечного подхода к разработке, позволяющий организовать иерархический вызов библиотечных процедур и упростить автоматическую сборку готового продукта из нескольких библиотек. Предлагаемый подход может служить одним из элементов CI/CD при разработке ПО на платформе 1С.

Платные

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
(только для физ. лиц)
Пример к статье. Базы и пакетные файлы для сборки.
.zip 240,55Kb
3 1 850 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний за 2430 руб. в месяц

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Для разработки сложного программного обеспечения, фирма 1С рекомендует использовать библиотечный подход. Он описан, например, в Системе стандартов и методик разработки. Одной из особенностей этого подхода является использование в библиотеках переопределяемых модулей, содержимое которых должно быть изменено при внедрении библиотеки. Сами разработчики методики признают, что существует 

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

а также

При обновлении версии библиотеки в конфигурации-потребителе особого внимания требуют модули корневого объекта конфигурации и переопределяемые общие модули, так как автоматическое обновление таких «узких мест» конфигурации-потребителя невозможно. 

А почему бы нам не сделать то, что кажется невозможным? Попробуем это на простом примере.

Итак, предположим нашей целью является автоматизация процесса продаж. Допустим, что в нашей системе должен быть документ "Продажа" с табличной частью "Товары", содержащей реквизиты "Номенклатура", "Цена", "Количество" и "Сумма". Базовым функционалом будет являться расчет 

Сумма = Количество * Цена

Этот расчет – функционал базовой библиотеки, которая будет лежать в основе остальных библиотек.

Возможно нам понадобится расчет налогов. Не вдаваясь в тонкости налогового учета, допустим что налог – это некая сумма, рассчитанная по ставке и просто добавляемая к основной сумме.

Сумма = Сумма * (100 + Ставка) / 100

Аналогичным образом формализуем учет скидок:

Сумма = Сумма * (100 - Скидка) / 100

Каждая из этих формул, а также объекты, содержащие все необходимые для расчета данные, реализованы в своей библиотеке. Но проблема в том, что запуск расчета производится в форме документа, в базовой библиотеке, в которой может быть ничего не известно о функционале, да и вообще о наличии других библиотек. Классический подход подразумевает реализацию в базовой библиотеке переопределяемого модуля расчета суммы, который в итоговой конфигурации должен быть дополнен (изменен) вызовами методов других библиотек. 

Но можно поступить иначе. Предположим, в итоговой конфигурации у нас есть некий перечень методов, вызывая которые, мы сделаем все необходимые расчеты. Список этих методов может быть различным, в зависимости от конкретной конфигурации. Каждый метод реализован в модуле своей библиотеки. Все что нужно сделать при запуске расчета в базовой библиотеке – это передать такой перечень механизму, который обработает каждый элемент этого списка. Но где задать нам этот список методов? Опять использовать переопределяемый модуль и получить проблемы с обновлением? А пусть он создается сам, в зависимости от наличия той или иной библиотеки! Давайте придумаем некий механизм, который в зависимости от наличия каких-нибудь объектов метаданных, поймет, какие методы каких модулей надо включить в список для выполнения расчета. Здесь появляется небольшая проблема: для поиска среди объектов метаданных можно использовать только имя, а объекты одного вида с одинаковым именем создавать нельзя. Т.е. нельзя в каждой библиотеке создать свой общий модуль с именем "РасчетСуммы" и объединить их в одну конфигурацию. Но можно создавать подсистемы с одинаковыми именами, если они принадлежат разным родителям. Получается следующая схема:

Для каждой библиотеки создана своя подсистема, в которой есть подсистема с именем "РасчетСумм". В составе последних включены общие модули, в которых реализован экспортный метод, выполняющий расчет (имена методов также одинаковы). Подсистемы библиотек лежат в пределах одной группы, для упрощения поиска. Таким образом, ориентируясь на имя подсистем "РасчетСумм" мы легко можем получить список модулей и методов для проведения расчета. 

Несколько слов по поводу выполнения этих методов. Самый простой вариант – создание некоего "менеджера", который будет последовательно вызывать каждую процедуру. Но я решил остановиться на другом способе – вызывать самую последнюю процедуру из списка и передавать ей управление. Решение о вызове предыдущего метода полностью возлагается на эту процедуру. Такой вариант более гибок – предыдущий метод может быть вызван в любом месте, а может и быть просто проигнорирован, если в нем нет нужды. Порядок методов в списке определяется порядком расположения подсистем библиотек внутри "ПереопределяемыеОбъектыБиблиотек".

Как это выглядит на практике:

В документе "Продажа" реализована команда:

&НаСервере
Процедура РассчитатьНаСервере(ИД)	
	ПараметрыРасчета = Объект.Товары.НайтиПоИдентификатору(ИД);
	Последовательность = УправлениеБиблиотекамиКлиентСервер.ПоследовательностьМодулейПроцедур("РасчетСумм");
	УправлениеБиблиотеками.ВыполнитьПредыдущуюПроцедуруНаСервере(ПараметрыРасчета, Последовательность);	
КонецПроцедуры

&НаКлиенте
Процедура Рассчитать(Команда)
	ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
	Если ТекущиеДанные <> Неопределено   Тогда   
		РассчитатьНаСервере(ТекущиеДанные.ПолучитьИдентификатор());	
	КонецЕсли; 	
КонецПроцедуры

В серверной процедуре получаем последовательность описаний методов и запускаем выполнение последнего из них. В нашем случае это будет РасчетСуммСоСкидкой.РасчетСумм

Процедура РасчетСумм(Параметр,Последовательность)Экспорт
	УправлениеБиблиотеками.ВыполнитьПредыдущуюПроцедуруНаСервере(Параметр, Последовательность);
	Скидка = РегистрыСведений.СкидкиНоменклатуры.Получить(новый Структура("Номенклатура",Параметр.Номенклатура)).Скидка;
	Параметр.Сумма = Параметр.Сумма * (100 - Скидка) / 100;
КонецПроцедуры

В процессе расчета мы сначала выполняем предыдущий метод РасчетСуммСНалогом.РасчетСумм, а затем производим обработку скидки.

Перед налоговым расчетом мы так же вызываем предыдущий метод РасчетСуммБазовый.РасчетСумм:

Процедура РасчетСумм(Параметр,Последовательность)Экспорт
	УправлениеБиблиотеками.ВыполнитьПредыдущуюПроцедуруНаСервере(Параметр, Последовательность);
	Параметр.Сумма = Параметр.Сумма * (100 + Константы.СтавкаНалога.Получить()) / 100;
КонецПроцедуры

В котором выполняем самый первый расчет.

Процедура РасчетСумм(Параметр,Последовательность)Экспорт
	УправлениеБиблиотеками.ВыполнитьПредыдущуюПроцедуруНаСервере(Параметр, Последовательность);
	Параметр.Сумма = Параметр.Количество * Параметр.Цена;
КонецПроцедуры

в последнем случае метод  УправлениеБиблиотеками.ВыполнитьПредыдущуюПроцедуруНаСервере не выполнит ничего, так как предыдущих процедур не осталось.

Описанный выше механизм можно применять и для других целей, например для создания общего списка строковых или табличных ресурсов. Вот так реализовано описание конфигурации, которое создается на основе табличных макетов, принадлежащих разным библиотекам:

В обработке "Инфо" создается общий табличный документ:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	ОписанияМакетов = УправлениеБиблиотекамиВызовСервера.ДопОбъектыПоВиду("Инфо");	
	Для каждого ОписаниеМакета Из ОписанияМакетов Цикл  		
		Таблица.Вывести(ПолучитьОбщийМакет(ОписаниеМакета.ИмяОбъекта));
	КонецЦикла; 	
КонецПроцедуры

Как внедрять или обновлять получившиеся библиотеки.

Процесс внедрения и обновления библиотек – обычное сравнение объединение конфигураций. В этом режиме надо отметить объекты по подсистемам файла: 

и выполнить объединение. При этом никаких других действий, таких как редактирования модулей, делать не надо. 

Подобное объединение можно проводить в автоматическом режиме. Для этого служит специальная команда пакетного режима конфигуратора. Пример такой команды:

1cv8.exe DESIGNER /F"c:\bases\prod\" /MergeCfg"c:\bases\lib2.cf" -Settings"c:\bases\UpdLib2Settings.xml"

здесь c:\bases\prod\ - путь к файловой базе, c:\bases\lib1.cf - конфигурация библиотеки, c:\bases\UpdLib1Settings.xml  - файл настроек объединения.

Файл настроек нужен для того, чтобы указать платформе, какие объекты следует объединить и правила такого объединения. Описание формата файла: https://its.1c.ru/db/v8314doc#bookmark:adm:TI000000713 . Пример файла:

<?xml version="1.0" encoding="UTF-8"?>
<Settings xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://v8.1c.ru/8.3/config/merge/settings" version="1.1">
	<Parameters>
		<AllowMainConfigurationObjectDeletion>true</AllowMainConfigurationObjectDeletion>
	</Parameters>
	<Objects>
		<Configuration>
			<MergeRule>DoNotMerge</MergeRule>
		</Configuration>
		<Object fullNameInSecondConfiguration="Подсистема.Скидки">
			<MergeRule>GetFromSecondConfiguration</MergeRule>
			<Subsystem configuration="Second" includeObjectsFromSubordinateSubsystems="true">
				<MergeRule>GetFromSecondConfiguration</MergeRule>
			</Subsystem>
		</Object>
		<Object fullName="Подсистема.Скидки">
			<MergeRule>GetFromSecondConfiguration</MergeRule>
			<Subsystem configuration="Main" includeObjectsFromSubordinateSubsystems="true">
				<MergeRule>GetFromSecondConfiguration</MergeRule>
			</Subsystem>
		</Object>
		<Object fullNameInSecondConfiguration="Подсистема.ПереопределяемыеОбъектыБиблиотек.Подсистема.Скидки">
			<MergeRule>GetFromSecondConfiguration</MergeRule>
			<Subsystem configuration="Second" includeObjectsFromSubordinateSubsystems="true">
				<MergeRule>GetFromSecondConfiguration</MergeRule>
			</Subsystem>
		</Object>
		<Object fullName="Подсистема.ПереопределяемыеОбъектыБиблиотек.Подсистема.Скидки">
			<MergeRule>GetFromSecondConfiguration</MergeRule>
			<Subsystem configuration="Main" includeObjectsFromSubordinateSubsystems="true">
				<MergeRule>GetFromSecondConfiguration</MergeRule>
			</Subsystem>
		</Object>
	</Objects>
</Settings>

здесь мы указываем, что не меняем свойства конфигурации, разрешаем удалять объекты, помечаем для объединения объекты нужных нам подсистем. Обратите внимание, что каждую подсистему мы указываем дважды: в новой конфигурации (для добавленных и измененных объектов) и в основной конфигурации (для измененных и удаленных объектов).

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

Итак, вот что мы получили: базовую библиотеку и две дополнительные библиотеки, на основе которых можем в автоматическом режиме собрать четыре разные конфигурации для разных заказчиков. Эти конфигурации различаются по функциональным возможностям и могут иметь разную продажную стоимость, что позволит более гибко составлять коммерческие предложения. 

Конечно же, предлагаемый подход не панацея. Так, он не поможет при работе с определяемыми типами, с переопределяемыми макетами и некоторыми другими объектами, но облегчить работу он может значительно. Надо отметить, что и стандартные возможности платформы включают в себе нечто подобное, хотя и менее функциональное. Это - подписки на события.

Рассмотренный пример вы можете увидеть в приложенном к статье файле. Это архив, содержащий в себе:

  • Папка base – базовая библиотека
  • Папки lib1, lib2 – 2 библиотеки
  • Папка prod – итоговая конфигурация
  • 1_CreateBase.bat – пакетный файл для создания итоговой конфигурации на основе базовой библиотеки
  • 2_AddLib1.bat, 3_AddLib2.bat – пакетные файлы для первоначального внедрения в итоговую конфигурацию библиотек lib1, lib2
  • 4_UpdLib1.bat, 5_UpdLib2.bat – пакетные файлы для обновления в итоговой конфигурации библиотек lib1, lib2
  • *Settings.xml – файлы с настройками объединения

Желательно чтобы все эти папки и файлы находились в каталоге c:\bases, так как в пакетных файлах используются абсолютные пути. Также надо указать путь к файлу 1cv8.exe в зависимости от версии платформы.

Библиотеки Переопределяемые CI CD Непрерывная интеграция автоматическое обновление объединение конфигураций

См. также

DevOps и автоматизация разработки Обновление 1С Системный администратор Программист 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление холдингом Абонемент ($m)

Продолжаем делиться опытом ICL SOFT – в этой статье рассказываем о сложном обновлении сильно доработанной конфигурации "1С:ERP Управление холдингом с версии 3.1.8.15" до актуальной версии редакции 3.2. Публикации о сложных обновлениях, которые можно найти в открытых источниках, содержат мало подробной информации об использованных инструментах и решениях. Часто в них отсутствует информация о том, что находится под капотом этих решений. Будем рады, если наша статья окажется полезной

1 стартмани

вчера в 13:00    264    vladimir_iclsoft    0    

6

Рефакторинг и качество кода Обновление 1С Программист 1С v8.3 Бесплатно (free)

Тестовая база обновлена через все ключевые релизы, всё протестировано, остатки сведены, вы готовы обновить «боевую» базу, но…по замерам для этого потребуется целая неделя, а у вас есть всего пара выходных. Знакомая ситуация? Расскажем, как увеличить скорость отработки промежуточных конфигураций!

18.06.2025    1587    1c-izh    12    

8

Обновление 1С Программист Стажер 1С v8.3 Бесплатно (free)

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

04.06.2025    2960    1c-izh    6    

16

Обновление 1С 1С v8.3 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Абонемент ($m)

Добавление в Справочник "Статьи затрат" отсутствующих предопределённых элементов.

1 стартмани

23.05.2025    380    0    qrw    0    

0

БСП (Библиотека стандартных подсистем) Обновление 1С Программист 1C:ERP Бесплатно (free)

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

29.04.2025    2220    krasnoshchekovpavel    7    

17

Рефакторинг и качество кода Обновление 1С Программист 1С v8.3 Бесплатно (free)

Методика, описанная в статье, выработана при переезде с 1С:ДО 2.1 на 1С:ДО 3.0. Может также применяться при переходе с 1С:УПП на 1C:ERP, 1C:ERP на 1C:ERP УХ и т. п. Учтены все необходимые доработки при переезде на новую конфигурацию и предупреждены возможные ошибки.

21.04.2025    2500    PROSTO-1C    4    

4

Обновление 1С Программист 1С v8.3 1C:Бухгалтерия 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1C:ERP Абонемент ($m)

Внешняя обработка для обновления расширений и дополнительных обработок 1С из GitHub. Поддерживает как публичные, так и приватные репозитории, фильтрацию релизов по версии конфигурации, скачивание .cfe, .epf, .erf.

1 стартмани

15.04.2025    1956    7    Aleksandr    0    

21

Обновление 1С Системный администратор Программист 1С v8.3 Абонемент ($m)

Скрипт для загрузки конфигурации в 1С, обновления базы и архивации файла с логированием.

1 стартмани

02.04.2025    1061    3    DoubleT    8    

5
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. pm74 204 04.03.19 09:27 Сейчас в теме
где и как определяется порядок выполнения процедур
2. Alxby 1133 04.03.19 10:30 Сейчас в теме
(1)
Порядок методов в списке определяется порядком расположения подсистем библиотек внутри "ПереопределяемыеОбъектыБиблиотек".
Первой вызывается последняя процедура списка. В каждой процедуре вызов предыдущей может располагаться как в начале, до ее выполнения, так и в конце, как впрочем и в любом другом месте. Вызов предыдущей процедуры может и вовсе отсутствовать.
Леонов Александр; +1 Ответить
3. sdf_tm 01.04.19 13:35 Сейчас в теме
Супер!
Вы изобрели наследование классов в 1с :)

кстати - в аксапте именно super() вызывает родительский класс (из вышестоящего слоя)
см. напр

http://gennadyyun.blogspot.com/2007/07/1_23.html
http://gennadyyun.blogspot.com/2007/07/2_23.html
http://gennadyyun.blogspot.com/2007/07/x-1.html
4. Alxby 1133 31.05.19 16:49 Сейчас в теме
(3)Спасибо за ссылки! Все-таки это не совсем (а точнее совсем не) наследование классов. У меня не было цели моделировать соответствующий подход ООП. В Вашем примере, насколько я понял, дочерний класс унаследован от родительского и точно известно, метод какого родительского класса будет выполнен при вызове из дочернего. В моем же случае итоговая конфигурация может быть собрана из произвольного набора библиотек, поэтому вызов «предыдущего» метода означает вызов метода какой-то библиотеки, которая стоит предыдущей в последовательности. Больше всего это похоже на механизм hook-ов или подписок на события в 1С – мы выполняем свою реализацию какого-то существующего функционала, и при необходимости передаем управление дальше по цепочке стандартному обработчику. Или наоборот – выполняем стандартный обработчик, а потом свой. Причем в общем случае мы не знаем ни о наличии других обработчиков, ни об их порядке.
Леонов Александр; +1 Ответить
Оставьте свое сообщение