От V7 к V8. Обсуждение концепций структур данных. Функциональные зависимости.

Как известно, Функциональная Зависимость (далее ФЗ) является одним из ключевых понятий теории реляционных БД при обсуждении проблем нормализации БД. Здесь же мы используем терминологию ФЗ...

Как известно, Функциональная Зависимость (далее ФЗ) является одним из ключевых понятий теории реляционных БД при обсуждении проблем нормализации БД. Здесь же мы используем терминологию ФЗ для повышения уровня абстракции объектов Регистры в V7, связать в единое целое понятия Периодические Реквизиты, Регистры, Проведение Документов.

Итак, суть понятия ФЗ состоит в том, что существует особый класс ТД, в которых значения одних реквизитов (детерминант ФЗ) определяют значения других (зависимая часть). Пока будем рассматривать только однозначные ФЗ, то есть и такие ФЗ, при задании детерминанта которых зависимая часть принимает единственное значение.

Будем использовать следующий способ записи ФЗ:

{ Детерминант: Зависимая часть }

Как детерминант, так и зависимая часть могут состоять из нескольких полей (реквизитов). Поля детерминанта будем называть Измерениями, поля зависимой части – Ресурсами. Пример простейшей (тривиальной) ФЗ – простой атрибут справочника:
{#Фирма: Дата регистрации}.

Здесь будет уместным сказать о необходимости расширения понятия атрибут (реквизит) в V7. Во-первых, необходимо дать возможность в явном виде указывать "вычисляемые атрибуты" – это такие атрибуты, значения которых вычисляются на основе значений других атрибутов (не требует пояснений). Во-вторых, по аналогии с транзитивными ФЗ, удобно указывать транзитивные атрибуты.

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

Для ТД, отражающих ФЗ, должны быть определены специальные классы (типы данных). При этом должны быть указаны колонки, принадлежащие детерминанту ФЗ и колонки, соответствующие зависимой части (ресурсам). Колонки детерминанта являются ключом ТД, следовательно, позиционирование в ТД на каком-либо значении детерминанта позволяет получить значения ресурсов ФЗ.

С другой стороны, такую ТД можно рассматривать как многомерный массив. Количество измерений ФЗ определяет размерность массива, а в ячейках массива хранятся значения ресурсов ФЗ. Отметим также, что в сгруппированной ТД колонки, по которым была произведена группировка, образуют измерения детерминанта.

Набор данных.

Введение понятия ФЗ потребует расширения синтаксиса языка V7. Логичным будет ввести такой тип данных как Набор Реквизитов (атрибутов). К данному типу принадлежат детерминант ФЗ, зависимая часть ФЗ, группировки ТД.

По сути, набор данных – это ТД из одного кортежа. Если переменная setA имеет тип данных "Абстрактный набор", то допустимы присваивания
setA = ФЗ1.Детерминант; или
setA=ФЗ1.Ресурсы.

Набор может быть также определенного типа, например:
setA=СоздатьОбъект("Регистр.СкладскойУчет.Детерминант");. В этом случае количество и типы атрибутов набора задаются детерминантом регистра "Складской учет". Значение набора может быть задано и в явном виде, например,
setA.Значение={ТекущийТовар, ТекущийСклад}.

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

Базовые ФЗ

На низшей ступени иерархии ТД, выражающих ФЗ, не накладывается никаких ограничений на тип измерений или ресурсов. Дополнительных процедур (вся функциональность обычных ТД наследуется) у данного класса немного: УстановитьРесурсы(…), ПолучитьРесурсы(…).

Форма записи данных процедур может варьироваться. Например, перед вызовом УстановитьРесурсы() можно определить устанавливаемые детерминант и ресурсы ФЗ:

фзПример.Детерминант=НаборИзмерений; 
фзПример.Ресурсы=НаборРесурсов;
фзПример.УстановитьРесурсы();

а можно передавать измерения и ресурсы в качестве параметра: фзПример.УстановитьРесурсы(НаборИзмерений, НаборРесурсов).

Использование функции ПолучитьРесурсы(…) аналогично. Детерминант ФЗ можно определить заранее, а можно передать в качестве параметра вызова.

Динамические и статические ФЗ.

Все множество типов ФЗ можно разбить на два класса: статические и динамические ФЗ. Под динамическими ФЗ мы будем понимать такие, в которых одним из измерением детерминанта является Время (t) или интервал времени (dt).

Например:
{#Сотрудник, t: Размер оклада} или
{#Контрагент, #Договор, t: Размер долга} или
{#Контрагент, #Товар, dt: Объем реализации}.

Под статическими ФЗ соответственно будут пониматься такие, в которых привязка детерминанта ко времени отсутствует. Примеров, где удобно использовать статические ФЗ, множество (обычно это какие-нибудь справочные таблицы), а в V7 соответствующего понятия, к сожалению, нет. Далее рассматриваются свойства динамических ФЗ (ДФЗ).

Для динамических ФЗ должна быть определена операция "фиксирования времени", что-то типа ИспользоватьВремяЗаписиСчитывания() (или ИспользоватьИнтервал()), после выполнения которой с ДФЗ можно работать как с обычным статическим ФЗ. Детерминант образующейся ФЗ не содержит времени – назовем такой детерминант статическим.

Приведем пример двумерной ДФЗ. Пусть некое предприятие имеет несколько территориально разнесенных подразделений. Каждое подразделение имеет право (и им пользуется) назначать свои как закупочные, так и продажные цены, предварительно согласовав их с центром. Вопрос, как вести учет всех этих прайсов?

В терминах ДФЗ все просто: {#Товар, #Подразделение: Цена покупки, Цена продажи}.

Если требуется вести прайсы в разрезе поставщиков/покупателей, к детерминанту добавим измерение "контрагент".

В терминах ДФЗ периодические реквизиты справочников являются одномерной ДФЗ, в которой измерением является ссылка на элемент справочника. Учет истории ресурсов в ДФЗ приводит к появлению понятий, связанных с регистрацией изменений состояния ФЗ. Значения ресурсов ФЗ могут меняться только в результате каких-либо событий. Проведение документа – это и есть фиксация/инициация такого события. Причем реквизиты документа всегда статичны, поскольку событие "жестко привязано" ко времени.

При проведении документа можно указать детерминант ДФЗ и соответствующие ему значения ресурсов на момент после проведения документа. Можно допустить также "ручное" событие, то есть изменение ресурсов ДФЗ интерактивно.

Событие как изменение состояния ДФЗ может иметь дополнительные характеристики. Это приводит к появлению у ДФЗ реквизитов движения. Кроме того, появление истории приводит к понятию изменение истории задним числом, что может быть критичным для каких-либо задач, использующих ресурсы ДФЗ. Таким образом, в ДФЗ должна быть предусмотрена возможность хранения последовательности записи или, в терминах V7, границ последовательностей (ГП) для всех значений детерминантов. Если последовательность записи истории была нарушена, то должен быть выставлен соответствующий флаг.

Вышесказанное означает, что физически ДФЗ разбивается на две связанных базовых ТД. В одной ведется учет изменений ресурсов, назовем ее ТД регистрации движений (или просто ТД движений). Детерминант данной ТД (помимо собственно детерминанта ДФЗ) включает в себя измерение Время (события, проведения документа), а к ресурсам ФЗ добавлены реквизиты движения (обязательные реквизиты движения – это документ и идентификатор строки ТЧ документа).

В другой ТД (назовем ее ТД хранения итогов) находятся актуальные (на текущий момент) значения ресурсов и регистрация нарушения ГП (если для ДФЗ задан учет ГП). Детерминант данной ТД является статическим, а ресурсы расширены реквизитами учета ГП.

"Векторные" ресурсы ДФЗ

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

Самым простым и распространенным векторным ресурсом является множество действительных чисел. ДФЗ с ресурсами исключительно векторного типа очень близка к понятию регистров в V7.

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

Для ДФЗ с накопительными ресурсами весьма актуальна проблема регистрации события задним числом (нарушения ГП). В предыдущем разделе указано, что в ТД хранятся конечные значения ресурсов ФЗ. Следовательно, если регистрируется событие изменения ресурса, имеющее более раннее время, чем хранящиеся в ТД итоги, то значения ресурсов всей последующей истории становятся неверными. Как известно, во избежание это проблемы в V7 введено понятие периодичности хранения итогов ресурсов, то есть одна таблица хранит итоговые значения ресурсов с заданной периодичностью, а другая – изменение данных итогов.

При необходимости получить значение ресурса на произвольный момент времени система находит ближайшие к данному моменту итоги и прибавляет к ним изменения ресурсов за интервал времени между границей хранения итогов и требуемым моментом времени. Преимущество такого подхода в том, что при изменении ресурса задним числом нет необходимости пересчитывать все промежуточные итоги ресурса, достаточно лишь пересчитать итоги на определенные границы времени. Недостаток – неудобство расчета итогов на произвольный момент, некоторая "искусственность" модели.

Мы предлагаем другой принцип работы с накопительными ресурсами. Во-первых, в ТД движений должны храниться конечные значения ресурсов. Если нарушений последовательности ввода не было, то получать итоговые значения ресурсов также просто, как периодические реквизиты справочников – они в явном виде есть в ТД движений. Во-вторых, вводится специальная ТД для учета движений (изменения ресурсов), нарушивших последовательность ввода – ТД корректировки итогов. Таким образом, при изменении состояния ресурса задним числом система выполняет следующие действия:

  • делает соответствующую запись в ТД регистрации движений;
  • изменяет итоги ресурса для заданного детерминанта в ТД хранения итогов;
  • заносит в ТД корректировки запись о том, что для заданного детерминанта, начиная с такого-то момента времени, требуется корректировка ресурсов (с регистрацией значения корректировки);
  • делает отметку в ТД итогов, что требуется пересчет итогов в ТД движений.
Что имеем в результате. Текущие значения итогов ресурсов (в ТД итогов) всегда актуальны. Если требуется получить значения итогов на произвольный момент времени, то система:
  1. находит соответствующее значение ресурса из ТД движений;
  2. проверяет ТД итогов на необходимость корректировки данного ресурса данного детерминанта;
  3. если корректировка необходима, извлекает из ТД корректировки все значения изменений ресурсов со временем более ранним, чем требуемое и складывает их со значением ресурса, полученного из ТД движений.
В итоге получаем требуемое значение. Кроме того, в фоновом режиме (автоматически или принудительно) система должна выполнять операции по очистке ТД корректировки и соответствующему изменению итоговых значений ресурсов в ТД движений.

Обороты векторных ресурсов

Во многих задачах требуется знать не конечное значение векторного ресурса, а его суммарное изменение за определенный временной интервал. Соответственно, для хранения оборотных итогов таких ресурсов в качестве "динамического" измерения должен использоваться Интервал времени. ДФЗ, в детерминанте которых присутствует Интервал времени будем называть оборотными. Фактически, оборотные ДФЗ соответствуют регистрам оборотов в V7.

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

Более гибким (и правильным) для организации оборотных ДФЗ представляется использование ТД, сгруппированных по временным интервалам. Какие интервалы участвуют в группировке – задается при создании оборотной ДФЗ. Таким образом, если указаны временные интервалы год, квартал, месяц – это означает, что ТД хранения итогов представляет собой три ТД со следующими соотношениями подчиненности:

{Детерминант, Год:…} <– {Детерминант, Квартал:…} <– {Детерминант, Месяц:…}

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

Если ресурс ДФЗ является исключительно оборотным, то не имеет смысла хранение его итоговых значений в ТД движений и нет смысла в ТД учета корректировки данного ресурса. При выполнении движения задним числом все итоги по всем группировкам временных интервалов тут же корректируются (в направлении от подчиненных группировок – к их владельцам).

Единицы измерения векторных ресурсов. Учет направления изменения ресурсов.

Если векторный ресурс подразумевает возможность его заполнения значениями, которые имеют разные единицы измерения, то для такого ресурса в ФЗ необходимо предусмотреть ведение учета единиц измерения. Наличие такого учета приблизит математическую модель ДФЗ к реальности. В реальном мире имеет смысл сложение только тех ресурсов, которые выражены в одних и тех же единицах измерения.

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

Часто при изменении векторного ресурса важно учитывать не только величину изменения, но и направление. Это означает, что в некоторых ситуациях операция "сложение с -2" далеко не то же самое, что операция "вычитания 2". Для организации учета разделения движений необходимо ТД регистрации движений разделить на две, одна из которых будет учитывать только приход, а другая – только расход. Второй возможный путь – это не делить ТД движений, а добавить в ней дополнительный реквизит движения, учитывающий направление движения. Минус данного подхода в том, что, поскольку состав детерминантов оборотных итогов прихода и расхода может быть различен (различным может быть также состав реквизитов движения на приход и расход), то в общей ТД движений некоторые ее колонки заведомо будут частично не заполнены.

Пример структуры ДФЗ.

Для иллюстрации всего выше сказанного рассмотрим пример организации ДФЗ. Пусть ДФЗ имеет один векторный ресурс, для которого необходимо учитывать как накопительные итоги, так и оборотные с разделением движений. Предположим, что детерминанты всех итогов различны, детерминант накопительных итогов имеет два измерения, а детерминанты движений – по одному. Оборотные итоги прихода и расхода ресурса требуется хранить по годам, кварталам и месяцам. Тогда структура ТД, реализующих данную ДФЗ будет примерно следующей:

Время движения Измерение 1 Измерение 2 Измерение
прихода 1
Приращение
ресурса
Конечное значение
ресурса
ИД документа ИД строчки
ТЧ документа
               

Структура ТД регистрации движений на приход

Время движения Измерение 1 Измерение 2 Измерение
расхода 1
Приращение
ресурса
Конечное значение
ресурса
ИД документа ИД строчки
ТЧ документа
               

Структура ТД регистрации движений на расход

Измерение 1 Измерение 2 Итоговое значение ресурса Учёт границы последовательности Учёт корректировки промежуточных итогов
         

Структура ТД накопительных итогов

Измерение 1 Измерение 2 Время движения Значение для корректировки
       

Структура ТД корректировки промежуточных итогов (конечных значений) ресурса

Год Изм1
Изм2
ИзмПрих1
Оботоры ресурса
     
««
Квартал Изм1
Изм2
ИзмПрих1
Оботоры ресурса
     
««
Месяц Изм1
Изм2
ИзмПрих1
Оботоры ресурса
     

Структура ТД хранения оборотов ресурса на приход

Год Изм1
Изм2
ИзмРасх1
Оботоры ресурса
     
««
Квартал Изм1
Изм2
ИзмРасх1
Оботоры ресурса
     
««
Месяц Изм1
Изм2
ИзмРасх1
Оботоры ресурса
     

Структура ТД хранения оборотов ресурса на расход

Итого получили шесть ТД, две из которых сгруппированы по интервалу. Описанные параметры ДФЗ довольно близки к понятию бухгалтерского счета. Однако при моделировании последнего необходимо, чтобы в структуре ТД нашел отражение тот факт, что приращение стоимостного остатка (ресурса) на одном бухгалтерском счете всегда означает его уменьшение на другом (баланс). То есть два движения (на приход и на расход) должны быть связаны между собой.

Резюме.

  • Понятие регистров, периодических атрибутов справочников в V7 необходимо расширить до определения Функциональных Зависимостей (ФЗ).
  • Полезным было бы определение Транзитивных Атрибутов.
  • Регистры являются частным случаем динамических ФЗ, при этом измерения образуют "статический детерминант" ФЗ, а зависимая часть ФЗ состоит из ресурсов только "векторного" типа.
  • Понятие Набор Данных облегчит использование ФЗ.
  • Учет границы последовательности динамических ФЗ должен быть встроен в структуру ТД, поддерживающих ДФЗ. Для каждого значения статического детерминанта – своя поддержка ГП.
  • Для ФЗ с накопительными ресурсами понятие "период хранения остатков" не является оптимальным решением. Лучше использовать корректировочные ТД.
  • Для организации хранения итогов оборотов ресурсов необходимо использовать подчиненные ТД с группировкой по регламентным периодам.
  • Одна динамическая ФЗ может иметь различные детерминанты для разных видов итоговых значений одного и того же ресурса.

Дмитрий Малюгин
Copyright © ITland 2002-2003

      

Комментарии

1
  • Хранитель_врат
    Гениально!
    Браво!
    Я тоже думал о чем-то подобном.
    Когда же это будет реализовано...
    В конечном итоге бухитоги, регистры сведений, остатков и итогов реализуются в рамках функциональных зависимостей.

    Кстати, как тебе такая мысль:
    { ,t : Количество, Остаток(Количество)}
    Остаток(Ресурсе) - вычислимый ресурс, вычисления производятся встроенными средствами или же по формуле = Summ'(Ресурс) WHERE (t<tтек) И (Измерения=Измерения текущие).

    Т.е. остаток будет таким же ресурсом, как и ресурс количество, только вычислимым...

    Да, все гораздо упрощается... Дожить бы до этого светлого будущего...