Event sourcing w pigułce czyli podróże w czasie i odporność na coraz to bardziej kreatywne wymagania biznesowe. Kiedy, jak i po co tworzyć naturalny log wydarzeń Twojej aplikacji - plusy i minusy wzorca, przykłady implementacji, event sourcing a CQRS.
17. TRADYCYJNY KOSZYK
class Cart
{
private $id;
private $products = [];
public function add($productId)
{
// changing the state of the cart
$this->products[] = $productId;
}
}
18. KOSZYK PRODUKUJĄCY EVENTY
class Cart
{
private $id;
private $products = [];
private $raisedEvents = [];
public function add($productId)
{
// changing the state of the cart
$this->products[] = $productId;
// let's raise an event
$this->raisedEvents[] = new ProductAddedToCart($this->id, $productId);
}
}
22. ODTWARZANIE AGREGATU KOSZYKA W REPOZYTORIUM
class EventSourcedCartRepository implements CartRepository
{
public function find($aggregateId)
{
$events = $this->eventStore->findEvents($aggregateId);
$cart = new Cart(); // inicjalizacja pustego agregatu
// "nagrywanie" eventów na agregacie cartu
foreach($events as $event) {
// metoda apply() woła odpowiednie metody prywatne
// na podstawie nazwy przekazywanego eventu, np.
// ProductWasAddedToCart => applyProductWasAddedToCart
$cart->apply($event);
}
}
}
23. ENCJA
class Cart
{
// this method is called by event store to replay event on the cart
protected function applyProductAddedToCart(ProductAddedToCart $event)
{
$this->products[] = $event->getProductId();
}
}
24. OBIE METODY
class Cart
{
public function add($productId)
{
if ($this->products > 2) {
throw new CartLimitExceeded();
}
// raise the event
$event = new ProductAddedToCart($this->id, $productId);
$this->raisedEvents[] = $event;
// change the state
$this->applyProductAddedToCart($event);
}
// change the state, this is called by Event Store
public function applyProductAddedToCart(ProductAddedToCart $event)
{
$this->products[] = $event->getProductId();
}
}
30. PROJEKCJE
class CurrentCartProductsProjector
{
public function applyProductAddedToCart(ProductAddedToCart $event)
{
$this->connection->query('insert into cart_products ...');
}
public function applyProductRemovedFromCart(ProductRemovedFromCart $event)
{
$this->connection->query('delete from cart_products ...');
}
}