Неоднократно возникала и возникает необходимость в гибком наборе полей, будь то реквизиты справочников и документов, измерения ресурсов и т.д. Частичным решением проблемы стали вводимые пользователями свойства, связанные с механизмом планов видов характеристик. Эта механика практикуется во всех типовых конфигурациях последние годы, показала свою полезность, но имеет один недостаток: можно добавить лишь шапочные свойства и лишь к справочникам и документам.
Целью данной заметки является краткое описание концепции, позволяющей создавать и поддерживать более широкие возможности – расширяемые регистры и табличные части. Реализация данных механизмов представляется оптимальной в виде подсистемы с высокой степенью портируемости и универсальности. Опишем объекты, входящие в подсистему, применив взятую для удобства нотацию имён. Нотация имён имеет рекомендательный характер.
План видов характеристик «Разрезы сочетаний». ПВХ описывает состав и типы данных для изменяемых функционалов, т.е., как и в классическом варианте, описывает «добавляемые» пользователем поля. Если в конфигурации есть несколько задач, решаемых описываемым способом, можно сделать ПВХ иерархическим. Реквизиты – на усмотрение разработчика. В зависимости от решаемых задач варьируются допустимые типы.
Справочник «Сочетания разрезов». Справочник собственно содержит конкретные данные всех изменяемых функционалов, значения «добавленных» пользователем полей. Рекомендуется делать его иерархическим с иерархией групп, что позволит повысить скорость работы с подмножествами его элементов через использование штатной механики платформы, но можно обойтись и без иерархии. Также можно задействовать связь по владельцу. Рекомендуется использовать представление в виде кода и сделать длину наименования нулевой. Если в конфигурации есть несколько задач, решаемых описанным способом, и по каждой прогнозируется рост объёмов данных, имеет смысл создавать отдельные справочники одинаковой структуры – это распараллелит нагрузку. Группа справочника может иметь реквизиты, ускоряющие её обнаружение и, через неё, работу с её элементами. Элемент справочника может не иметь шапочных реквизитов (это – на усмотрение разработчика), но обязательно должен иметь табличную часть «Состав сочетания», содержащую 2 реквизита: «Разрез» (ссылка на ПВХ «Разрезы сочетаний») и «ЗначениеРазреза» (характеристика ПВХ «Разрезы сочетаний»). Каждый элемент справочника содержит уникальное сочетание значений «ЗначенийРазрезов», таким образом, двух элементов с абсолютно идентичными табличными частями быть не должно. Это достигается функционалом общего модуля – поиском имеющихся сочетаний, и лежит на совести разработчика. Именно уникальность элементов принципиально важна.
Общий модуль «РаботаССочетаниями», с возможностью выполнения на сервере, где расположены нужные процедуры и функции. По сути можно предложить такие, как «НайтиСочетаниеРазрезов» и «СоздатьОбновитьСочетаниеРазрезов». Их аргументом будет таблица значений, аналогичная табличной части справочника «Сочетания разрезов», а их задачи будут заключаться в поиске имеющегося сочетания по указанному образцу и в создании либо обновлении имеющегося сочетания (ранее найденного по, возможно, другому набору значений разрезов). Очевидно, что для этого следует использовать характеристический механизм запросов с помощью СКД.
Примерный вид запроса для СКД:
ВЫБРАТЬ Сочетания.Ссылка КАК СочетаниеСсылка ИЗ Справочник.СочетанияРазрезов КАК Сочетания ГДЕ Сочетания.ПометкаУдаления = Ложь И Сочетания.Ссылка В ИЕРАРХИИ (&УслРодительскаяГруппа) // и любое другое условие, позволяющее ограничить объём выборки {ХАРАКТЕРИСТИКИ ТИП(Справочник.СочетанияРазрезов) ВИДЫХАРАКТЕРИСТИК (ВЫБРАТЬ ПВХРазрезыСочетаний.Ссылка КАК ПВХРазрез, ПВХРазрезыСочетаний.Наименование КАК ПВХНаименование, ПВХРазрезыСочетаний.ТипЗначения КАК ПВХТипЗначения ИЗ ПланВидовХарактеристик.РазрезыСочетаний КАК ПВХРазрезыСочетаний ГДЕ ПВХРазрезыСочетаний.ЭтоГруппа = Ложь) ПОЛЕКЛЮЧА ПВХРазрез ПОЛЕИМЕНИ ПВХНаименование ПОЛЕТИПАЗНАЧЕНИЯ ПВХТипЗначения ЗНАЧЕНИЯХАРАКТЕРИСТИК (ВЫБРАТЬ Состав.Ссылка КАК Сочетание, Состав.Разрез КАК Разрез, Состав.ЗначениеРазреза КАК ЗначениеРазреза ИЗ Справочник.СочетанияРазрезов.СоставСочетанияРазрезов КАК Состав И Состав.ПометкаУдаления = Ложь И Состав.Ссылка В ИЕРАРХИИ (&УслРодительскаяГруппа) // и любое другое условие, позволяющее ограничить объём выборки ) ПОЛЕОБЪЕКТА Сочетание ПОЛЕВИДА Разрез ПОЛЕЗНАЧЕНИЯ ЗначениеРазреза}
За внешний вид запроса благодарю обработку Evg-Lylyk (хотя сделать переносы строк и вариант для не-управляемых форм было б невредно, ага)
Очевидно, что для поиска нужных сочетаний следует наложить условия на поля СКД, соблюдая их нотацию. Напомню, при наличии символов, недопустимых в именах системных полей, платформа выполняет неявное преобразование данных, переданных ей в ПОЛЕИМЕНИ, и следует соблюдать правила написания пути к данным в отборах СКД, т.е. нечто вида «СочетаниеСсылка.[«+ПолеКакЕгоОбозвалаСКД+»]».
Собственно реализация может быть любой. Рассмотрим на примере регистра сведений с составом, управляемым пользователем. Предположим, нам нужен регистр сведений, хранящий отпускные цены, зависящие от заранее неизвестного набора значений, и состав этого набора непредсказуем. Так, пусть цена зависит от группы контрагентов и региона. Регистр будет иметь лишь одно обязательное измерение (остальное – на усмотрение разработчика), а именно «СочетаниеРазрезов», ссылку на справочник. Опустим интерфейсные ухищрения, заметим лишь, что для пользователя рабочая таблица регистра должна иметь привычный вид: колонки измерений, ресурсов и реквизитов, и что для организации такого интерфейса следует предпринять определённые усилия по написанию кода. Впрочем, можно лишь незначительно доработать форму списка, обеспечив прямой переход к просмотру/редактированию каждого элемента справочника.
Главное в работе с регистром то, что вместо статично заданных измерений пользователь имеет дело со строками табличных частей элементов справочника, являющегося измерением. Каждый элемент справочника уникален. При появлении нового сочетания значений создаётся новый элемент справочника. Таким образом, справочник содержит все имеющиеся варианты значений в их сочетаниях, и каждый набор сочетаний позволяет найти соответствующий элемент, а зная его, и запись в регистре. Изменения в составе разрезов могут и должны сказываться на составе табличных частей элементов справочника, но суть не изменится – единственным измерением будет сам этот справочник, хотя для пользователя он может быть сделан вообще «скрытым» чисто интерфейсными средствами или через RLS.
Аналогично, можно сделать табличную часть объекта, где одним из реквизитов будет ссылка на справочник «Сочетания разрезов». Тогда для пользователя состав данных этой табличной части будет столь широк, сколько разрезов фигурирует в табличных частях справочников, и опять-таки это будет в распоряжении пользователя.
В общем случае количество строк в табличных частях разных элементов справочника может быть совершенно разным, поэтому вопрос актуализации и синхронизации целиком ложится на разработчика. Так, если ранее практиковались 2 разреза («Группа контрагентов» и «Регион»), а позже пользователь ввёл разрез «Категория товара», то табличные части элементов справочника, созданные ранее, могут остаться неизменными, если реализация рабочих модулей будет это учитывать; в противном случае следует продумать дописывание в табличных частях строки с новым разрезом и пустым значением (по сути, ту же операцию, что делает платформа при добавлении измерения в регистр разработчиком). Аналогично следует не забыть обработку случаев изменения типа значений ПВХ или удаления элемента ПВХ.
На следующем этапе развития подсистемы можно ввести понятие шаблона, образца сочетания разрезов, и обеспечить наполнение табличных частей не любыми разрезами и их значениями, а только входящими в образец. Это позволит ещё оптимизировать работу с содержимым справочника. Можно при описании образца указывать, является ли значение того или иного разреза обязательным или нет, можно создать механику избирательного доступа к тем или иным значениям разрезов и т.д., вплоть до конструирования псевдо-OLAP систем, т.е. принципа управляемой многомерности, чему, возможно, будет посвящена следующая заметка.
Было бы неплохо увидеть базу с примером использования. Заранее благодарю, если поделитесь
(1) Есть мысль доделать нормальную подсистему, постараюсь выложить в ближайшие дни. Сейчас оно так лихо интегрировано, что придётся выкладывать всю конфу, а это мне низя.
Изложенная концепция успешно используется на практике уже год, поэтому и решил поделиться. Если что-то не подробно, постараюсь детализировать.
Идея замечательная. Конечно, реализацию в виде готовой подсистемы хотелось бы иметь. Как дела с производительностью?
(3) Если делать на большие объёмы один неиерархический справочник — дела с производительностью так себе. Если же предпринимать усилия по всякой оптимизации, то очень даже неплохо. Упомянутый запрос у меня на ста тысячах элементов отрабатывает за пару секунд, и это на файловой базе.
Реализацию ещё выдрать из конфы надо. 🙂
Да если глянуть примерчик было бы очень здорово но смущает выборка всего из 100000 и уже не быстро а что такое 100000? Поэтому смотреть и тестить. Заранее спасибо
(5) Когда планируется большое количество разрезов, т.е. большое количество вариантов их сочетаний без повторений (порядок разрезов считаем неважным), то, конечно, будет и много больше ста тысяч. Сам тоже «буду посмотреть», как оно живёт на SQL, т.к., повторюсь, база файловая.
Тут ведь в чём гадость: СКД не позволяет нормально оптимизировать выборки внутри секции запроса характеристик. Ни временных таблиц, ничего, увы. Это считаю узким местом.
(4) Хорошо, подождем. А по производительности: есть ощущение, если вместо табличной части справочника сочетаний использовать вспомогательный регистр сведений с его возможностью кластерного индекса, то будет быстрее. Хотя если и так все хорошо, то ломать не стоит 🙂
Интересно интересно.Мое мнение нужно ето дело увидеть на практике. Автору за идею и за работу спасибо, ну и конечно заслуженое 5+++++
Идея — безусловно — многообещающщщая, поставил закладку, буду вдумчиво перечитывать, и если подсистема появится — будет вообще здорово!
ЗЫ Однако терминология… Прочитав «Разрезы сочетаний» …… «Сочетания разрезов» — минут 15 не мог сосредоточиться —
это ж «План по валу» — «Вал по плану!»
(9) Согласен, вернее, конечно, формулировка «Сочетания конкретных значений разрезов». Но длинно.
(10) по смыслу чем-то напоминает ключи аналитики из РАУЗ. Может, так и назвать: ПВХДопАналитика и КлючиДопАналитики?
«Значениz разрезов» — чем не подходит такое название?
(13) Можно, только и «ДопАналитика» бывает разная. Вообще да, вопрос терминологии довольно остро стоит для этой задачи. Какие ещё есть предложения?
Я посмотрю, какие варианты, и когда буду выкладывать подсистему, уже сделаю в ней именно такую нотацию.
(0) как концепция статья понравилась. напишите пожалуйста изначальную постановку задачи. думаю, что задачу возможно решить более «легковоспринимаемым» способом.
а на практике за счет увеличения взамосвязей объектов метаданных происходит усложнение разработки, доработки, отладки: к примеру, как в Комплексной конфигурации реализованы регистры РАУЗ? Через такой же расширяемый регистр. Только в измерениях справочник — ключ, являющийся комбинацией всех своих реквизитов, в реквизитах тоже справочники-ключи, являющиеся комбинациями своих реквизитов. Можно продолжить ряд…
А такое видели? Справочник содержит предопределенные макеты на СКД — по сути запросы к базе. Теперь для любого элемента этого справочника можно выбрать реквизит — какой конкретно способ (по сути запрос) будет использоваться при закрытии месяца. кто в курсе меня поправит…
Или кто-нибудь видел БГУ? Там тоже много интересного: в каждом документе определяется ЛокальнаяПеременная через название, тип этой переменной изменяется в зависимости от переданного названия. Или как определяется доступность реквизитов и значения по умолчанию для документов в БГУ? Через справочник ВидОперации — который является ключевым реквизитом в таких справочниках как РеквизитыДокументовПрочие, РеквизитыЕСПБУ. Кто в курсе меня поправит 🙂
Это все примеры того, как на базовые объекты конфигурации (нижний уровень) накладываются сложные для восприятия взаимосвязи (средний уровень), и получаются механизмы иного порядка (верхний уровень). И тогда с помощью таких пирамид решаются задачи уже другого порядка.
Мда, для разработчиков настоящая головоломка…
Любопытно. Буду следить за развитием идеи.
(14) про РАУЗ ничего не знаю, честно. А этой концепции, которую я описал в заметке, уж года четыре. Просто решил опубликовать наконец.
(14)Занятно. Может статейку кто накрапает о подобных принципах? Думаю, будет популярна. Самому вскоре придется что-то придумывать на эту тему, было бы интересно иметь сведения из практики. А то лезут в голову всякие мысли иногда, типа «возможно ли внешнее регламентное задание…» 🙂
(14) Изначальной задачей был регистр сведений с неизвестным заранее набором измерений. Ровно то, что описано в примере. Возможность пользователя менять мерность и характер измерений регистра.
(18) Это же постановка задачи на языке разработчика. А постановка задач на языке клиента есть? Все ли меня понимают, о чем я прошу? 🙂
(16)
У меня лично при виде подобной статьи в первую очередь возникает вопрос: в РАУЗе-то оптимизирована структура для уменьшения возможности конфликтов взаимоблокировок.. а как тут?
И — да, на порядок возрастает сложность доработок подобных систем, если они обоснованно необходимы, конечно.
(19) А на языке клиента ничего конкретного не было. Клиент сам не знал, от чего будут зависеть цены, и всё сводилось к обычному «сделайте, чтобы работало и мы могли сами поменять». Даже нормального ТЗ не состоялось.
(20) Возможно, скажу глупость, но — а какие тут могут быть взаимоблокировки? Это ведь справочник. чтение — есть чтение, без блокировки для изменения. Каждое действие происходит только с одним элементом, чистая объектная блокировка силами платформы. Или я не понял, о чём речь?
Насчёт возрастания сложности на порядок — не соглашусь. Если не дорабатывать сам механизм, а просто его юзать, то ничего особенного, сужу по своим коллегам.
Идея не плохая. У нас сейчас стоит та же задача. Поэтому очень интересно Ваше решение.
(22) Ни сил, ни времени выламывать подсистему из готовых решений, к сожалению, нет. Могу разве только совсем грубо «кусок выдрать».
Если не затруднит, то было бы здорово!