Ci sono esempi di approcci non CRUD?

14

Sono un programmatore ma ho anche lavorato come archivista. Come archivista, si tratta di conservare i dati.

Spesso parlo di argomenti con i colleghi quando si tratta di operazioni sui dati. Non mi piacciono troppo le U e le D in CRUD. Piuttosto che aggiornare un record, preferisco aggiungerne uno nuovo e avere un riferimento al vecchio record. In questo modo costruisci una storia di cambiamenti. Inoltre, non mi piace eliminare i record, ma contrassegnarli come inattivi.

C'è un termine per questo? Fondamentalmente solo la creazione e la lettura dei dati? Ci sono esempi di questo approccio?

    
posta Pieter B 16.11.2012 - 18:57
fonte

8 risposte

16

Contrassegnare un record come eliminato è noto come eliminazione graduale . Non ho mai sentito una frase alternativa per l'aggiornamento, ma suppongo che ciò ti causi la possibilità di eliminare il vecchio record e crearne uno nuovo.

Va notato, questa è una tecnica controversa. Vedi i link: Con vs Pro .

    
risposta data 16.11.2012 - 19:02
fonte
11

Uno dei problemi con il mantenimento di una cronologia delle modifiche è che ingombra il database e può aumentare notevolmente le sue dimensioni (in base ai modelli di utilizzo). Quindi una buona idea sarebbe quella di archiviare la pista di controllo in un posto separato e mantenere le tabelle delle applicazioni effettive popolate solo con dati rilevanti. Pertanto, ogni volta che un'applicazione CRUD viene eseguita dall'applicazione, la modifica viene registrata nelle tabelle di controllo e l'operazione CRUD viene eseguita sulle tabelle dell'applicazione (nessuna eliminazione soft).

Mantenendo separato il percorso di controllo si ottiene un archivio dati incontaminato con cui interagire l'applicazione, pur conservando la cronologia delle modifiche qualora fosse necessario. Ora puoi anche archiviare separatamente la pista di controllo o addirittura distruggerla, in base ai tuoi requisiti aziendali.

    
risposta data 16.11.2012 - 19:59
fonte
5

EventSourcing suona come lo schema che stai cercando.

Facciamo un esempio usando un semplice oggetto "auto" che vorremmo tenere traccia del colore di (segue il codice pseudo C #).

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

Con un'implementazione CRUD quando aggiorniamo il colore dell'auto, il colore precedente andrebbe perso.

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

Questa perdita di informazioni mi sembra la cosa che vorresti evitare di più (da qui l'antipatia per l'aggiornamento e l'eliminazione di parte del pattern CRUD).

Se dovessimo riscrivere la classe dell'auto per rispondere agli eventi durante l'aggiornamento delle modifiche, potrebbe apparire come segue:

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;
    }
}

Ora come aggiorneremmo il colore di questo oggetto? Potremmo creare un evento CarColorChanged !

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

Si noti la mancanza di un salvataggio sull'oggetto modello attuale? Questo perché, invece di persistere direttamente sul modello, persistono gli eventi che portano il modello allo stato corrente. Questi eventi dovrebbero essere immutable .

Ora spostiamoci in avanti e cambiamo il colore qualche altra volta:

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

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

Se dovessimo esaminare la nostra memoria degli eventi (potrebbe essere un database relazionale, basato su file, ecc.) vedremmo una serie di eventi relativi al nostro oggetto auto:

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

Se volessimo ricostruire quell'oggetto auto, potremmo farlo semplicemente creando un nuovo oggetto auto e applicando gli eventi dal nostro storestore a detto oggetto.

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

Con il flusso di eventi possiamo riportare lo stato della macchina a un periodo di tempo precedente semplicemente creando un nuovo oggetto auto e applicando solo gli eventi che vogliamo:

var MyCar = new Car();
var event = MyDatabase.GetFirstEventForCar("CarIdentifierHere");
MyCar.ApplyEvent(e);
Console.WriteLine(MyCar.Color); // Red
    
risposta data 16.11.2012 - 23:17
fonte
5

Event Sourcing è la strada da percorrere, e dovresti dare un'occhiata a ciò che Greg Young ha da dire al riguardo.

link

Dai anche un'occhiata a questa presentazione sul suo Database (Event Store). Puoi trovare anche altri video.

link

Non sceglierei la risposta "soft-delete" a meno che tu non abbia la necessità di cercare gli elementi eliminati, ma non dovresti pensarli come eliminati ma piuttosto archiviati. Penso che la terminologia sia abbastanza importante qui.

Non vorrei neanche mantenere una "tabella delle versioni". Tutte le "tabelle delle versioni" che ho mai visto (tra cui quella su Sto cercando di ripulire al momento - 7 anni di dati danneggiati a causa di bug ... e non c'è modo di riaverlo anche se abbiamo storico i dati ... perché è altrettanto corrotto) finiscono corrotti a causa di bug nel codice e alla fine perdi ancora i dati perché non puoi mai tornare indietro e ricreare i dati danneggiati dalla corruzione.

Con il modello di sourcing degli eventi questo non è il caso. Puoi sempre replicare esattamente ciò che l'utente ha fatto. Questa è la differenza molto importante tra CRUD ed Event Sourcing. L'architettura Event Sourcing salva gli eventi in un archivio eventi e non oggetti dati o oggetti modello dominio. Un evento potrebbe facilmente influire su più oggetti. Basti pensare a una soluzione del carrello della spesa in cui si converte ogni articolo nel carrello della spesa in un ordine effettivo. Un evento influisce su tutti gli oggetti dell'oggetto e sugli oggetti del carrello degli acquisti, che viene trasformato in un oggetto ordine.

Se tenevi una copia con versione di ogni riga in ogni tabella nel database, immagina l'orrore di dover riavvolgere un timestamp specifico, per non parlare della quantità folle di spazio e di overhead delle prestazioni nel mantenere quella tabella delle versioni.

Con Event Sourcing, puoi facilmente riavvolgere, semplicemente ripetendo gli eventi fino a un certo punto nel tempo. I forward veloci possono essere implementati usando le istantanee, ma è tutta una questione di implementazione.

Ma il vero vantaggio che penso ti piacerà, visto che sei particolarmente interessato a non perdere dati, è che se scopri un bug nel codice che salva questi dati, allora non devi tornare indietro e pulire i dati (che è spesso impossibile perché i dati non sono quasi mai completi). Invece basta correggere il bug e rivedere tutti gli eventi. Allora avrai un database con dati corretti e corretti.

In caso di debug, quante volte hai chiesto all'utente di dirti cosa hanno fatto ... perché non solo riprodurre ciò che hanno fatto e quindi passare il codice! Abbastanza carino eh.

Spero che questo aiuti.

    
risposta data 17.11.2012 - 00:39
fonte
2

Non proprio il tuo esempio, ma nei vecchi sistemi finanziari hai avuto WORM storage. Se avevi bisogno di "aggiornare" hai scritto un nuovo record e hai sempre fatto riferimento all'ultimo record come corrente ma nessun dato impegnato potrebbe mai essere sovrascritto.

Molte persone hanno portato questa idea nei sistemi successivi. Ho sentito ciò che descrivi indicato come tabelle WORM, ma solo in quelle cerchie.

    
risposta data 16.11.2012 - 20:36
fonte
2

Sì, è piuttosto comune nei sistemi aziendali. Ci sono fondamentalmente due approcci: -

  • "bi-temporale" in cui ogni record ha un timbro valido e valido per il timestamp (il record "corrente" con una data valida di "per sempre" - null, "9999-12-31" o alcuni di questi valori alti valore). I record non vengono mai eliminati, ma la data "valido a" è impostata sull'ora corrente e, nel caso di un aggiornamento, viene inserito un nuovo record con un valore valido dall'ora corrente e un valore sempre valido fino alla data.
  • "tabella cronologia": ogni volta che viene modificato un record, una copia del vecchio record viene scaricata in una tabella cronologia / registro con un timestamp per l'evento.

Esistono grandi variazioni nella granularità per entrambi gli approcci. per esempio. Se la quantità di widget su un articolo dell'ordine viene modificata, mantieni la cronologia per l'intero ordine o solo per quell'elemento?

In generale, "bi-temporale" è un lavoro extra e ne vale la pena se si hanno molti casi d'uso come "l'auditor ottiene lo stato degli ordini al 31 dicembre".

    
risposta data 15.08.2014 - 04:18
fonte
1

Puoi usare "soft-delete" come suggerito da pdr . Per quanto riguarda gli aggiornamenti, è possibile conservare la cronologia dei record, una specie di risposta alla mia risposta qui: link dove l'OP voleva essere in grado di tenere traccia di tutte le versioni di determinati tipi di dati.

    
risposta data 16.11.2012 - 19:37
fonte
-2

fondamentalmente il greggio non può essere completato senza queste 4 cose. Crude significa Crea, Leggi, Aggiorna ed elimina così quando stai solo provando a leggere i dati puoi usare una semplice query, ma tutte e tre queste cose sono collegate a uno e ad altri concetti semplici di database

    
risposta data 17.11.2012 - 07:39
fonte

Leggi altre domande sui tag