Чи є приклади підходів, що не стосуються CRUD?


14

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

Я часто вступаю в суперечки з колегами, коли мова йде про операції над даними. Мені не подобається U та D в CRUD. Замість того, щоб оновити запис, я вважаю за краще додати новий і мати посилання на старий запис. Таким чином ви будуєте історію змін. Мені також не подобається видалення записів, але я вважаю їх неактивними.

Чи є для цього термін? В основному лише створення та читання даних? Чи є приклади такого підходу?


1
Is there a term for this? Basically only creating and reading data?Звичайно, є: CR; P
yannis

7
З точки зору користувача, це все ще CRUD. Мені невідомі якісь конкретні мітки для цього стилю реалізації, але я думаю, що це часто зустрічається у МНОГО додатках. (Обмін стеками - хороший приклад ...)
Марк Е. Хаас

Ви можете побачити розмову під назвою Невідповідність імпедансу - наша вина .
Антон Барковський

+1 У якийсь момент хтось хоче отримати звіти, і дуже важко створювати звіти за даними, які не існують, оскільки вони "оновлювалися" поза існуванням. Я вважаю ваш підхід думкою вперед.
Чак Конвей

2
Ви також можете подивитися розмову про Datomic: infoq.com/presentations/The-Design-of-Datomic
Marjan Venema

Відповіді:


16

Позначення запису видаленим відоме як програмне видалення . Я ніколи не чув альтернативної фрази для оновлення, але, мабуть, це змусить вас видалити старий запис і створити новий.

Зазначимо, це суперечлива техніка. Дивіться посилання: Con проти Pro .


11

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

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


3
Це. Також референтна цілісність стає кошмаром; ви не можете вказати іноземний ключ для "одного запису в цій таблиці за допомогою цього не унікального ключа, який не позначений видаленим". Ви зможете подолати це, зберігаючи дані для копії запису, який збирається оновити в іншій таблиці, перш ніж оновити цю "робочу копію" новими даними, але ви все ще маєте велику кількість даних для вирішення.
KeithS

5

EventSourcing звучить як зразок, який ви можете шукати.

Візьмемо приклад, використовуючи простий об’єкт «автомобіль», за яким ми хотіли б відстежувати колір (далі йде псевдо C # код).

public class Car {
  public string Color { get; set; }
  public Car() { this.Color = "Blue"; }
}

З реалізацією CRUD, коли ми оновлюємо колір автомобіля, попередній колір втрачається.

MyCar.Color = "Red";
MyCar.Save();  // Persist the update to the database and lose the previous data

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

Якби ми переписали автомобільний клас, щоб замість цього реагувати на події при оновленні його змін, це може виглядати приблизно так:

public class Car {
    public string Color { get; private set; } // Cannot be set from outside the class

    public void ApplyEvent(CarColorChangedEvent e) {
      this.Color = e.Color;
    }
}

Тепер, як би ми оновили колір цього об’єкта? Ми могли б створити подію CarColorChanged !

var evnt = new CarColorChangedEvent("Red");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

Помічаєте відсутність економії на фактичному об'єкті моделі? Це тому, що замість того, щоб безпосередньо зберігати модель, ми наполягаємо на подіях, які ставлять модель до сучасного стану. Ці події повинні бути незмінними .

Тепер давайте швидко вперед і ще кілька разів змінимо колір:

var evnt = new CarColorChangedEvent("Green");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

var evnt = new CarColorChangedEvent("Purple");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

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

CarColorChangedEvent => Red
CarColorChangedEvent => Green
CarColorChangedEvent => Purple

Якби ми хотіли відновити цей автомобільний об’єкт, ми могли б зробити це просто, створивши новий автомобільний об’єкт і застосувавши події з нашого магазину подій до зазначеного об’єкта.

var MyCar = new Car();
var events = MyDatabase.SelectEventsForCar("CarIdentifierHere");
foreach(var e in events) {
  MyCar.ApplyEvent(e);
}
Console.WriteLine(MyCar.Color); // Purple

За допомогою потоку подій ми можемо повернути стан автомобіля до попереднього періоду часу, просто створивши новий об'єкт автомобіля і застосувати лише ті події, які ми хочемо:

var MyCar = new Car();
var event = MyDatabase.GetFirstEventForCar("CarIdentifierHere");
MyCar.ApplyEvent(e);
Console.WriteLine(MyCar.Color); // Red

5

Sourcing подій - це шлях, і вам слід поглянути на те, що Грег Янг говорить про це.

http://goodenoughsoftware.net/

Погляньте також на цю презентацію на його базі даних (Event Store). Ви також можете знайти інші відео.

http://oredev.org/2012/sesions/a-deep-look-into-the-event-store

Я не хотів би відповісти на "м'яке видалення", якщо вам спеціально не потрібно мати змогу шукати видалені елементи, але тоді ви не повинні вважати їх видаленими, а скоріше заархівованими. Я думаю, що тут термінологія є досить важливою.

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

З моделлю пошуку подій це не так. Ви завжди можете відтворити саме те, що зробив користувач. Це дуже важлива різниця між CRUD та Sourcing подій. Архітектура подій Sourcing зберігає події в сховищі подій, а не об'єкти даних або об'єкти моделі домену. Подія може легко вплинути на кілька об’єктів. Просто подумайте про рішення кошика, де ви перетворюєте кожен товар у кошику у фактичне замовлення. Одна подія впливає на всі об'єкти товару, а також на об'єкти кошика, що перетворюється на об'єкт замовлення.

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

За допомогою Sourcing подій ви можете легко перемотати назад, просто відтворюючи події до певного моменту часу. Швидкі форварди можна здійснити за допомогою знімків, але це все питання реалізації.

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

У разі налагодження, як часто ви просили користувача розповісти вам, що вони зробили ... чому б просто не повторити те, що вони зробили, а потім переглядати код! Досить вишуканий да.

Сподіваюсь, це допомагає.


2

Не точно ваш приклад, але у старих фінансових системах ви мали WORM- сховище. Якщо вам потрібно було "оновити", ви написали новий запис, і ви завжди називали останній запис як поточний, але жодні введені дані ніколи не могли бути перезаписані.

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


2

Так, це досить поширене в корпоративних системах, в основному два підходи: -

  • "двочасова", в якій кожен запис має дійсну від та дійсну до часу позначку ("поточний" запис, що має дійсну дату "назавжди" - null, "9999-12-31" або якесь таке високе значення). Записи ніколи не видаляються, натомість дата «дійсна до» встановлюється на поточний час, а в разі оновлення вставляється нова запис з дійсним з поточного часу та вічно чинним на сьогоднішній день.
  • "таблиця історії" - кожен раз, коли запис змінюється, копія старого запису скидається в таблицю історії / журналу з часовою позначкою події.

Для обох підходів є великі відмінності в деталізації. Наприклад, якщо кількість віджетів для товару замовлення змінено, чи зберігаєте ви історію для всього замовлення або лише для одного товару?

Взагалі кажучи, "двочасова" - це багато зайвої роботи, і це варто того лише, якщо у вас є багато випадків використання, наприклад "аудитор отримує статус замовлення станом на 31 грудня".



-2

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.