Інформаційні системи повинні основуватися на фактах

Про що більшість розробників (включно з архітекторами) зазвичай забувають, то це про те, що інформаційні системи мають базуватися на фактах, тобто незмінних подіях минулого. Інформація – це інсайди, висновки, інтерпретації з сукупності фактів, якими володіє інформаційна система.

Замість розробки структури даних(фактів), більшість розробників одразу переходять до створення сутностей (втілень патерну Entity з DDD, або чогось подібного), що мають стан, але не мають історії (множини пов’язаних із ними фактів). В таких системах неможливо рефлексувати, тобто повторно використовувати факти для отримання нових інсайдів і висновків, а також досить складно (іноді неможливо) відмінити деякі помилкові зміни та повернути систему до нормального стану.

У цій публікації я розкажу як необхідно підходити до дрозробки дійсно ефективної та гнучкої інформаційної системи. Такий підхід відмінно підходить для розробки будь-яких систем, щоправда, він є надлишковим для розробки PoC (proof of concept) та прототипів, які не мають використовуватися у т.з. “продакшені”, а покликані лише продемонструвати що має вийти та залучити інвестиції для подальшої розробки повноцінного рішення.

Робота з фактами

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

Ми досить вільні у тому, що саме можна вважати окремим фактом. Наприклад, публікація у блозі має окрім власне змісту публікації багато мета-атрибутів, як то категорія, теги, meta-keywords, meta-description, автора публікації і таке інше. Якщо нас не хвилюють деталі, то ми можемо зберігати усі ці значення як одну одиницю даних (datum), як один факт.

Якщо предметна область така, що нас хвилюють зміни у змісті публікації (наприклад, ми хочемо мати можливість версіонування), то ми можемо використовувати два окремі факти: власне публікацію (наприклад, як деякий унікальний ідентифікатор, типу елементу URI – slug) та окремо її зміст. Коли ми редагуємо публікацію, то створюємо новий факт про її зміст і за замовчуванням відображаємо останній факт про зміст публікації. Ця сама логіка поширюється і на інші атрибути публікації.

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

Створення сутностей

Геракліт колись давно сказав, що не можна двічі увійти до однієї річки. Мені доводилося принаймні двічі входити до Саксагані, Інгульця, Дніпра, Росі та Тхорівки. Геракліт мав на увазі те, що річка тече й змінюється і кожного наступного моменту вона інша, аніж була. Проте, ми продовжуємо сприймати змінену річку як ту саму. Гераклітова річка – це факт про положення усіх молекую матерії, що річку формує, а річка у розумінні обивателя – це те, що ми називаємо сутністю, те, що існує протягом якогось часу, змінюється, але продовжує суб’єктивно для спостерігача залишатися тим самим.

У публікації в блозі може змінюватися назва, зміст, автор, категорія, але допоки це має сенс для спостерігача, публікація залишається тією самою публікацією. У такому випадку можна стверджувати, що сутність публікації існує лише у голові спостерігача. Але, не будемо опускатися до повної шизофренії. Люди мають вельми схожі гештальти сприйняття і тому сутність ми можемо представити як факт про її існування (появу) без жодних інших атрибутів. Таким чином факт про існування сутності – це штучно створений унікальний ідентифікатор або деякий атрибут, який, ми впевнені, ніколи не зміниться, або зміна якого руйнує сутність та створює нову (новий факт існування/появи чогось іншого). Останні два варіанти принято називати “натуральним первинним ключем” у реляційній теорії/реляційних базах данних.

Усі пов’язані із сутністю факти, мають містити посилання на ідентифікатор сутності, безпосередньо у собі, або через інші факти – відношення. Наприклад, існування певної людини – це факт, існування конкретного будинку – це також факт. Залежно від предметної області ми можемо вважати людину і будинок сутностями. Те, що будинок належить людині, чи що людина володіє будинком не є сутнісними властивостями, ані будинку, ані людини. Те, що будинок належить певній людині, або що певна людина володіє будинком – це окремий факт.

Якщо людина позбавляєть права власності на об’єкт нерухомості, то ми не зобов’язані видалити відповідний факт відношення (хоча можемо зробити і так, все залежить від предметної області та того, які інсайди/висновки/інформацію ми бажаємо отримувати від бази даних). Ми можемо створити новий факт-відношення між тим самим будинком та іншою людиною, а потім запитати у бази даних останнього власника будинка, аби отримати інформацію по актуальному власнику.

Обмежені контексти (bounded contexts)

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

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

Сутності User із різних контекстів можуть використовувати одні і ті самі типи фактів (що найменше, факт про створення/існування сутності, тобто запис про її унікальний ідентифікатор), оскільки у сумісному використанні незмінних данних немає ніяких проблем.

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

P.S.

Якщо щось Вам здалось незрозумілим – це нормально. Не соромтесь та задавайте питання у коментарях. Також, я збираюсь в одній з наступних публікацій розробити простий додаток на Golang аби продемонструвати підхід, що був описаний у цій публікації.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *