Podstawowe koncepcje Event Sourcing
Event sourcing to potężny, ale złożony wzorzec często używany we współczesnej architekturze oprogramowania, szczególnie w aplikacjach C# i .NET Core. Aby w pełni zrozumieć, jak zaimplementować event sourcing, przejdziemy przez kluczowe zasady wyjaśniane przez Dereka Comartina z CodeOpinion.com w jego filmie "Event Sourcing Core Concepts".
Jeśli chcesz lepiej zrozumieć koncepcje magazynu zdarzeń, projektowanie zorientowane na domenę lub jak budować systemy oparte na event sourcing, jesteś we właściwym miejscu. Zaczynamy!
Wprowadzenie do Event Sourcing
Na początku (0:00) Derek omawia zamieszanie wokół event sourcing oraz związane z nim podstawowe koncepcje. Określa event sourcing nie tylko jako "zatrzymywanie obecnego stanu", ale przechowywanie zdarzeń – zatrzymywanie każdej zmiany, jaka występuje w modelu dziedzinowym, w logu tylko do zapisu.
W ten sposób zachowujesz pełną historię zmian stanu twojego systemu. Zamiast utrwałać tylko stan końcowy, utrwałasz zdarzenia, które odzwierciedlają logikę biznesową, która miała miejsce.
Zdarzenia: Zatrzymywanie faktów biznesowych
O 0:33 Derek wyjaśnia, czym faktycznie jest zdarzenie. Zdarzenie reprezentuje coś, co już się wydarzyło w systemie — fakt biznesowy. Na przykład zdarzenie "ProductReceived" zawierałoby ilość otrzymaną i datę.
Derek podkreśla, że kiedy przechowujesz zdarzenia, muszą być one nazywane zgodnie z konwencją nazewnictwa, która odzwierciedla czas przeszły, na przykład "Product Shipped" lub "Inventory Adjusted". W schemacie zdarzenia możesz mieć pola takie jak public Guid Id, public string Name i znaczniki czasu.

Każde zdarzenie powinno również mieć unikalny identyfikator, co jest kluczowe dla systemu przechowywania tylko do dodania, w którym dodajesz zdarzenia do strumienia zdarzeń.
Strumienie zdarzeń: Organizowanie zdarzeń
O 2:02 Derek przechodzi do strumieni zdarzeń. Dokonuje porównania z tabelą relacyjnej bazy danych, ale wyjaśnia, że w event sourcing wszystkie zdarzenia związane z obiektem domeny (np. przedmiotem inwentarza) należą do tego samego strumienia zdarzeń.
Każdy strumień zdarzeń jest powiązany z określoną jednostką - często definiowaną przez public Guid Id i string Name. Na przykład produkt z SKU ABC123 miałby swój strumień zawierający utrwalone zdarzenia takie jak przyjmowanie lub wysyłka.
Derek sugeruje, że kiedy modelujesz te, myśl w kategoriach korzeni agregacji i obiektów domeny, zapożyczając z koncepcji projektowania zorientowanego na domenę.
Modelowanie cyklu życia — czy to krótkotrwałego, czy długotrwałego — pomaga optymalizować liczbę i wielkość strumieni. Jest to kluczowe dla poprawy wydajności w złożonych systemach.
Projekcje i modele odczytu
O 4:12 Derek wprowadza projekcje i model odczytu. Ponieważ twój system oparty na event sourcing przechwytuje zdarzenia zamiast tylko obecnego stanu, musisz odtworzyć zdarzenia, aby odpowiedzieć na pytania, takie jak "Jaka jest aktualna ilość zapasów?"
Aby zbudować modele odczytu, przetwarzasz zdarzenia ze strumienia. Na przykład używając private void Apply(Event e) lub podobnej metody, zwiększasz lub zmniejszasz zapasy na podstawie obsługi zdarzeń dla każdego typu zdarzenia.
Derek ilustruje, jak zbudować model odczytu w bazie dokumentów lub bazie relacyjnej — być może w jednej projekcji po prostu jest pokazana dostępna ilość, w innej historia wysyłek.
To odzwierciedla segregację odpowiedziąlności za zapytania i polecenia (CQRS): oddzielenie operacji zapisu (poleceń) od operacji odczytu (zapytania).
Projekcje dla modeli zapisu
O 6:48 Derek pokazuje, jak stosować projekcje również po stronie zapisu. Jest to kluczowe dla weryfikacji działań, zanim zostaną one dopuszczone.
W handlerze polecenia, przed wysyłką produktów, musisz zweryfikować, czy istnieje wystarczająca ilość. Derek używa metody jak private void Apply(List
Pola jak public int Version pomagają śledzić ewolucję strumienia, zapewniając ostateczną spójność.

To praktyczne wdrożenie pomaga wymusić logikę biznesową przy obsłudze nowych zdarzeń, zapewniając, że twój system działa tylko na podstawie poprawnych przejść stanów.
Subskrypcje: Reagowanie na nowe zdarzenia
O 8:01 Derek omawia subskrypcje. Subskrypcje pozwalają konsumentom zdarzeń słuchać nowych zdarzeń i reagować.
Na przykład projektor może subskrybować strumień zdarzeń i aktualizować model odczytu, gdy zobaczy zdarzenie "Product Shipped". Alternatywnie, wydawca może nasłuchiwać zdarzeń i publikować je do zewnętrznych systemów jak RabbitMQ lub Kafka, integrując się z innymi usługami.

Derek opisuje subskrypcje nie tylko do aktualizacji wewnętrznych modeli, ale także do dystrybucji danych w oddzielnych systemach zdarzeń, zachowując ostateczną spójność.
To pokazuje kolejny główny korzyść architektury opartej na zdarzeniach: twoje usługi pozostają ostatecznie spójne, ale niezależnie skalowalne.
Omówienie podstawowych koncepcji
O 9:21 Derek podsumowuje podstawowe koncepcje:
-
Zdarzenia zatrzymują fakty.
-
Strumienie zdarzeń organizują zdarzenia według jednostki.
-
Projekcje zamieniają strumienie w modele odczytu możliwe do zapytania lub modele zapisu możliwe do działania.
- Subskrypcje pozwalają usługom reagować i odpowiednio się aktualizować.
Podkreśla, że przechowujesz zdarzenia w logu tylko do zapisu, utrzymujesz ścieżkę audytu i odtwarzasz zdarzenia, gdy jest to konieczne.
Snapshotowanie i optymalizacja
O 9:39 Derek porusza temat snapshotowania. Chociaż często omawiany w kontekście event sourcing, wyjaśnia, że snapshoty są optymalizacją wydajności, a nie zasadniczym wymogiem.
Snapshoty zmniejszają narzut ponownego odtwarzania wszystkich zdarzeń przez okresowe zapisywanie częściowego stanu, ale kompletna historia nadal istnieje poprzez log tylko do zapisu.
Kluczowe rozróżnienie: Event Sourcing vs Architektura oparta na zdarzeniach
O 10:00 Derek ostrzega przed powszechnym nieporozumieniem: event sourcing i architektura oparta na zdarzeniach to różne rzeczy! Narzędzia takie jak Kafka pomagają w rozprowadzaniu danych, ale prawdziwy event sourcing koncentruje się na rejestrowaniu zdarzeń dziedzinowych jako niezmiennego śladu audytu.
Zrozumienie różnicy jest kluczowe, gdy integrujesz event sourcing w swoich złożonych systemach.
Wnioski
Na podstawie filmu Dereka Comartina jasno wynika, że event sourcing polega na rejestrowaniu każdej zmiany jako zdarzenia, a nie tylko stanu końcowego. Przechowując zdarzenia w systemie przechowywania tylko do dodania, tworzysz bogaty schemat zdarzeń, który zapewnia ślad audytu, elastyczność w zapytaniach dotyczących zdarzeń i solidne wsparcie dla segregacji odpowiedziąlności za zapytania i polecenia.
Niezależnie od tego, czy masz do czynienia z event sourcing w C# na .NET Core, czy na jakiejkolwiek innej platformie, zorganizowane wyjaśnienie podstawowych koncepcji, obsługi zdarzeń, private sets, protected sets i stosowania zdarzeń takich jak private void Apply() w swoich modelach Dereka jest niezwykle cenne.
Jeśli pracujesz nad budowaniem odpornego modelu dziedzinowego, poprawą systemu przechowywania, czy tworzeniem złożonych wzorców z wieloma korzyściami, takimi jak ostateczna spójność, studiowanie podejścia Dereka jest koniecznością. Obejrzyj jego kanał YouTube dla bardziej wnikliwych filmów.
