Ci sono esempi di approcci non CRUD?


14

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

Mi capita spesso di litigare con i colleghi quando si tratta di operazioni sui dati. Non mi piacciono troppo la U e la D in CRUD. Invece di 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 piuttosto contrassegnarli come inattivi.

C'è un termine per questo? Fondamentalmente solo creando e leggendo dati? Ci sono esempi di questo approccio?


1
Is there a term for this? Basically only creating and reading data?Certo che c'è: CR; P
yannis

7
Dal punto di vista dell'utente, questo è ancora CRUD. Non sono a conoscenza di etichette specifiche per quello stile di implementazione, ma penso che sia comune in MOLTE applicazioni. (Stack Exchange è un buon esempio ...)
Mark E. Haase,

Potresti voler guardare un discorso chiamato The Impedance Mismatch is Our Fault .
Anton Barkovsky,

+1 Ad un certo punto, qualcuno vorrà rapporti ed è molto difficile creare rapporti su dati che non esistono perché sono stati "aggiornati" dall'esistenza. Trovo il tuo approccio molto lungimirante.
Chuck Conway,

2
Potresti anche voler guardare un discorso su Datomic: infoq.com/presentations/The-Design-of-Datomic
Marjan Venema

Risposte:


16

Contrassegnare un record come eliminato è noto come eliminazione temporanea . Non ho mai sentito una frase alternativa per l'aggiornamento, ma immagino che ciò causi la cancellazione soft del vecchio record e la creazione di uno nuovo.

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


11

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

Mantenendo la traccia di controllo separata, si ottiene un archivio di dati incontaminato con cui l'applicazione può interagire, pur conservando la cronologia delle modifiche in caso di necessità. Ora puoi anche archiviare la pista di controllo separatamente o addirittura distruggerla, a seconda delle esigenze aziendali.


3
Questo. Inoltre, l'integrità referenziale diventa un incubo; non è possibile specificare una chiave esterna per "l'unico record in questa tabella con questa chiave non univoca che non è contrassegnata come eliminata". Per ovviare a ciò, persistendo i dati per la copia di un record che sta per essere aggiornato in una tabella diversa, prima di aggiornare questa "copia di lavoro" con i nuovi dati, ma hai ancora enormi quantità di dati da gestire.
KeithS

5

EventSourcing sembra il modello che potresti cercare.

Facciamo un esempio usando un semplice oggetto "auto" di cui vorremmo tenere traccia del colore (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 ciò che vorresti evitare di più (da qui la antipatia per l'aggiornamento e l'eliminazione di parte del modello CRUD).

Se dovessimo riscrivere la classe dell'auto per rispondere invece agli eventi durante l'aggiornamento della sua modifica, potrebbe apparire così:

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 potremmo aggiornare il colore di questo oggetto? Potremmo creare un evento CarColorChanged !

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

Notare la mancanza di un salvataggio sull'oggetto modello reale? Questo perché invece di persistere direttamente nel modello persistiamo gli eventi che mettono il modello allo stato attuale. Questi eventi dovrebbero essere immutabili .

Ora andiamo avanti velocemente e cambiamo colore più volte:

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

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

Se dovessimo guardare il nostro archivio eventi (potrebbe essere un database di relazioni, 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 negozio di eventi 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 ripristinare lo stato dell'auto a un periodo di tempo precedente semplicemente creando un nuovo oggetto auto e applicare solo gli eventi che vogliamo:

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

5

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

http://goodenoughsoftware.net/

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

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

Non vorrei cercare la risposta "soft-eletes" a meno che tu non abbia specificamente bisogno di essere in grado di cercare elementi eliminati, ma non dovresti pensarli come eliminati ma piuttosto archiviati. Penso che la terminologia sia piuttosto importante qui.

Non vorrei nemmeno mantenere una "tabella delle versioni". Tutte le "tabelle delle versioni" che io abbia mai visto (incluso quello che sto provando a ripulire al momento - 7 anni di dati corrotti a causa di bug ... e nessun modo per recuperarli anche se abbiamo dati storici .. perché è altrettanto corrotto) finiscono per corrompersi a causa di bug nel codice e alla fine perdi ancora dei dati perché non puoi più tornare indietro e ricreare i dati che la corruzione ha incasinato.

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

Se hai conservato una copia della versione di ogni riga in ogni tabella del database, immagina l'orrore di dover tornare indietro a un determinato timestamp, per non parlare della folle quantità di spazio e delle prestazioni generali nel mantenere quella tabella delle versioni.

Con Event Sourcing, puoi facilmente tornare indietro, semplicemente riproducendo gli eventi fino a un certo momento. Gli avanzamenti rapidi possono essere implementati utilizzando le istantanee, ma è tutta una questione di implementazione.

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

In caso di debug, con quale frequenza hai chiesto all'utente di dirti cosa hanno fatto ... perché non semplicemente riprodurre quello che hanno fatto e poi scorrere il codice! Abbastanza elegante eh.

Spero che sia di aiuto.


2

Non proprio il tuo esempio, ma nei sistemi finanziari precedenti avevi WORM archiviazione . Se hai bisogno di "aggiornare" hai scritto un nuovo record e hai sempre fatto riferimento all'ultimo record come attuale, ma non è mai possibile sovrascrivere i dati impegnati.

Molte persone hanno portato quell'idea nei sistemi successivi. Ho sentito quello che stai descrivendo come tabelle WORM, ma solo in quei circoli.


2

Sì, è abbastanza comune nei sistemi aziendali ci sono fondamentalmente due approcci: -

  • "bimetrale" in cui ogni record ha un timbro valido e valido fino al timestamp (il record "corrente" che ha una data valida fino a "per sempre" - null, "9999-12-31" o un valore così alto). I record non vengono mai eliminati invece la data "valida fino a" viene impostata sull'ora corrente e nel caso di un aggiornamento viene inserito un nuovo record con una data valida dell'ora corrente e una data sempre valida.
  • "tabella cronologia": ogni volta che un record viene modificato, una copia del vecchio record viene scaricata in una tabella cronologia / log con un timestamp per l'evento.

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

In generale "bilaterale" è molto lavoro extra e ne vale la pena solo se si hanno molti casi d'uso come "il revisore ottiene lo stato dell'ordine al 31 dicembre".



-2

fondamentalmente il greggio non può essere completato senza queste 4 cose. Crud significa Crea, Leggi, Aggiorna ed elimina, quindi quando stai solo cercando di leggere i dati puoi usare una semplice query per quello, ma tutte e tre queste cose sono attaccate all'una e all'altra e semplici concetti di database

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.