Функциональность отношений

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

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

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

(Автор позволил себе отклониться от общепринятых терминологических канонов, желая придать изложению чуть больше образности).

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

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

Типы отношений


Тип отношения устанавливает меру количественного взаимодействия объектов, производных от связанных отношением классов. Как известно, вариантов этой меры всего три: один-к-одному, многие-к-одному, и многие-ко-многим.

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

В полностью симметричном отношении один-к-одному (оно же — унитарное отношение), каждый из равноправных ссылочных атрибутов может выступить в качестве инициатора создания связи объектов, и быть первичным получателем значения. Деление на атрибуты прямой и обратной ссылки в таком отношении носит чисто ситуационный характер. И это при том, что один из них получит свое значение как следствие присвоение значения оппозитному атрибуту.

Понятийный смысл отношения многие-ко-многим весьма неоднозначен, что делает его предметом отдельного рассмотрения.

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

yok0uzbw8xmaowgdyfeoz0vqk5g.png


Такая нотация используется потому, что графический образ стрелки интуитивно ассоциируется как с образом вектора зависимости, так и с образом спискового атрибута обратной ссылки. Маркировка ссылочного атрибута типом и наименованием не является обязательным элементом изображения. Ссылочный атрибут типизирован оппозитным классом отношения, и, соответственно, заимствует наименование этого класса.

Ссылочный соединитель


Симметрия связи объектов обусловлена причинно-следственной зависимостью значений ссылочных атрибутов связываемых объектов. Как и всякая другая зависимость, она реализуется соединителем, который далее будем называть ссылочным соединителем. Ссылочный соединитель априори активен, что обеспечивает перманентную логическую согласованность и целостность ссылочных значений. В своей работе ссылочный соединитель использует, помимо собственно ссылочных атрибутов, также и служебные атрибутыOwn и Del. Декларация соединителя множественного отношения выглядит так:

b61vj7jwgyih0qwc3ukikpc0vfe.png

Служебный атрибут Own типизирован собственным классом, и в объекте класса хранит собственный идентификатор этого объекта (IDO). Именно этот атрибут используется всеми типами отношений в качестве источника значения, передаваемого соединителем отношения однотипному с ним атрибуту обратной ссылки.

Служебный атрибут Del используется соединителем отношения в качестве lock-контекста. При логическом удалении объекта класса A, его атрибут Del будет инициализирован, что породит вызов метода Unset в адрес базового сокета соединителя, что в свою очередь приведет к вызову в адрес атрибута B.{A} метода Set с «пустым» значением и ключом, и в результате соответствующая запись будет изъята из списка обратных ссылок B.{A}.

В качестве атрибута Key (key-контекст соединителя) по умолчанию выступает базовый атрибут класса. Значение этого атрибута используется соединителем как ключ, в пару к передаваемому значению — IDO атрибута Own. Получающий эту пару атрибут обратной ссылки B.{A} обладает простым функционалом списка, который непосредственно и формирует сам список обратных ссылок.

Ну, а собственно атрибут прямой ссылки A.[B] является всего лишь ref-контекстом, который предоставляет соединителю идентификатор IDO целевого объекта. Когда в процессе реализации ссылки атрибут A.[B] получит хранимое значение, то он вызывает в адрес базового сокета соединителя метод Reset, что в свою очередь приведет к вызову в адрес атрибута B.{A} метода Set с IDO объекта и ключом, и в результате в список обратных ссылок B.{A} будет добавлена новая запись. Далее, любое последующее изменение значений атрибутов Key и прямой ссылки A.[B] будет сопровождаться последовательными вызовами Unset и Reset с соответствующими изменениями в списке (ах) обратных ссылок.

В унитарном отношении очевидным образом не используется key-контекст, но зато присутствуют два ссылочных соединителя, которыми обеспечивается зеркальная симметрия реализации:

f3hyexrn9hzwl5cvrslbdemksra.png

При пристальном взгляде на представленную декларацию может показаться, что имеются все предпосылки для зацикливания процесса присвоения ссылочного значения, но это не так. Метод Set не порождает производные рекурсивные вызовы, если значение, полученное им извне, эквивалентно уже имеющемуся в наличии.

Создание отношения


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

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

Мощность отношения


Рассмотрим такую операцию, как передача Товара со Склада на Склад: в объекте Передаточная накладная необходимо адресовать сразу два объекта Склад. Реализуется такая потребность простым увеличением мощности отношения, с заменой атомарной формы хранения производных значений ссылочного атрибута A.[B] на перечислимую (массив).

zw5hqv3f9wd6lqrxq-_aqss7erg.png

Увеличивая мощность множественного отношения (кратность ссылки), конструктор модели создаст у атрибута прямой ссылки дополнительный элемент, и к нему еще один соединитель отношения, аналогичный уже существующему, который использует новый элемент в качестве источника адресного указателя (ref-контекст). Обратим внимание — увеличение мощности не повлияло на декларации атрибута обратной ссылки B.{A}, за исключением добавления еще одного входящего сокета. (На этом и последующих рисунках показаны только необходимые по смыслу контексты).

Аналогичным образом реализуется увеличение мощности унитарного отношения.

i87bqeovccysohdjjxh9imuy2gk.png

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

В свою очередь, атрибут обратной ссылки множественного отношения может обеспечить существование более чем одного списка. По умолчанию, первый (основной) список использует в качестве ключа базовый атрибут класса (для Накладной это будет атрибут Date). Предположим, что для каких либо целей требуется еще один список с другим порядком сортировки, например, по сумме накладной Total. Создавая декларацию нового списка, конструктор отношения создаст у атрибута обратной ссылки дополнительный элемент (A2), а также дополнительный ссылочный соединитель. Новый соединитель аналогичен первичному, но в качестве источника ключа использует уже не Date, а атрибут Total.

ybqlbhi9htd7sfbhjzhezyckbsa.png

Обратим внимание и подчеркнем: добавление нового списка не изменяет мощности отношения.

Если в свойствах списка указать дополнительный логический контекст, то в него попадут только те записи, для которых значением контекста будет true. Такая опция будет полезна например, при ведении «бело-серой» бухгалтерии. А так как все три контекста базового ссылочного соединителя уже использованы, то можно воспользоваться свободным lock-контекстом одного из контекстных сокетов. Например, так:

urcrju20qxjts4jwkh-02iwxlmq.png


Как видим, в отличие от ref — и key — контекстов, lock-контекст можно наращивать каскадно, создавая дополнительный логический контекст (условие) для уже существующего.

Управление ссылочной целостностью


Представляется очевидным, что объект, на который ссылаются, не может быть произвольным образом удален. Соответственно, в целях сохранения ссылочной целостности необходим контроль наличия актуальных внешних ссылок на объект.

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

bnk2slwcyh2eoywjhd209scx5ve.png

В методе Set специализированный служебный функционал атрибута Del проверяет все входящие соединители, и как только один из них вернет true (список обратных ссылок не пуст), функционал породит исключение, прерывающее транзакцию. Но до исключения можно и не доводить. Метод Get, адресованный атрибуту Del, опросит соединители, и вернет false, если удаление объекта возможно без конфликтов.

Существуют отношения, которые с понятийной точки зрения принято рассматривать как »родительские». Например, Накладная и ее условно »дочерние» Записи, которые могут существовать исключительно в контексте Накладной. Тут ожидается прямо противоположное поведение: объект Накладная не только может быть удален при наличии обратных ссылок от объектов Запись, но и должен также, в процессе собственного удаления, удалить все свои Записи. Требуемая реакция может быть обеспечена установкой виртуального флага Owner в свойствах отношения, после которой в модели данных будут сделаны следующие изменения:

cce9hdca02cfrkg69quobeldffu.png


Во-первых, будет добавлен активный соединитель, связывающий атрибуты Del в классах Накладная и Запись, а во-вторых, сбросом флага Get будет де-активирован соединитель, связывающий Del с соответствующим списком обратных ссылок.

Взаимная зависимость отношений


Рассмотрим систему из трех классов, связанных множественным отношением:

liiyzvnerwjbuivzi_1sfzzowuc.png


Объект класса C обладает прямыми указателями на объекты B и A, объект В — указателем на А. Так как никаких дополнительных правил и ограничений нет, то связанные взаимной ссылкой объекты C и B в самом общем случае могут непротиворечиво адресовать в том числе и разные объекты класса А.

Слегка изменим пример, внеся в него определенную смысловую нагрузку.

Пусть C — это класс Студент, B — Факультет, A — ВУЗ. Представляется очевидным, что Студент числится исключительно в том учебном заведении, на Факультете которого проходит специализированное обучение. Иными словами, для Студента указатель на ВУЗ определяется через указатель на Факультет. Это правило устанавливается созданием соединителя, связывающего атрибуты прямой ссылки на класс A в классах B и C через отношение CB. Обратим внимание, связываемые атрибуты имеют одинаковый тип — класс A.

2saii2-npjaxvsosptdzidfbhiw.png


Декларация активной связи ссылочных атрибутов стандартным соединителем автоматически обеспечит требуемую согласованность ссылочных значений C.[A] = B.[A] при любых внешних воздействиях. В самом деле:

  • при любом получении/изменении значения C.[B] соединитель будет инициирован (методами Unset/Reset) для передачи значения атрибута B.[A] в атрибут C.[A];
  • при изменении значения атрибута B.[A], новое значение будет передано всем объектам C из списка обратных ссылок B.{C};


Декларация активной зависимости атрибутов прямой ссылки C.[A] = B.[A] порождает прямое логическое следствие:

  • при наличии у объекта C актуального значения С.[A] (например, Студент уже выбрал ВУЗ для обучения), областью определения допустимых значений атрибута C.[B] будет список обратных ссылок атрибута A.{B} (список Факультетов данного ВУЗа). Это следствие в первом своем приближении принимает форму ограничения, которое в модели данных выражается явным образом — автоматическим созданием соединителя C.[B] = A.{B}, далее именуемым back-соединителем, производного от декларации direct-соединителя C.[A] = B.[A].


bq_pan6icgl43wtmzb11vxtdlxq.png


Производный back-соединитель абсолютно пассивен, он не инициируется изменением атрибута C.[A], так как соответствующие флаги (Unset/Reset) контекстного сокета выключены, и в процессе отработки внешних воздействий он участия не принимает. Этот соединитель используется в процессе организации присвоения значения ссылочному атрибуту C.[A], что будет детально рассмотрено позже. А пока обратим внимание, что адресуемый back-соединителем список обратных ссылок, если его рассматривать как источник данных, предоставляет множество однородных значений, без возможности автоматически выбрать из них единственное.

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

Группировка по значению


Рассмотрим пример из все тех же трех классов, но, для большей наглядности, в несколько иной интерпретации: класс A — это некоторый Журнал, Записи которого (класс C) следует группировать по календарным Дням (класс B). Каждый День в Журнале уникален по значению календарной даты Date (D). Данную уникальность обеспечивает назначенный атрибуту обратной ссылки A.{B} слегка модернизированный функционал списка, который генерирует транзакционное исключение при попытке добавить в список запись с уже существующим в списке значением ключа.

Соединитель back также претерпел некоторые изменения: он использует в качестве key-контекста атрибут Date (D), и стал полу-активным: его контексты активны (для всех контекстных сокетов соединителя установлены флаги Unset/Reset), при сброшенном флаге Set базового сокета.

lnqflwrikn4s40hhcxglizrjcs4.png


При активных контекстных сокетах, любое изменение значений атрибутов C.[A] или C.D активирует back-соединитель, который извлечет значение C.D, и использует его как ключ при обращении к списку A.{B}, после чего полученное значение (IDO объекта B) будет присвоено целевому атрибуту. Тем самым реализуется автоматическое позиционирование (иначе — группировка) объектов класса C на объекты класса B.

А что произойдет, если в качестве значения C.D ввести дату, для которой не существует соответствующего объекта День? В этом случае back-соединитель закономерно вернет значение NUL, и ссылка на День будет де-инициализирована.

Стоит отметить, что изредка требуется и такое поведение, но чаще всего требуемый объект День, соответствующий введенной дате, должен быть создан автоматически. Для реализации такого поведения атрибуту C.[B] назначают функционал Autoset. Этот функционал (рассматривается ниже) при его инициации back-соединителем автоматически создаст новый объект класса B, после чего присвоит атрибуту прямой ссылки в качестве значения идентификатор созданного объекта.

Но этого недостаточно. Для сохранения ссылочной целостности, атрибуты D и {A} нового объекта B должны автоматически получить строго определенные значения, а именно — совпадающие с текущими значениями аналогичных атрибутов объекта C. Для этих целей в соединителях B.D→C.D и B.[A]→C.[A] включается реверс передачи значения, а именно: во входящих Get-сокетах соединителя, принадлежащих атрибутам C.D и C.[A], дополнительно устанавливается флаг Set. Тогда при присвоении значения атрибуту C.[B], — транспортному контексту соединителей B.D→C.D и B.[A]→C.[A], эти соединители будут инициированы на передачу значений в объект B. Обратим внимание — приведенная на схеме декларация зависимостей обеспечивает автоматическое сохранение логической и ссылочной целостности при изменении любого из значений.

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

Группировка по ссылкам


Слегка модернизируем предыдущий пример: пусть место абсолютного атрибута D в классах A и С займет атрибут прямой ссылки на класс D (списку обратных ссылок в общем-то едино, что будет играть роль ключа к значению: календарная дата или идентификатор объекта IDO). И для большей наглядности изменим смысловое значение классов: класс A — это Товар, класс D — Склад, класс С — Запись счета/накладной (движение Товара). Тогда смысловая нагрузка на класс B становится однозначно производной: это Товар-на-Складе. Если заменить Склад на Поставщика или Покупателя, то класс B станет Товаром-у-Поставщика/Покупателя.

Соответствующая сделанным изменениям декларация будет выглядеть так:

zwhyyphcjijcpph7422jna7ahgg.png


Любая Запись при получении конкретных указателей на объекты Склад и Товар автоматически получит указатель на объект Товар-на-Складе, а в случае отсутствия такового — автоматически же его создаст. Обратим внимание: связь двух классов, Товар и Склад, через третий класс (Товар-на-Складе) представляет собой вариант реализации отношения многие-ко-многим, альтернативный прямому обмену значениями двух атрибутов обратной ссылки. Причем этот вариант обладает еще и свойством уникальности. Иными словами, для каждой пары объектов Товар и Склад, связывающий их объект Товар-на-Складе существует в единственном экземпляре. Такое поведение обусловлено свойством уникальности списка обратных ссылок, для которого в качестве источника ключа используется атрибут-указатель на оппозитный класс. И совершенно неважно, в каком из двух классов (Товар или Склад) декларирована уникальность списка, — такой же список обратных ссылок (с обычным функционалом списка) в оппозитном классе будет по факту содержать уникальный набор ключей.

Отношение многие-ко-многим


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

Совсем иное дело, когда отношение через третий класс обладает свойством уникальности, как Товар-на-Складе из примера выше. Здесь спецификой третьего класса (класса связи) является не столько использование атрибутов отношения в качестве источников ключа, сколько его понятийная «производность» от отношения классов. Поэтому, такая уникальная (по идентификаторам) связь классов через третий класс и будет в дальнейшем рассматриваться в качестве отношения типа многие-ко-многим. Именовать же такой тип можно как уникальным отношением, так и отношением-проекцией.

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

_dngxokgk6oj5y_5xtqpiv-j4yu.png


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

Корреспонденция


Увеличивая кратность отношения мы тем самым позволяем объекту одного класса адресовать два и более объекта другого класса, что в свою очередь также может рассматриваться как логический аналог рассмотренной ранее связи многие-ко-многим.

cnx7imexivedqe88w9ewdhuye8i.png


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

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

znxqypca7lxx9sujm1otr-kxpga.png


При всей странности ее внешнего вида, это логичная и вполне себе работоспособная декларация, которая практически используется, например, в бухгалтерском учете — для получения объектов взаимной корреспонденции балансовых счетов. Собственно говоря, отсюда и заимствовано название — корреспонденция, используемое далее для обозначения кратного уникального отношения, реализуемого классом-проекцией.

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

Реализация отношения


Существует ровно один способ реализовать отношение в объекте класса — присвоить методом Set атрибуту прямой ссылки идентификатор целевого объекта IDO. Причем соответствующий вызов может быть инициирован как извне, так и самой моделью данных. Например, атрибут может получить указатель на объект из другого класса через соединитель, связывающий однотипные ссылочные атрибуты. Также, отношение можно реализовать непосредственно при создании объекта, если метод Create адресовать не целевому классу, а типизированному этим классом атрибуту отношения, причем атрибуту как прямой, так и обратной ссылки. Таким способом удобно создавать новый объект относительно другого объекта (например, новую Запись относительно Накладной). Также атрибут может получить IDO, создавая целевой объект отношения функционалом Autoset.

Внешний пользователь не может просто так взять и присвоить атрибуту ссылочное значение. Печальные последствия открытия прямого доступа к системе внутренней идентификации очевидны и так, без комментариев. К тому же, за пределами пространства объектов отдельный дескриптор IDO что называется «теряет смысл», превращаясь в простое число.

Поэтому, внешний пользователь может реализовать ссылку только опосредованно, в форме диалога, путем выбора элемента из списка, в котором каждый объект представлен своими абсолютными (не ссылочными) значениями. Требуемый список ему предоставляют компоненты слоя Data-курсоров (серверная часть интерфейсных ресурсов объектной СУБД будет рассмотрена впоследствии), которые затем и инициируют присвоение IDO в соответствии со сделанным выбором. Диалог выбора может быть прямым или каскадным, что задается на основе действующих back-соединителей. Источником для формирования диалогового списка выступает соответствующий список обратных ссылок.

Функционал Autoset


Данный функционал назначают атрибуту прямой ссылки в целях реализации отношения путем автоматического создания производного объекта целевого класса отношения.

Функционал Autoset может быть инициирован как входящим соединителем, так и внешним событием Update. При этом целевой объект отношения будет создан функционалом только в том случае, если ссылочный атрибут в исходном объекте не имеет хранимого значения.

Воспроизводство множества


Существует твердое правило логического взаимодействия значений, согласно которому значение, принадлежащее определенному домену, можно связать только со значением, домен которого входит в исходный или включает в себя исходный. При этом принять исходное значение может только значение с равным или более обширным доменом. Самый большой домен (после Undefined Type) у атрибута типа Logical, который может принять значение любого другого типа. Проще говоря, соединителем можно связать только однотипные атрибуты, что и наблюдалось во всех рассматриваемых ранее примерах. Но вот в следующей декларации пассивный соединитель, связывая атрибуты обратной ссылки (A.{B} → C.{D}) очевидно разного типа, явным образом нарушает это правило, и тем не менее имеет полное право на жизнь.

tsbvdi4gxkguh0enipw33jcqpy8.png


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

Статический атрибут, производное значение которого не инициализировано, при обращении к нему с запросом, тем не менее способен вернуть значение, сформировав его из входящих соединений, при их наличии. При этом, само хранимое значение атрибут все равно не создаст, так как запрос не содержит явного указания на принадлежность к транзакции, а значит база данных должна сохранить свое состояние неизменным. Иное дело, когда транзакционный характер воздействия очевиден. В этом случае не инициализированный ранее статический атрибут вполне может и должен в рамках общего изменения состояния базы образовать хранимое значение. Как видно из декларации, рассматриваемый соединитель и его целевой атрибут C.{D} будут инициированы при присвоении значения атрибуту C.[A], то есть транзакционно. И если производного значения в этот момент не существует, атрибут C.{D} начинает его формирование по исходному образцу, предоставленному соединителем.

Как значение, список обратных ссылок производен от ссылок прямых. Иными словами, у атрибута C.{D} есть единственный способ сформировать собственный список размером с исходный, — это создать требуемое количество объектов класса D, и присвоить каждому из созданных объектов указатель на собственный объект. Такое создание с присвоением можно сделать одной командой Create в собственный адрес. Что атрибут (а если уж быть совсем точным — то функционал списка, назначенный атрибуту) и делает — для каждого элемента исходного списка. А так как значением этого элемента является ссылочный указатель, тип которого известен, то анализом кортежа класса создаваемого объекта определяется атрибут прямой ссылки требуемого типа, которому и присваивается извлеченное из элемента значение указателя.

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

Внутренние отношения


Для связывания однотипных объектов (объектов одного класса) используется отношение, создаваемое непосредственно внутри класса данных. При этом способ реализации собственно отношения остается неизменным — в классе создается два ссылочных атрибута, связанных ссылочными соединителями, и типизированных собственным классом.

Что примечательно, рассмотренную в предыдущем параграфе корреспонденцию также можно отнести, пусть и частично, к внутренним отношениям, так как связывает она объекты, производные от одного класса. Правда делает это через объекты стороннего класса.

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

Через внутреннее отношение атрибут может создать соединитель на самого себя. Это очень эффективный прием, позволяющий реализовать различного рода обобщения значений, включая обобщение «нарастающим итогом».

Функциональный смысл внутреннего отношения определяется его типом.

Цепочечное отношение


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

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

Примеры использования — прохождение дет

© Habrahabr.ru