Проект Вектор, або ООБД своїми руками, Різне, Програмування, статті

Автор: Артур Юртайкін, королівство Delphi


1. Передумови

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

База даних, середнього за складністю проекту, вже через рік експлуатації містить в собі десятки, а то й сотні таблиць і процедур. І це не межа, з часом структура БД пухне як на дріжджах. В результаті ми маємо величезну кількість таблиць зі складною схемою взаємних зв’язків. Керувати такою махиною стає складно, особливо коли доводиться постійно вносити зміни.

З усього перерахованого напрошується очевидний висновок – потрібно уніфікація структури даних, а також якийсь механізм управління МД.


2. Властивості і час

Перш ніж рухатися далі поговоримо про час. Якщо поспостерігати за об’єктами реального світу, то стане очевидно, що їх властивості змінюються з часом. Як кажуть філософи: “Все тече, Все змінюється “. Якщо сьогодні прізвище Вашої знайомої Сидорова, то не факт що завтра вона не стане Івонова. У наш час навіть стать людини може змінитися. Змінюється все. У кожної події є відмітка на шкалі часу, а у кожного процесу часовий інтервал. З плином часу змінюється законодавство і як наслідок бізнес-логіка програми.

Вважаю, що при розробці інформаційних систем необхідно враховувати, що об’єкти і логіка можуть змінюватися в часі. По всій видимості, необхідно, вже на етапі розробки програми, передбачити можливість внесення змін, як в властивості, так і в логіку. Повинен бути якийсь механізм синхронізації значенні властивостей об’єктів і логіки додатка. Хорошим прикладом вважаю продукцію фірми 1С, де передбачена робота з “періодичними” реквізитах.

У проекті Вектор всі властивості спочатку періодичні. Це означає, що їх значення позиціонується на шкалі часу, а вся історія змін зберігається в БД.

При роботі з даними ми маємо їх стан на певний момент часу. В принципі навіть саму логіку можна зберігати в БД, при цьому буде зберігатися її історія. Але це окрема тема.


3. Авторизація

У проекті Вектор передбачено автоматичне підписування даних. Це означає, що всі зміни даних підписуються Вашим логічним ім’ям. Зроблено це для того, щоб зняти питання відповідальності. Хто зраджував дані, ось той хай і відповідає.

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

Адміністратори баз даних, безумовно, зрозуміють і оцінять таку можливість.


4. Завдання

Насправді рішення вже існує. Найбільші розробники СУБД, такі як: Cache”, GemStone, ITASCA, Objectivity /DB, ObjectStore Versant, Стали вбудовувати в свої продукти підтримку об’єктної орієнтації. Але все це досить дороге ПО

Через брак фінансів, спробуємо вирішити це завдання виходячи з наших можливостей. А маємо ми SQL сервер і якусь середовище розробки, Ваш покірний слуга віддає перевагу всьому Delphi 7.

І так приступимо. Це повинна бути якась оболонка над SQL, абстрагуюча розробника від реляційної моделі, і бере на себе все навантаження по створенню та підтримці МД.

Формулюємо вимоги до оболонки:



5. Рішення

Для вирішення завдання я обрав, популярний в середовищі MS, механізм OLE – Автоматизації. Саму оболонку, у вигляді сервера автоматизації, я називав Вектор.

Щоб відобразити об’єктно-орієнтовану концепцію на МД, необхідно передбачити такі структурні елементи, які могли б підтримувати поняття об’єктів, типів, властивостей і методів.

Реалізація методів виходить за межі даної статті, тому залишимо розгляд цієї теми на майбутнє.

Що стосується типів об’єктів, то я взяв на себе сміливість спростити це поняття до примітиву, при якому тип розглядається як властивість об’єкта! Згоден, що це занадто сміливо, але в подальшому ви побачите, що дане припущення цілком прийнятно і навіть корисно для роботи з МД.

І так подивимося, як нам зберігати об’єкти та їх властивості.

Видається очевидним, що в БД повинна бути таблиця, що зберігає масив посилань на екземпляри об’єктів. Під посиланням ми будемо розуміти унікальний ідентифікатор об’єкта – id. Для реалізації найкраще підходить автоінкрементне поле. До всього іншого хотілося б знати, хто і коли створив об’єкт, додаємо в таблицю ще два поля: Creator і Time. У підсумку отримуємо таблицю Objs, Представлену на рис. 1.



Рис. 1

Тепер розглянемо властивості об’єктів. У загальному випадку властивість може мати будь-який тип.

Що стосується базових типів то очевидно, що зберігається вони повинні окремо – кожен тип в своїй таблиці. Щоб забезпечити стандартний механізм доступу створимо зведену таблицю опису властивостей Props. Для унікальної ідентифікації властивості послужить поле автоінкрементне типу id. Назва властивості будемо зберігати в поле Name. Для опису типу властивості створимо поле Type, В якому будемо зберігати ім’я типізований таблиці. В результаті вийшла таблиця представлена ​​на рис. 2.



Рис. 2

Самі значення властивостей будемо зберігати в окремих таблицях. Таблиці ці створюються автоматично у міру потреби. При описі нового властивості, Вектор буде розміщувати його у відповідній по типу таблиці, якщо ж такої не виявиться, то буде створена нова. Для прикладу розглянемо таблицю для властивостей типу int (довге ціле). Ідентифікатор об’єкта – поле idObj, Ідентифікатор властивості – idProp, Позиція на шкалі часу – Time, Само значення – Value, Користувач створив це значення – Creator. Структура представлена ​​на рис. 3. Щоб швидко витягати значення створюємо складовою індекс: idObj, idProp, Time.



Рис. 3

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


Отже, структура даних уніфікована, залишилося реалізувати механізми: створення об’єктів, створення властивостей, роботу зі значеннями властивостей.

Тепер поговоримо про оболонці. По суті, оболонка це програмний шар переводить нас на новий рівень абстракції. Всі механізми генерації і підтримки структур інкапсульовані в сервер автоматизації – Вектор.

Інтерфейс підтримує такі методи як створення об’єкта, створення властивості, привласнення і витяг значень властивостей. Це необхідний мінімум. Також я передбачив властивість для роботи з точкою актуальності.

На SQL рівні витяг властивостей відбувається з допомогою, так званих, скалярних функцій. Насправді це звичайна збережена процедура. Відмінністю є лише те, що скалярна функція повертає єдине значення. Параметрами є: idObj, idProp, І Time. Для конкретного об’єкта повертається значення певної властивості, актуальне на заданий момент часу.

Переглянути опис інтерфейсу можна тут.

Більше про оболонці говорити нічого.

На закінчення пара зауважень:



  1. інтерфейс зроблений якомога простіше;

  2. витяг множинних даних з бази доцільно проводити за допомогою користувацьких процедур. Цікаво, що використання типізованих скалярних функцій дозволяє значно спростити побудову потрібного запиту.

Наприклад:

Потрібно витягти для всіх об’єктів їх ідентифікатори і значення для властивості найменування.

Варіант в стандартному форматі










ALTER PROCEDURE dbo.usp_Tmp
(@ta datetime = 40000)
AS SELECT dbo.Objs.id, dbo.tblStr64.Value AS Nam
FROM dbo.Objs INNER JOIN
dbo.tblInt ON dbo.Objs.id = dbo.tblInt.idObj INNER JOIN
dbo.tblStr64 ON dbo.Objs.id = dbo.tblStr64.idObj
WHERE (dbo.tblStr64.Time <= @ta) AND
(dbo.tblInt.Time <= @ta) AND
(dbo.tblInt.idProp = 5) AND
(dbo.tblStr64.idProp = 6)

А тепер подивіться як просто і витончено з використанням скалярних функцій










ALTER PROCEDURE dbo.usp_Objs
(@ta datetime = 40000)
AS SELECT id, dbo.fGetVal_Str64(id, 6, @ta) AS Nam
FROM dbo.Objs
WHERE (dbo.fGetVal_Int(id, 5, @ta) = 1)


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*