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