EventSourcing suena como el patrón que puede estar buscando.
Tomemos un ejemplo utilizando un objeto simple "coche" del que querríamos hacer un seguimiento del color (a continuación se muestra el código pseudo C #).
public class Car {
public string Color { get; set; }
public Car() { this.Color = "Blue"; }
}
Con una implementación de CRUD cuando actualizamos el color del automóvil, el color anterior se perdería.
MyCar.Color = "Red";
MyCar.Save(); // Persist the update to the database and lose the previous data
Esta pérdida de información me suena como lo que más te gustaría evitar (por lo tanto, no me gusta la actualización y eliminar parte del patrón CRUD).
Si tuviéramos que volver a escribir la clase de automóvil para responder a los eventos al actualizar su cambio, podría verse así:
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;
}
}
Ahora, ¿cómo actualizaríamos el color de este objeto? Podríamos crear un evento CarColorChanged !
var evnt = new CarColorChangedEvent("Red");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);
¿Observa la falta de guardar en el objeto del modelo real? Esto se debe a que, en lugar de persistir directamente en el modelo, persisten los eventos que ponen al modelo en el estado actual. Estos eventos deben ser inmutable .
Ahora vamos a avanzar y cambiar el color unas cuantas veces más:
var evnt = new CarColorChangedEvent("Green");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);
var evnt = new CarColorChangedEvent("Purple");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);
Si observáramos nuestro almacenamiento de eventos (podría ser una base de datos de relaciones, archivos, etc.) veríamos una serie de eventos relacionados con nuestro objeto de automóvil:
CarColorChangedEvent => Red
CarColorChangedEvent => Green
CarColorChangedEvent => Purple
Si quisiéramos reconstruir ese objeto de automóvil, podríamos hacerlo simplemente creando un nuevo objeto de automóvil y aplicando los eventos de nuestro almacén de eventos a dicho objeto.
var MyCar = new Car();
var events = MyDatabase.SelectEventsForCar("CarIdentifierHere");
foreach(var e in events) {
MyCar.ApplyEvent(e);
}
Console.WriteLine(MyCar.Color); // Purple
Con el flujo de eventos podemos hacer retroceder el estado del automóvil a un período de tiempo anterior simplemente creando un nuevo objeto de automóvil y solo aplicar los eventos que deseamos:
var MyCar = new Car();
var event = MyDatabase.GetFirstEventForCar("CarIdentifierHere");
MyCar.ApplyEvent(e);
Console.WriteLine(MyCar.Color); // Red