В рамках повышения технологической грамотности наших заказчиков - подготовили материал с пошаговым описанием создания модели данных по произведению А.С. Пушкина "Сказка о рыбаке и рыбке" (Золотая рыбка). Вдруг кому :)
Модель данных - ядро информационной системы
Давайте спроектируем модель данных на примере сказки (кейса) "О рыбаке и рыбке" Александра Сергеевича Пушкина
Модель данных - это система, отражающая ключевые сущности (объекты управления), их атрибуты и связи
Модель данных - логическое отражение конкретной управленческой (жизненной) ситуации (системы), которая рассматривается как совокупность объектов (сущностей) и их связей
Давайте разберем - какие ключевые сущности (объекты) мы видим?
Старик и Старуха - это люди. С точки зрения проектирования информационных систем это один объект (сущность) - человек. Однако, для наглядности визуализации и восприятия не погруженного в тему проектирования давайте создадим - два объекта
oldWoman - Старуха
oldMan - Старик
Движемся дальше. Тезис, что "Старуха своя" - толкуем таки, что Старик и Старуха сформировали ячейку общества - Family
Уже возникают интересные нюансы в проектировании и построении учетной информационной системы
Связь oldWoman - oldMan можно реализовать и без таблицы Family добавив Старику и Старухе по атрибуту (строке), содержащему ссылку на супруга spouseId и
указав взаимные связи между объектами
Такой подход с одной стороны - облегчит проектируемую систему (минус одна таблица), но с другой стороны и уменьшатся учетные возможности нашей информационной системы. Если Старик разведется со Старухой (удалится связь; сорри за спойлер), то мы потеряем данные, что они были женаты
Использование же таблицы Family (для учета семей), позволяет нам хранить в базе данных всю актуальную и архивную информацию о таком важно объекте управления, как - семья
Движемся дальше - фиксируем новые сущности (объекты)
See - море (которое "самое синие")
Land - суша, на которой живут Старик со Старухой
По сути - это два фундаментальных объекта управления в кейсе про "Золотую рыбку". Так что игнорирование данных объектов значительно снизит качество нашей будущей информационной системы
p.s. По уму See и Land это просто два разных представителя (конкретизация) такой сущности как Пространство (как Старик и Старуха - Человек), однако для простоты восприятия мы их различим
Они жили в ветхой землянке
Ровно тридцать лет и три года.
Старик ловил неводом рыбу,
Старуха пряла свою пряжу
Видим, что живут они не в чистом поле (Land), а в ветхой землянке - Building (называем так, потом что Building будет претерпевать значимые физические и информационные изменения; сорри за спойлер)
Стаж проживания в тридцать лет и три года можно отнести как к свойству Family, так и к связи Family - Building (Тонкое отличие: семье может быть 33 года, но проживали они в разных локациях). Однако не будем перегружать нашу модель в виду несущественности данной информации в нашем кейсе. Равно как и проигнорим пряжу, но не - невод
FishingTool - невод
Обратите внимание на связи:
Family связана (проживают) с Building, а Building в свою очередь находится (связано) на Land.
Ну а инвентарный номер fishingToolId логически закреплен за oldMan
Далее. От статической картинки дошли до процессов - "старик ловил"
Обратите внимание - бизнес-процесс "ловля неводом рыбы" (и его результат) пока никак не могут быть отражены в нашей модели данных. Пока у нас имеется только oldMan, fishingTool и связь между ними
Раз он в море закинул невод, —
Пришел невод с одною тиной.
Он в другой раз закинул невод,
Пришел невод с травой морскою
Заброс невода в море - транзакция
Дошли до более тонкой темы - как организовать учет процесса и его результата
FishingAct - один заброс невода в море
Обратите внимание на параметры (атрибуты) FishingAct:
id - уникальный идентификационный номер (уже случилось два FishingAct)
fisher_id - идентификационный номер рыбака (у нас рыбак один - oldMan, но в теории их может же быть много )
fishingTool_id - идентификационный номер FishingTool (у нас это - невод, но может быть и удочка и запрещенка же всякая с разными инвентарными номерами)
sea_id - идентификационный номер Sea, в котором рыбачим (предусмотрим возможность рыбалки в различных водоемах)
startTime - дата и время заброса FishingTool в Sea
endTime - дата и время извлечения FishingTool в Sea (по разнице endTime - startTime - можно вычислить продолжительность операции)
result - описание того бесполезного, что оказалось в FishingTool по результатам fishingAct (типа, трава морская и прочее)
isGoldFish - оказалась ли в FishingTool gGoldFish? (boolean)
Пока ход бизнес-процесса "ловля рыбы" и его результаты отражаются следующими данными в нашей информационной системе:
В третий раз закинул он невод, —
Пришел невод с одною рыбкой,
С непростою рыбкой, — золотою.
Как взмолится золотая рыбка!
Голосом молвит человечьим:
«Отпусти ты, старче, меня в море,
Дорогой за себя дам откуп:
Откуплюсь чем только пожелаешь.»
Удивился старик, испугался:
Он рыбачил тридцать лет и три года
И не слыхивал, чтоб рыба говорила.
Отпустил он рыбку золотую
И сказал ей ласковое слово:
«Бог с тобою, золотая рыбка!
Твоего мне откупа не надо;
Ступай себе в синее море,
Гуляй там себе на просторе».
Очевидно, что у нас возникает объект GoldFish. Но это еще не все!
Также возникает уже "невидимый" объект - обязательства GoldFish перед OldMan. И это будет отдельный объект, при чем он будет спроектирован в логике связей - "многие к многим" (Для сравнения - связь OldMan - FishingTool - "один ко многим" - у одного рыбака может быть несколько девайсов для рыбалки, но у каждого девайса будет ровно один хозяин-рыбак)
GoldFish_OldMan_commitment - таблица по учету обязательств GoldFish (могу быть разные) перед OldMan (тоже могут быть разные; отсюда и логика связи "многие-к-многим"). Таблица для учета "рыбьей дебиторки" OldMan'а
При этом пока эта таблица - пуста («Бог с тобою, золотая рыбка! Твоего мне откупа не надо; Ступай себе в синее море, Гуляй там себе на просторе»)
Обратите внимание, что мы установили связь между GoldFish и Sea (убираем риск, что oldMan может забыть к какому Sea потом идти с каждым новым Commitment; сорри - спойлер)
Также по уму напрашиваются два существенных атрибута для GoldFish_OldMan_Commitment - дата и время возникновения обязательства (дебиторки), и дата и время исполнения обязательства (погашения дебиторки), но мы опустим данные параметры для упрощения модели (к тому же - точные данные этих параметров - безвозвратно утеряны)
Также обращаем внимание, что дальше меняется структура бизнес-процессов. FishingAct более не происходит - вся дальнейшая движуха происходит на связях OldMan с OldWoman и GoldFish
Воротился старик ко старухе,
Рассказал ей великое чудо.
«Я сегодня поймал было рыбку,
Золотую рыбку, не простую;
По-нашему говорила рыбка,
Домой в море синее просилась,
Дорогою ценою откупалась:
Откупалась чем только пожелаю.
Не посмел я взять с нее выкуп;
Так пустил ее в синее море».
Старика старуха забранила:
«Дурачина ты, простофиля!
Не умел ты взять выкупа с рыбки!
Хоть бы взял ты с нее корыто,
Наше-то совсем раскололось».
Не будем плодить новую информационную сущность про "коммуникационный акт" между OldMan и OldWoman (кстати, до этого и не коммуницировали в нашей кейс) - с управленческой точки зрения для нас важен факт того, что OldWoman формулирует содержание GoldFish_OldMan_Commitment и ставит соответствующую задач OldMan
Теперь у нас в базе данных появляется следующая запись (по аналогии с FishingAct)
Вот пошел он к синему морю;
Видит, — море слегка разыгралось.
Стал он кликать золотую рыбку,
Приплыла к нему рыбка и спросила:
«Чего тебе надобно, старче?»
Ей с поклоном старик отвечает:
«Смилуйся, государыня рыбка,
Разбранила меня моя старуха,
Не дает старику мне покою:
Надобно ей новое корыто;
Наше-то совсем раскололось».
Отвечает золотая рыбка:
«Не печалься, ступай себе с богом,
Будет вам новое корыто».
Воротился старик ко старухе,
У старухи новое корыто.
Еще пуще старуха бранится:
«Дурачина ты, простофиля!
Выпросил, дурачина, корыто!
В корыте много ль корысти?
Воротись, дурачина, ты к рыбке;
Поклонись ей, выпроси уж избу».
Ускорим сказку и сразу отразим всю историю транзакций в таблице GoldFish_OldMan_commitment
isKorytoExist - true
isKorytoBroken - true
Теперь вспомним вот эту фразу:
"По сути - Sea и Land это два фундаментальных объекта управления в кейсе про "Золотую рыбку". Так что игнорирование данных объектов значительно снизит качество нашей будущей информационной системы"
В итоге у финальная модель данных кейса "Сказка о рыбаке и рыбке" сложилась следующим образом
Информация - это различие
Кант давно уже говорил, что этот кусок мела содержит миллион потенциальных фактов (Tatsachen) , но лишь очень немногие станут подлинными фактами, воздействуя на поведение сущностей, способных реагировать на факты. Вместо кантовых Tatsachen я бы употребил слово различия и заметил бы, что количество потенциальных различий в этом меле бесконечно, но очень немногие из них станут эффективными различиями (т.е. единицами информации) в умственном процессе некоторой большей сущности. Информация состоит из действенных различий.
Грегори Бейтсон, "Разум и природа. Неизбежное единство", 1979г.
Комментарии
В многосвязной матрице и достаточной её размерности для этой задачи всё отразить - не судьба?
Раскладка - просто класс.
Мне бы такую работу, где можно рабочее время на такие шедевры тратить.
Спасибо!
Дык - выходной же :)
Предложена довольно кривая структура данных, наплодили лишних сущностей (таблиц) oldman & oldWoman это просто должна быть одна таблица Actor с дополнительным полем gender, туда же и рыбку можно записать с аттрибутом Type. Для людей это будет Human, для рыбки - Fish. land & sea тоже только одна таблица - с флагом isLand - Yes/No, Family нужна только если надо отслеживать историю разводов и свадеб старика и старухи или других персонажей, а если не надо, то просто добавить поле SpouseId в таблицу Actor (Персонажи). Ну и так далее..
При этом туда можно будет и внучку и жучку добавлять, а не плодить новые таблицы типа Zhychka & youngWoman.
Согласен. Но в тексте же есть дисклеймер на эту тему (лишних таблиц :)
Задача - ликбез заказчиков на тему проектирования моделей данных (апчем они)
Двигаемся мелкими шагами - минимизируем риски срыва во фрустрацию целевой аудитории ;)
Дык автор не знает, что такое "описание бизнес-процессов". Поэтому и рисует таблицы непонятно для чего.
автор - таблица Family должна быть темпоральной. для записей должны быть поля: Дата начала/дата окончания
в варианте со сказкой - дата окончания пустая, но если в описании вы строите вариант, что может быть развод и повторная женитьба, то эти поля нужны - как вы актуальный брак рассчитаете ?
Принимается-согласен ;)
Повторная женитьба - это уже другая семья, отдельная запись.
Правильная модель предметной области это всё. За её пределами ничто.
Почему на языке "партнёров"?
Не понял вопроса
Ну видимо предполагается, что современные СУБД позволяют создавать объекты не только на языке "вероятного противника"......
Ну integer, boolean -хрен с ними. Но OldMan и OldWomen -это для разбора сказок Киплинга&Со.
Что Вы курите? Скажите, чую вещь забористая...
у вас ошибка в генерализации данных. старик и старуха - абсолютно равны по структуре данных. это один класс. так что принимая христианские нормы мы можем parent id для старика делать null a для старухи - id старика.
мало того, если сказка происходит в исламской стране, где количество жён может быть больше 1, эта модель работает без переделки. а вашу надо полностью выкидывать.
Эта модель и для посвящённого запада не работает. Вот Позитрон сразу отметил, надо в таблице Гендер прописывать. Правда поскромничал, не стал писать что он должен быть Int16, а то и Int32, что бы учесть все возможные варианты.
А может и вообще Float,
И все варианты людей сводить в
один концлагерьв одну таблицу.да. это я тоже заметил, также как избыточность моря и земли, которые всегда в единичном экземпляре. типичные константы или в крайнем случае таблица начальных установок. также как генерализация всех морских объектов в одну таблицу fishingResults к которой 1..n цепляется таблица свойств объектов, поскольку мы заранее не знаем ни объектов ни их свойств и добавлять будем по мере работы системы.
далее, у каждого хуман объекта должно быть состояние. у старика - рыбак (из заголовка сказки), у старухи - старуха, потом дворянка, потом царица и т.д. это такблица состояний.
из таблицы fishingAct убрать result, поскольку он будет определяться соотношением 1-0..n к таблице fishingResults.
далее нужна таблица встреч старика и старухи... тут много чего не так...
с другой стороны, у автора православно получается, семья - из деда и бабки.
Если всех особей в одну таблицу свести, там совершенно чудовищные варианты могут быть (дед с рыбкой, рыбка с бабкой и тд)
не факт что будет хуже. а дед хоть от этой бабки отдохнёт.
Sea
Не занимайтесь ерундой, вставайте под знамена графовых баз данных.
Нда... Назвать этот опус мастер-классом это сильно... Это из серии "смотри, дядя, как я могу" в исполнении ребенка, который уже многое в этой жизни успел познать)))
Занятно...
Столько коллег, и все не правы...
...одна я умная в белом пальто стою красивая.
ДБЛ БЛД