Создание CMS • Модель данных. Основы
Система управления содержимым (CMS) обязана предоставить гибкие всеохватывающие функциональные возможности для управления содержимым сайта, облегчить работу администратора-конфигуратора и способствовать созданию удобного в использовании сайта. Содержимым сайта можно назвать новости, размещенные на нём, а также статьи, комментарии, фотографии. Содержимым также являются целые структуры информации: новостные ленты, каталоги, форумы, блоги. Обобщенно: содержимое – это данные, размещенные на сайте.
CMS может просто передавать данные по запросу клиентскому приложению, например сетевой программе, flash-клипу или AJAX-приложению. Но чаще всего, CMS предоставляет клиенту уже подготовленные для отображения данные в HTML формате. В этом случаи, для обеспечения доступности, легкости восприятия и удобства пользования содержимым, выполняется стилизация и объединение его с элементами оформления (темы, шаблоны), навигации (меню, ссылки) и управления (формы и ссылки тоже), и всем этим тоже нужно управлять.
Идея
Окружающий мир воспринимается нами объектным, мы мыслим «объектами», в наших умах выстраивается объектная модель мира. Поэтому нам не составит труда создать объектную модель содержимого сайта и управлять ею. Новости, товар в каталоге, сообщения на форуме и сами форумы, и все другое можно представить в виде объектов. Устанавливая связи между объектами, можно создавать структуры данных любой сложности, от добавления комментариев к статьям до создания социальных сетей и более.
Объекты, классы и связи данных – это информация, которую нужно уметь создавать, хранить, использовать, изменять и удалять. В нашем распоряжении реляционная база данных для хранения информации. Действия же совершаемые с информацией – часть логики функционирования CMS, которая в большей части будет реализована модулем данных Data.
Фактически модуль данных будет осуществлять объектно-реляционную проекцию (ORM) – предоставлять объектно-ориентрованный доступ к базе данных. При этом сущности объектной модели (классы, связи, объекты) будут определяться в базе данных, а не программно, что позволит, не программируя, создавать новые классы данных – новые типы содержимого.
Чтобы не путаться с объектами и классами языка программирования, применяются термины «объект данных» и «класс данных»
Для хранения однотипных объектов в реляционной базе данных в принципе достаточно одной таблицы, поля которой будут соответствовать атрибутам объекта. Но объекты могут иметь связи на другие объекты и чаще только их и имеют. Вместо того, чтобы в таблице объектов создавать поля (внешние ключи) для связи с другими объектами, лучше создать отдельную таблицу для связей – это, кстати, позволит хранить дополнительные сведения о связях, в частности, именование и их тип. Связь образует свойство у объекта, владеющего связью. Свойством называется совокупность связи и объекта, на который установлена связь.
Атрибуты и свойства объектов определяются классом. Фактически же атрибуты определяются таблицей – её полями. Определение свойств у объектов можно реализовать наличием связей между соответствующими классами. Сами классы тоже нужно хранить, поэтому для них тоже нужно создать таблицу. По имени класса будет определяться таблица с его объектами.
Каждая сущность (класс, объект и связь) должна иметь идентификатор – уникальное целое число, уникальное среди всех сущностей. То есть не должно быть, например, класса и объекта с одинаковым идентификатором. Уникальность идентификатора среди разнотипных сущностей позволяет, в частности, хранить связи классов в таблице вместе со связями объектов. Термин «сущность» подразумевает и объект, и класс, и связь.
Одно из основных понятий объектной модели – наследование классов. Наследование тоже нужно представить в реляционном виде и это достаточно легко сделать, определив целочисленное поле в таблице классов для хранения идентификатора наследуемого класса (внешний ключ), и оперировать этой информацией для слияния соответствующих таблиц объектов при запросах. Если класс «B» наследует класс «A», то атрибуты объектов класса «B» будут храниться в таблице «А» и «Б».
Классы являются объектами! Пока без объяснений. Так как класс – это объект, а у любого объекта имеется класс, значит и у класса есть класс, определяющий атрибуты для него, в частности имя и идентификатор наследуемого класса. Связи тоже являются объектами, соответственно и они имеют свой класс. Таким образом, всё является объектами, но чтобы не путаться с назначениями разнотипных объектов, в целях обобщения будет применяться термин «сущность».
Реализация
Итак, исходя из всего изложенного, каждая сущность обладает идентификатором и классом, точнее связью на класс. Приступим к реализации и для всех сущностей создадим таблицу с названием «id». В таблице два поля – идентификатор сущности и идентификатор класса сущности. Мы создали (пока ещё не полностью) базовый класс «сущность» – все остальные классы обязаны будут наследовать класс «сущность» иначе смысла в их создании не будет.
CREATE TABLE `id` ( `id` int(10) unsigned NOT NULL auto_increment, `class` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `index_class` (`class`) );
Создаем второй класс с названием «class». Пока создание класса сводится к созданию таблицы. Создаем таблицу с именем «class» и полями «id», «sys_name», «extend», «final». Поле «id» используется для связи «один к одному» с таблицей сущностей, поле «id» используется логикой системы для слияния записей при реализации наследования. «sys_name» – это системное имя класса, совпадающее с именем таблицы, в которой будут храниться объекты соответствующего класса. «extend» – идентификатор наследуемого класса. «final» – признак возможности наследования класса (если 0).
CREATE TABLE class ( `id` int(10) unsigned NOT NULL, `sys_name` VARCHAR(255) NOT NULL, `extend` int(10) unsigned NOT NULL default '1', `final` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`id`), UNIQUE `index_sys_name` (`sys_name`) );
Сейчас понять картину взаимосвязей будет непросто – это как случай с курицей и яйцом, типа, что было первым? В данном случае даже ошибочно рассказывать появление двух сущностей (классов) последовательно, так как они должны появиться одновременно и не могут существовать друг без друга.
Созданы две таблицы – как бы созданы два класса, но именно как бы, так таблицы пусты – сущностей нет. Первая сущность – это базовый класс «id» называемый «сущность». От того, что сущность эта является классом, ассоциируемая с ней запись должна быть как в таблице «id» так и в таблице «class». Идентификатор первой сущности равен 1. Обратите внимание на системное имя класса – оно совпадает с именем таблицы «id». Вторая сущность тоже является классом, поэтому запись тоже и в таблице «id» и в таблице «class». Системное имя второго класса «class» совпадает с именем таблицы созданной для классов. Второй класс наследует первый – это определено в поле «extend». Второй класс запрещено наследовать.

Теперь обратим внимание на поле «class» в первой созданной таблице. Обе сущности определяются классом с идентификатором 2. Да, именно так! Первая сущность определяется классом 2, поэтому она является классом, у неё определены все атрибуты характерные классам. Вторая сущность, тоже является классом и наследует первый класс, поэтому объекты класса 2 имеют идентификатор и связь на класс. Проанализируйте взаимосвязи, посмотрите, как все лаконично само себя определяет – и таблицы и атрибуты и то, что обе сущности являются классами.
Создадим теперь класс для связей. Класс-связь определяет атрибуты специфичные для связей:
- «sys_name» – системное имя связи;
- «define» – идентификатор связи, определяющей данную связь;
- «kind» – признак вида связи: «использовать» или «состоять»;
- «size» – признак мощности связи: «много» или «один»;
- «is_define» – признак, что связь определяет связь между объектами;
- «is_mandat» – признак, что связь обязательно должна быть у объекта;
- «primary» – идентификатор сущности владельца связи;
- «secondary» – идентификатор сущности, с которым выполняется связь.
CREATE TABLE `link` ( `id` int(10) unsigned NOT NULL, `define` int(10) unsigned NOT NULL default '0', `sys_name` varchar(255) NOT NULL, `kind` tinyint(1) unsigned NOT NULL default '0', `size` tinyint(1) unsigned NOT NULL default '1', `is_mandat` tinyint(1) unsigned NOT NULL default '1', `is_define` tinyint(1) unsigned NOT NULL default '1', `primary` int(10) unsigned NOT NULL, `secondary` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `index_define` (`define`), KEY `index_sys_name` (`sys_name`), KEY `index_primary` (`primary`), KEY `index_secondary` (`secondary`) );
Связи имеют двойное назначение, используемое логикой модуля Data. Первое назначение – непосредственная связь между объектами для реализации свойств, второе назначение – определение этих свойств классом. Класс, установкой связи с другим классом, определяет свойства для своих объектов. Но если рассматривать класс как объект, то он тоже может иметь свойства. Значит простым наличием связи между классами нельзя определить, что эта связь описывает свойство у объектов. Поэтому у связи имеются атрибуты «define» и «is_define». По атрибуту «define» можно найти связь между классами, определяющею данную связь. Атрибут «is_define» является признаком, принимающим значение 0, если это обычная связь между объектами и 1, если эта связь описывает свойство и применяется классом.
Связи бывают двух видов: «использовать» (агрегация, ассоциация) или «состоять» (композиция, быть частью). Вид определяется атрибутом «kind». Объекты, связанные с другим объектом связью вида «состоять» и являющиеся подчиненными, будут зависеть от объекта-владельца связи. Зависимость сводится к тому, что удаляя главный объект, будут автоматически удаляться все подчиненные объекты связанные связью вида «состоять». Есть другие особенности, например объект не может «быть частью» более чем для одного объекта.
Связи второго вида – вида «использовать» сохраняют независимость связанным объектам. Без ограничений и последствий может быть независимо удален как объект владелец свойства, так и объект являющийся свойством. Объект может «использоваться» любым количеством объектов.
Если бы не были бы оптимизированы связи объекта с классом и связь наследования у классов, то в общем счете было бы четыре вида связи. Вдобавок к описанным были бы связи вида «являться» и «наследует».
Следующий важный атрибут связи – «size» (мощность), принимающий значение «много» или «один». Например, у статьи может быть несколько комментариев, что будет определяться множественным свойством. Этот атрибут используется связью класса, описывающей свойства для объектов. На самом деле статья будет иметь ровно столько связей, сколько комментариев должно быть с ней связано, но эти связи будут иметь одинаковые значения атрибутов, отличие только в идентификаторе и объекте (комментарии), с которым выполняется связывание. Ниже в таблице приведены примеры свойств объекта статьи (в скобках указана мощность связей). Атрибуты, кроме идентификатора, у статьи отсутствуют.
Статья:
| состоит | использует |
|---|---|
|
заголовок (1); дата создания (1); текст (1). |
категория (1); автор (1); комментарий (Много); файл (Много); фотография (Много); |
Атрибут «is_mandat» тоже используется связью класса, определяющей свойства у объектов, и является признаком, что свойство обязательно должно существовать у объекта, если значение атрибута не равно 0 (логическое значение).
Атрибуты «primary» и «secondary» осуществляют уже непосредственную связь между сущностями по их идентификаторам – являются внешними ключами для связывания таблиц объектов. Само связывание выполняется логикой модуля Data.

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

Логика модуля данных Data различает только эти три типа сущностей и предоставляет базовые действия: создание новых сущностей, их загрузку из БД, а также изменение и удаление. Каждый объект может иметь атрибуты и свойства в зависимости от своего класса. Классы наделяются возможностью определять свойства и атрибуты для объектов и возможностью наследоваться. Связи реализуют непосредственные ссылочные связи между объектами в программном смысле.
Что дальше
Впереди ещё как минимум две части на тему «модель данных». В следующей статье речь пойдет о самом модуле данных Data и будет продемонстрирован процесс создания содержимого сайта с помощью него.
Продолжение на днях!
Обсуждение темы перенесено на форум: Проектирование->Объектная модель данных
> Так как класс – это объект, а у любого объекта имеется класс, значит и у класса есть класс, определяющий атрибуты для него, в частности имя и идентификатор наследуемого класса. Связи тоже являются объектами, соответственно и они имеют свой класс. Таким образом, всё является объектами, но чтобы не путаться с назначениями разнотипных объектов, в целях обобщения будет применяться термин «сущность».
хорошая трава
interface Object{
$id;
}
class Class implements Object;
class Relation extends Class;
class Entity extends Class;
class Meta
{
$entity = new Entity;
$relation = new Relation;
}
это я такое придумывал. отказался от реализации. выгода не оправдывает затрат.
как у вас?
Окружающий мир воспринимается нами объектным, мы мыслим «объектами», в наших умах выстраивается объектная модель мира.
Не факт…
У меня только Object
и нет жесткой связи на класс, у объекта его атрибуты и связи на другие объекты, одной из которой является связь на класс
direqtor, тут, конечно, не поспоришь, мне неизвестно какими метаданными вы оперируете… Я постараюсь в 4 части этой статьи расписать теоретическую часть объектной модели… От неё, правда, голова закружится
))
слушай, тёзка, ты же видишь мой емейл? стукнись по юзернейму в скайп, где-нить в субботу побеседуем, глядишь, и польза будет
м?
ждем-с 4ю часть
со скайпом проблема — микрофона нет)) а в аське всегда пожалуйста — это ко всем относится. 209504733
Мертвая идея.
Увидите через полгода…
«не программируя, создавать новые классы данных – новые типы содержимого» — а оно надо? Типов-то обычно надо: integer, float, string, datetime, blob.
Чего вы выдумываете, какие типы?
Потом вы запаритесь с производительностью,
выяснится, что проще писать нативный SQL.
Эти грабли народ уже проходил.
Не, ну если вы готовите системку для посещаемости один запрос в минуту — то да, можно поэкспериментировать…
Почему бы не?
)) В сегодняшнее время, когда вопрос звучит: производительность или гибкость, большинство выбирает гибкость. Мощности серверов постоянно растут, а гибкость тебе никто просто так не даст для рабочего сайта. Дешевле купить сервер помощнее, чем лопатить систему для нового сайта в тех же фреймворках, и этому подтверждение популярность систем типа друпала.
И не так уж плохо выходит с производительностью, подумаешь на 10 запросов больше сделаешь))
В Эльдорадо микрофон стоит 99 рублей.
Здравствуйте.
Как Вы различаете связь объекта с классом (т.е. то что А относится к классу Б), и связь объекта со значением свойства (А.свойство = Б).
Предположим, А — это «Иванов», свойство — это «пол»,
Б — значение свойства «пол» для «Иванова» и равно «мужской».
И это было зависимое значение, которое стиралось бы вместе с Ивановым.
А потом то, что было «мужской» вдруг стало классом, и теперь определяет какие-то чисто мужские свойства Иванова. Это как-то решается?
Извините, если ответ уже есть в Ваших статьях, мог и не заметить. Спасибо.
По идеи, изменив связь с классом — установив её на сущность «class», объект должен превратится в класс, но система (модуль Data) не позволит изменить связь с классом у существующего объекта, поэтому Б не сможет вдруг стать классом.
В базе данных, связь с классом осуществляется по внешнему ключу в таблице «id», информации об этой связи нет в таблице «lik». Программно связь различается по имени — свойство с именем ‘class’ у объекта — это связь на класс. По классу определяется, какие атрибуты и свойства должны быть у объекта и от куда (как) их загружать/сохранять/удалять. Всё просто))
Ясно, что класс определяет свойства объекта.
)
Но дело в том, что действительно гибкая система должна учитывать это волшебное превращение значения атрибута в класс. История очень распространенная для гибкого подхода.
Сотрудник А работает в отделе Б. Отдел — это значение атрибута. До поры, до времени. Но вдруг в информационной системе становится важным учитывать, что у сотрудников отдела Б есть свойство «уровень допуска». В других отделах такого быть не должно. Ясно, что можно сделать специальный класс для сотрудников отдела Б, который определит для них связь с классом «уровень допуска». Но правильно ли это? Как в этом случае описать связь конкретного отдела и нового класса.
Конечно, Вы можете хранить связи объекта с классом и с атрибутом по-разному, в разных табличках. Но нужен механизм превращения значения в класс.
Имхо
Я вас понимаю следующим образом: есть класс сотрудников, есть класс отделов, есть сами сотрудники и отделы – объекты. Каждый сотрудник имеет связь с конкретным отделом. Существует некий отдел «Б». Со временем, появляется необходимость, чтобы все сотрудники отдела «Б» имели уровень доступа.
Замечу, я поспешил, сказав, что объект не может сменить связь на свой класс – есть одна тонкость. В реальности, человек классифицирует (группирует) объекты по общим свойствам, получается – не класс порождает объекты, а объекты образуют классы. И вот, к примеру, я появляюсь на неком предприятии, где есть отделы и сотрудники, поначалу мне известно только то, что каждый сотрудник относится к конкретному отделу – это информация в моей голове. Но через какое-то время директор объясняет мне, что у сотрудников отдела Б есть уровень доступа. Что происходит с моей информационной базой?)) Я среди всех сотрудников выделяю особых, принадлежащих к отделу «Б» и имеющих уровень доступа, т.е. создаю новый класс «особые сотрудники» например. Этот класс наследуется от «сотрудники». Фактически я сменил класс у некоторых объектов-сотрудников, но без нарушения общего смысла. То есть возможность изменить класс у объектов на наследуемый логически верна и имеет право на существование.
В новом классе появляется свойство на уровень доступа. Остается вопрос с отделом, ведь «особые сотрудники» должны принадлежать обязательно к отделу «Б»!! Первое решение – не заморачиваться по этому поводу и не вводить условие принадлежности именно к отелу «Б», все равно свойство уровня доступа будет применяться только, если сотрудник принадлежит к этому отделу. Второе решение появилось благодаря вашему вопросу, спасибо вам.
Мы должны сохранить само свойство (связь) на отдел у особых сотрудников, иначе будет нарушен принцип наследования, то есть мы не можем создать новое свойство на отделы, но можем переопределить его. И вот решение, которое легко реализуется в текущей объектной модели. Класс определяет свойство у объектов наличием связью с другим классом. При этом в самой связи, её атрибутом «is_define» устанавливается, что она используется для определения свойств у объектов – объекты должны будут иметь связи на объекты класса, с которым связана эта связь. Класс в этом случаи применяется как ограничение, как группа объектов, из которых можно выбирать с кем связаться объекту. А что, если определяющая связь в классе будет устанавливаться не на класс, а на объект, как бы сужая группу до одного объекта! Таким образом, мы можем переопределить свойство отдел в классе «особые сотрудники» связав её вместо класса «отдел» с объектом отдел «Б». При этом свойство отдела у особых сотрудников остаётся принадлежать к классу «отдел» не смотря на то, что мы сузили его определение.
Надеюсь, понятно изложил)) Стучитесь в аську 209504733
Да, именно об этом писал Дейт в своём 3-м манифесте: наследование может выражаться не только в расширении свойств класса, но и в сужении их области определения. Так класс «сотрудник» получается из «человека» добавлением свойств «отдел», «зарплата» и проч., а класс подросток — ограничением значения свойства «возраст» (которое есть и у «человека») до <=16.
На счет возраста нужно подумать. По идеи, возраст — это число, пусть даже оно будет объектом, но у каждого человека будет свое значение от 0
до скажем 150
. Как определить классом ограничение <=16? Есть идеи?
В ситуации с отделом вы ограничивали значения свойства, скажем так, по id. Ограничения свойства по значению — это немного другая история, сильно завязанная на то, как система работает с элементарными форматами — числами, строками, датами и т.д. В любом случае имеем:
Класс Человек. Класс Возраст. Свойство Человек-Возраст.
Класс Подросток, наследует Человека, вместе с возрастом.
Нужна связь класса Подросток и свойства Человек-Возраст — это некоторая специальная связь-объект, которая говорит о том, что наследуемое свойство будет слегка переопределено. И свойством уже этой связи д.б. ограничение <=16.
Как это реализовать в табличках — вопрос десятый, но, думается, такого рода штуки сильно расширят возможности системы.
Замечу ещё, что ограничения по значению всё-равно не загонишь под одну гребёнку: у Дейта же говорилось о классическом наследнике прямоугольника со свойствами А(ширина) и Б(высота), которые равны друг другу, т.е. о квадрате. Это видимо всё-таки не декларация, а, увы, код. Но место для него вполне можно предусмотреть в системе
Забегаем вперед)) В статье «архитектура CMS» на схеме отображен модуль Formats. Принцип его функционирования ещё не полностью продуман, но суть примерно следующая…
В модели данных существуют классы для представления скалярных значений – строк и чисел. В статье Модель данных Часть 2 показано, как они созданы и как они применяются, например, у объекта новость свойство заголовок – это объект класса string. Но вот вопрос, правильно ли использовать класс string для представления e-mail адреса, номера телефона и других строковых значений, накладывающих ограничения (условия) на свой формат? Можно наследовать класс string и создать для каждого варианта строкового представления (если не ошибаюсь, такие уточненные типы называют доменами) свой класс. Но правильно ли это?? Создать то создадим, а кто проверять значения будет и нужно ли создавать гору классов?
Представьте коробку, коробка ваша – грубо говоря, между вами и коробкой существует связь. В коробку можно положить все что угодно, но вы используете её только для хранения в ней, допустим, дисков исполнителей в рок-стиле. Вы об этом знаете само собой и перед тем как в коробку что-то положить вы проверяете соответствие, что это диск с музыкой в рок-стиле.
В нашем случае диск – это скалярное значение, ради примера, а коробка это объект с атрибутом value. хоть это и смешно:)) А условие на то, что можно положить в коробку определяется связью между вами и коробкой. Просто так вам это условие не нужно и коробке как-то безразлично, что в неё положат, поэтому условие в связи. Получается, у связи на коробку есть свойство – связь на объект условия. Да, у связи есть свойства, в предложенной объектной модели уже сказано, что связи тоже являются объектами. Что такое объект условия? Фактически это условие на значение, записанное в виде php кода. Как все это можно использовать?
Когда модуль данных, точнее в объекте класса Object (о нем в статье Модель данных Часть 2) происходит присвоение значений свойству или атрибуту, генерируется событие – это событие в частности обрабатывается модулем Formats, который исходя из оперируемых объектов обращается к свойству format у связи (если это свойство есть) и проверяет условие, находящееся в нем. Результатом обработки события может быть измененное (отфильтрованное) значение, либо признак – продолжать или завершить присвоение значение в объекте данных. Это ещё спорное решение, но уже реализующее уточнение значения без создания нового класса.
Теоретически, класс (объект) может тоже иметь связь на условие, которым можно будет проверять не сами значения атрибутов объекта, а выполнять их сравнение. Например, для класса квадрат создать условие равенства ширены и высоты. Обрабатываться условие будет точно также модулем formats, просто модуль нужно будет научить различать условия у связи и условие у класса. Таким образом, мы все-таки можем создать новые классы, наследуя их от string, добавляя условия на их атрибуты.
Вообще тема хоть и сложноватая, но интересна.
хранение дезориентированного циклического графа http://www.sql.ru/forum/actualthread.aspx?tid=635337
ориентированного ациклического графа http://www.gotdotnet.ru/LearnDotNet/Misc/448064.aspx
когда-нибудь возникнет необходимость остановиться с определениями типов («классов») объектов. и надо будет ввести аксиоматичные (элементарные) типы.
другой вариант: аксиоматичный тип у нас уже есть: class Object
применяя правильно его к задаче про «сотрудников отдела Б» получим что, как только СОБ получает спецдопуск, объект ОБ получает свойство «необходимость спецдопуска», объект СОБ получает ещё один класс «спецдопуск», так? это множественное наследование, нереализованное в пхп
Не пойму, как представить у отдела свойство «необходимость спецдопуска» для его сотрудников? С другой стороны я действительно не усмотрел, что остальные сотрудники уже не могут оказаться в отделе «Б» — только особые с уровнем доступа.
Спецдопуски и отделы мне мешают думать, давайте вернёмся к половому вопросу
Пусть в честь завтрашнего праздника есть у нас класс «прекрасная дама». Человек Петрова является также прекрасной дамой. У человека «размера груди» нет, а у дамы есть. Отнеся Петрову, которая безусловно остаётся человеком, к дамам, мы получаем возможность оперировать с размером её груди. Предлагаю подумать об этом 
Пол, который был как-бы свойством человека, превращает человека каждым своим значением в представителя ещё какого класса и определяет новые свойства для объекта. Это не наследование, это кое-что поинтереснее.
Почему же не наследование? Создаем класс «прекрасная дама» от «человек» при этом добавляем свойство «грудь» и уточняем или сужаем значение пола до «женский» — так как вариант пола сужен до одного, он уже может автоматически устанавливаться при создании объектов. Как реализовать сужение уже рассмотрено.
Уж извините, сотрудники с отделами полней демонстрируют зависимости))
Связь между сотрудником и отделом имеет вид «использовать» и этой связью владеет сотрудник, то есть отделу вообще безразлично, кто в нем работает и есть ли грудь и права доступа у его сотрудников))
Мы все-таки можем другого сотрудника без уровня доступа связать с отделом «Б», просто сотрудник не будет иметь доступ к нему. Это наверно как подарить автомобиль
), но забыть вручить ключи.
ну да, если только сотрудники отдела Б могут иметь спецдопуск, но могут и не иметь его, то связь получается неадекватная. и наследование другое.
ОБ наследует отдел со связью к сотрудникам. но именно принадлежность к ОБ добавляет сотруднику св-во спецдопуск (и даже не свойство, а связь с объектом класса спецдопуск). упс, у нас новый класс СОБ
Думаю, что изобретать даже ничего не надо, только малость дополнить программной логики. Ранее я показал, как сузить определение свойства у класса, связав его определяющую связь в классе с объектом отдела «Б». Лучше пойти другим более верным способом.
Нужно создать класс, например «особый отдел» и потом объект отдел «Б» сменить на этот класс. В определении класса «особые сотрудники» создавать определение свойства не на отдел «Б», а на класс «особый отдел». Во-первых, это позволит создавать новые отделы, требующие спец. допуска. Во-вторых, у нас само собой образуется уточнение для отделов, что их сотрудники должны иметь спец. допуск!!!
Объясняю как.
Достаточно только определяющие связи между классами обрабатывать взаимно, например связь между классом «сотрудники» и «отделы» говорит, что сотрудники относятся к отделам, но в тоже время говорит и то, что отделы имеют сотрудников.
Определив класс «особые сотрудники» со спец допуском и класс «особые отделы» и переопределив связь в классе «особые сотрудники» установив её вместо с отделами — с «особыми отелами» мы тем самым уточнили не только то, что особые сотрудники должны относится к особым отделам (у нас только отдел «Б» особый пока) но и то, что особые отделы могут иметь только особых сотрудников со спец. допуском.
Да, вообщем можно и так. Я скажу, как это решено у меня.
1. Имеем множественное наследование, классы называю группами, чтобы не путать с тем, что в коде. (Кстати тоже PHP. Когда-то был Pascal)
2. Связи такие:
А входит в группу Сотрудники.
А через свойство «Отдел» работает в отделе Б.
Связь А и Б трактуется одновременно как вхождение в группу, если вдруг Б — это группа. Это физически одна стрелочка.
Вхождение в группу Б даёт А свойство для определения секретного допуска.
С формальной точки зрения, отдел С, которому может быть новых свойств объявлять и не нужно, тоже становится группой. Но при отсутствии определения специфического поведения для входящих в него объектов — это не важно.
А вообще, очень приятно видеть собрата по размышлению над стрелочками. Удачи Вам. Кстати, я тоже Владимир
Спасибо, мне тоже очень приятно видеть понимающих тему людей и создающих отличные комментарии! А то большинство только вякает, что наблюдалось на сайте habrahabr.ru
Предлагаю что-нибудь ещё рассмотреть
Зато я узнал о Вашей работе на Хабре
Причины «вяканья» вполне понятны: почти каждый думающий разработчик пробовал создавать гибкую систему. И почти все приходят к похожим решениям: информация — это граф, всё вокруг объекты — и связи, и классы, и всё тотально связано.
Кто-то тонет в своих велосипедах (любимая тема на Хабре!) и возвращается к привычным методам работы; кто-то уходит в смежный лагерь семантики — RDF, онтологии, SPARQL, или к объектно-каким-нибудь БД, где уже есть промышленные решения многих мучающих нас с Вами вопросов. Большинство же с удовольствием пользуется результатами новаторов, нынешний очевидный мейнстрим — ORM. (Кстати для меня ORM — это другое: Object Role Modeling, http://orm.net — посмотрите, если не видели.)
То, что кучи LEFT JOIN’ов на основе хитро закрученных метаданных тормознее, чем написать всё на ассемблере, это понятно. Но ведь и правда надо быть в хорошем смысле фанатиком, чтобы довести подобное дело хоть до какого-то конца. Я уверен, что этот подход победит уже лет через пять, но путь в семантическое счастливое будущее реально непростой. Поэтому: удачи Вам ещё раз, а я — в отпуск, и когда вернусь — с удовольствием продолжу диалог.
Этот коммент на главную сайта
BUG DETECTED!
существует некая разница между статикой и динамикой.
> Нужно создать класс, например «особый отдел» и потом объект отдел «Б» сменить на этот класс. etc…
это путь статики. если у нас нет ещё записей ни про отдел, ни про сотрудников. мы можем сочинять конструкции наследования, вводить отделы и «особые классы»
если у нас уже имеются записи о сотрудниках и отделах, мы не можем сменить их базовую (классовую, в местных терминах) принадлежность.
в конечном итоге, любой наш путь сильно напоминает pattern Decorator имхо. самая мегадинамичная фича для изменения поведения объекта. может, и другие есть; знающий, да поправит.
т.к. мы не можем изменить классы ОБ и СОБ, мы их декорируем спецпринадлежностями. я не зря писал про множественное наследование и графы в БД. именно это и получаем. кажется о_О
зы: немного спорной теории: в реализации к декораторам относят фильтры (filter(obj->A1) >>> obj->A2) — изменяют объект «снаружи», врапперы (new Wrapper(typeA1||typeA2)) — собирают классы разного поведения под однотипный интерфес, и собственно декораторы (objA1->decorate(Decorator) >>> objA2) изменяют объект «изнутри»
зы2: ОРМ был очевидным мейнстримом года 3-4 назад, когда писалось большинство цмс, известных сейчас. сейчас в моде всё тот же активрекорд, но какой-то вычурный, вот как здесь, например %)
Мы же не программируем классы, в нашей объектной модели классы и объекты — это данные, а их поведение реализуется независимо логикой системы. Изменить класс у объекта нам не составляет труда — всего-то нужно сменить связь на него… Конечно, менять на произвольный класс нельзя, но можно сменить на наследуемый от текущего — никаких нарушений не возникнет.
Декоратор применяется в поведении объектов, он же и придуман, чтоб, не меняя программный код методов, добавлять новых функций и часто примером является визуализация объектов/компонентов.
Кстати, у меня изначально была мысль, чтобы объектам можно было добавлять новые свойства (связи на другие объекты) не зависимо от его класса. Но это создавала препятствия для других действий с объектной моделью, в частности, то же изменение класса на новый из цепочки наследования текущего. Поэтому я не стал её пока реализовать, тем более это требовала дополнительного кода.
Вообще-то про декорирование стоит подумать, как о добавлении новых свойств объекту не зависимо от его класса…
..Нужно что ли вводить понятие интерфейса в нашу объектную модель?? Вообще-то интерфейс получится подобием класса, наверно тогда нужно просто добавить новый вид связи с классом. Сейчас есть связи с классом вида «являться» (class) и «наследовать» (extend) — добавить третью «реализует» (interface).. назвать можно по другому для понятности чтоб)) .
!!! С другой стороны — нафиг этот интерфейс, если в итоге просто получается множественное наследование)) в классах данных же нет реализации методов, методов вообще нету) В нашей модели класс и интерфейс фактически одно и тоже.
Что-то меня понесло)) просто множественное наследование не интересно, интересней, когда объект будет иметь возможность определяться несколькими классами!! Вот ужас)) Фактически — это просто понимается как вхождение объекта одновременно в несколько групп. Класс — группирует объекты. Первая проблемка с множественным определением уже видна — не должно быть совпадений имен атрибутов и свойств у классов, определяющих один объект, появятся, наверно, и семантические проблемки/вопросы. И все же множественное определение выглядит естественным))
> объект будет иметь возможность определяться несколькими классами
собственно, это поведение (в силу своей начитанности) я и называю множественным наследованием
«проблема» с совпадением имён аттрибутов решается достаточно просто, по классической схеме: следующий класс переопределяет одноимённые аттрибуты предыдущего
а если всё заменить на ИДшники, то нам и имён их знать не надо %)
Понятно. Но мы в принципе задачу с сотрудниками решили и без множественного наследования.
P.S. Заходите на форум, создавайте темы, задавайте любые вопросы по проекту… надеюсь, получится интересная дискуссия
Обсуждение темы перенесено на форум: Проектирование->Объектная модель данных
Пользователь lucky, для вас создана учетная запись на форуме, пароль выслан по почте, на адрес указанный вами в комментариях (luc…@jetstyle…) Ваши сообщения теперь на форуме.
Перенос на форум вызван большим объемом комментариев (не только их количеством).