104. Clickbait Events - EDA /Anti/Patterns
Kontynuujemy mini-serię o antywzorcach Event-Driven Architecture - ponownie z Oskarem Dudyczem. Tym razem jednak bierzemy na początek na warsztat puchnące zdarzenia: jedno “uniwersalne” zdarzenie, które próbuje zadowolić wszystkich naraz. Kolejne pole, kolejne ID “na wszelki wypadek”, aż w końcu wysyłamy w świat pół swojej bazy danych. Zupełnie jak w wierszyku o sznurku Jurka - ktoś dorzuci papierek, aż robi się góra śmieci. Jednak to tylko pretekst do tego, aby dotknąć właściwego tematu, czyli podziału między to, co publiczne, a to, co prywatne.
To według mnie jednym z takich głównych powodów jest też to, że zespół, który wytwarza te zdarzenia, ma jakieś swoje priorytety. I kolejne funkcjonalności, które są potrzebne dla innych zespołów, wiadomo, to nie jest ich jira, więc nie jest to w ich priorytetach. No i zwykle, skoro oni te zdarzenia już mają, bo o takiej sytuacji mówimy, Jeżeli oni już te zdarzenia mają i bardzo często teraz, jeżeli mamy właśnie architekturę mikroserwisową, to zwykle jeden moduł czy też bounded context, zwał jak zwał, ma kilka serwisów, bo mamy jakieś modele zapisu, modele odczytu, może jakiś jeszcze dodatkowy serwis, który wspomaga No i te zdarzenia już gdzieś tam latają na tych szynach, czy to na kawce, czy rabicie i tak dalej.
No i tutaj to jest tak naprawdę spirala nienawiści zaczyna się nakręcać, bo jeżeli zespoły w tym momencie się nie zatrzymają i nie zrobią sobie takiego sanity check, jak to mówią Anglicy, no to są do podjęcia w zasadzie tylko złe decyzje. Jedną z nich jest to, co powiedziałeś, czyli a wiesz co, no dobra, to ci dorzucimy to pole, nie? To wam będzie, wiesz, szybciej to zrobienie, zanim my tutaj przez jakieś API dociągniemy te dane, no to wy macie ten obiekt przecież przy rzucaniu tego eventu, to jeszcze dopchnijcie, to dokładnie w ten sposób powstaje. No i ktoś może powiedzieć, w sumie spoko, my też to mamy do read modeli, to będzie nam nawet łatwiej, dorzucimy to pole. Inną opcją jest to, że ktoś mówi, a wiesz co, my mamy takie jeszcze zdarzenia ze słownikami, weź se tam zasubskrybuj.
To zobaczę ile dodatkowo kodu ktoś musi naklepać, żeby tylko dociągnąć to jedno pole. No więc jak ktoś to usłyszy, to mówi wtedy, wiesz co, no w sumie tak, ale może nie masz takiego przypadkiem, może endpointcika, teraz popularne w sumie, kod, kodzik, może endpointzik też można, nie? Więc takiego poecika, gdzie mógłbym ja to po prostu doczytać, bo w sumie no fajne te zdarzenia słownikowe, ale nie chce mi się pisać tych 20 słowników razy 5, 100 handlerów, bez sensu. To ja sobie strzelę tam. No i potem strzela. I wiadomo jakie mogą być konsekwencje. Serwis może być niedostępny, dane już mogą być inne itd.
No właśnie, bo tutaj to jeszcze wspomniałem, to jest to, że ta sytuacja, wiesz, historia lubi się powtarzać. Więc to, jak opisałeś, to jeżeli to się wydarzy powiedzmy raz, no dobra, jesteśmy w stanie to przetrwać, nie? Jak to się wydarzy drugi, trzeci, czwarty, dziesiąty, no to kończymy sytuacją właśnie, że no kurczę, mamy Wiesz, tak jak we własnej pierścieni. Jeden pierścień, który próbuje rządzić światem. Mam jeden event, który próbuje zadowolić wszystkich klientów, a potem przychodzą kolejni, kolejni, kolejni i ten system jest taki, wiesz, over bloated, że tak powiem. No i tutaj trzeba, żeby się zastanowić, wrócić do podstaw, to właściwie co te eventy oznaczają. Tak. Bo to API, o którym wspomniałeś, no to, wiesz, moje pierwsze skojarzenie, no to czy to jest moje API publiczne, czy to jest moje API prywatne. Bo być może nie każdym eventem chciałbym się dzielić. Bo jak wspomniałeś o tym, że hej, hej, tu masz taką kolejeczkę, weź się zasubskrybuj. No. Dawno temu tak zrobiłem.
Zabolało bardzo mocno, bo się okazało, że na tej kolejce latały tak naprawdę nasze wewnętrzne zdarzenia, które ewidentnie nie powinny być opublikowane. Dopuściliśmy do tego, że te eventy, które były na tej kolejce, stały się de facto naszym kontraktem. De facto nie powinny, bo straciliśmy do nimi kontrolę. Nagle się okazało, że musimy utrzymywać kompatybilność wsteczną i straciliśmy możliwość ewolucji naszego modelu w ramach naszego tam modułu. No i chyba tutaj trzeba się zastanowić, właśnie do czego my w ogóle tych zdarzeń używamy? Czy używamy ich do tego, żeby spropagować stan do innej części systemu? No i wtedy faktycznie, dopychanie tam pewnych informacji, być może nawet nadmiarowych miałby sens, ale z gatunku wtedy z natury będziesz miał te informacje prawdopodobnie teczkę nieświeże i tam to się godzimy. Czy używamy tych zdarzeń do tego, żeby stygerować dalszą kontynuację procesu w innej usłudze?
No to wtedy być może Same identyfikatory by były wystarczające. Jeżeli różne serwisy miałyby potrzebę właśnie kontynuacji tego procesu i potrzebę posiadania odpowiednich danych, żeby ten proces kontynuować, no to tak, to masz ten end point, weź sobie te dane dociągnij, ale tylko te, które potrzebujesz. I wtedy, jeżeli być może przyszedłby kolejny zespół, pojawił się kolejny serwis, No to wtedy faktycznie nie musiałbym prawdopodobnie grzebać tego eventu, zmieniać jego strukturę i przy okazji jeszcze otwierać wiesz, troszeczkę wrót piekieł dla części zespołów właśnie z wersjonowaniem i o tym, o czym mówisz w kontekście tego API. Tak, no zanim w ogóle przejdziemy do powiedzmy przedyskutowania, jak dzielić te zdarzenia i co to w zasadzie są te prywatne, publiczne, o których wspomniałeś, To wydaje mi się, że warto byłoby powiedzieć, że komunikacja w systemach opartych na zdarzeniach to nie są tylko zdarzenia.
I powinniśmy wziąć pod uwagę również przy modelowaniu i wprost powiedzieć o tym, Co my faktycznie chcemy zrobić? Bo ja bardzo lubię podział Gregora Hoppe z Enterprise Integration Patterns. Tak, to jest ta gruba książka z półki wstydu każdego z nas. Ale on tam powiedział, że w zasadzie są według niego trzy rodzaje wiadomości, czyli komenda, zdarzenie i dokument. Dokument to inaczej można powiedzieć stan. Wiadomo, że w architekturach opartych na zdarzeniach preferowaną formą komunikacji są zdarzenia. Czyli ogłaszamy światu, że coś się wydarzyło i świat może na to zareagować.
Ale tak jak powiedziałeś, bardzo często świat nie potrzebuje na to reagować, nic z tym nie potrzebuje zrobić. Tylko na przykład chcemy mieć w innym serwisie lokalną kopię danych, żeby móc to wyświetlić na naszym frontendzie lub żeby móc po prostu podjąć taką decyzję na zasadzie, sprawdzamy czy taki klient istnieje. Wiadomo, że nie jesteśmy źródłem prawdy, ale może to być wystarczająco dobre. No i szczególnie jeśli mamy architekturę rozproszoną, no to wtedy pytamy własne dane, a nie gdzieś tam z serwisu, który może być padnięty. No więc wtedy, według mnie, warto po prostu powiedzieć, że nie, my nie wysyłamy zdarzenia, tylko wysyłamy po prostu stan.
Z relacyjnej do Elastica. Może mieć to sens. Ale to, co tutaj wynoszę, to jest, Oskar, to, że muszę zrozumieć, jaki jest typ tego zdarzenia, bo tutaj nawiązałeś troszeczkę do tej klasyfikacji, która mi jest bardzo bliska i bardzo mi tam, wiesz, siedzi w sercu, ta klasyfikacja Fullera z tego jego artykułu What Doesn't Mean Event Driven, gdzie właśnie Fuller pokazuje ten podział na trzy rodzaje wiadomości, czyli właśnie Event Carriage Stand Transfer, Notification Event i Event Sourcingowy. Czasem tam gdzieś widać w internecie, że ktoś jeszcze dodaje do tej klasyfikacji czwarty rodzaj, czyli taki delta event, często to jest nazywane, że nie przenoszę stanu, tylko przenoszę różnicę pomiędzy tym stanem. W praktyce to jest inna forma przeniesienia tego stanu. W zasadzie to, co powiedziałeś, te konwencje Fowlera się pokrywają z tym, co wspomniałem od Gregora Hoppe, intencją.
Wchodzisz, a tam się okazuje... I tak samo jest z tymi zdarzeniami, bo na przykład interesuje nas fakt, że rezerwacja została potwierdzona, a dostajemy zdarzenie, zmieniono status rezerwacji. No i w sumie tyle. I musimy strzelić i zobaczyć, co tam się faktycznie zadziało, jakie te dane. A potem się okazuje, że no tak, no fajnie, ktoś sobie tam zmienił status z być może potwierdzoną na prawie potwierdzoną, czy już tak... O, tutaj założyłem, wiesz, że to zdarzenie moje notyfikacyjne to właśnie nie będzie, że zmieniłem status, tylko właśnie przykładowo odwołałem rezerwację, tu masz identyfikator rezerwacji, identyfikator użytkownika, właściciela tej rezerwacji, oczywiście moment, kiedy to zostało zrobione, ale jeżeli potrzebujesz jakichś tam szczegółów tej rezerwacji,
Nie zawsze tak jest, ale bardzo często. Jeszcze co do samego takiego właśnie, jak sobie radzić z tymi zależnościami, no to wrócę do tego, co mówiłem na początku, czyli tego znanego podziału Frontend Backend, czyli API First i Backend for Frontends. To bardzo fajnym narzędziem jest tutaj do rozróżniania jak się komunikować kontekst mapy, czyli jeżeli sobie wyznaczymy jaka jest relacja między modułami, jest nam też łatwiej uwzględnić tą formę komunikacji, bo jeżeli na przykład mamy Moduł zamówienia, który jest takim centralnym koordynatorem, który gdzieś tam zbiera informacje, czy też o dostawie, o płatności itd., ale jednak jest bardziej takim, może nie koordynatorem, bardziej integratorem, czyli on tak jakby zbiera te informacje.
No to prawdopodobnie tak będzie łatwiej jakby dowieźć funkcjonalność, ale inaczej się zachowam w momencie, kiedy moich klientów obsługiwałbym w modelu open host, czy jakimś tam innym koncepcie, no to inaczej. To może wtedy właśnie na przykład w ogóle to nie powinno być zdarzenie. Znowu przywoływany Łukasz Szydło ma świetną prezentację, nie pamiętam niestety tytułu, ale podeślemy ją w linkach pod artykułem. Gdzie Łukasz powiedział o tym odwróconym myśleniu, czyli zamiast na przykład moduł wyszukiwania, nasłuchiwać na zdarzenia z wielu miejsc, no to po prostu wystawia komendę, czyli weź mi z indeksu. I może jeżeli mamy open house, to w ogóle nie powinniśmy publikować zdarzenia, tylko wysłać komendę, czyli intencję zrobienia czegoś. Możeś zrobił klamrę do Gregora Hoppe i jego klasyfikacji, bo w tym wypadku zmieniam event na komendę.
No tak, ale to według mnie właśnie te koncepty się bardzo fajnie ze sobą spinają i polecam zresztą słuchaczom zrobić sobie taki właśnie prosty test, żeby wziąć swoje moduły, spróbować sobie wziąć ten kontekst mapy, nanieść I takie jakie są, bez wymyślania jak powinny być. Takie jakie są. I nanieść sobie komunikację, jakie wiadomości latają pomiędzy nimi i wtedy zastanowić się, czy faktycznie te relacje i typy tych zdarzeń, niezależnie czy podział Gregora Hoppe, czy Martina Fowlera, Czy widzą jakieś zależności albo czy widzą, że im coś nie gra? Oczywiście to ćwiczenie jest ryzykowne, bo może być, że nie jest tak jak trzeba, ale to jest bardzo ciekawe i pouczające według mnie ćwiczenie i to są takie narzędzia,
Które faktycznie pozwalają nam na lepszą rozmowę o tym, jakie są twoje potrzeby albo w jaki sposób zrobić tą komunikację z darzeniami, żeby to nie było na zasadzie właśnie, a weź mi dorzuć, no dobra, to ci dorzucę. Najpierw co potrzebujesz, a później się zastanowić jaki jest kontekst naszych zespołów, jaki jest kontekst naszych modułów i w ten sposób zamodelować właściwie tą komunikację, bo właśnie podaliśmy dużo to zależy, ale też wydaje mi się, że sporo takich porad, gdzie można sobie to spróbować Wpasować jedno do drugiego. No i właśnie to, co mówiłeś na przykład o partnership'ie, bardzo często jest tak, i według mnie to jest ok, że jeden zespół pracuje nad kilkoma modułami i tak jak powiedziałeś, mogą sobie rozluźnić, mogą nie robić może tego mapowania dodatkowego, bo i tak jeden zespół to będzie
Wtedy to według mnie taka świadomość tego, jakie są te relacje, pomagają w modelowaniu właściwych sposobów komunikacji, a nie właśnie tą metodą palca, śliny i wiatru. Czyli co, na koniec myślę, że tak jak powiedziałeś, to powinno bardzo mocno wyglądać, że przy próbie rozszerzenia istniejącego kontraktu, albo prowadzenia nowego eventu, rozszerzenia naszego API, to czasem zadaje się pytanie, w jakim celu my to prowadzimy, jak to będzie ktoś wykorzystywał, bo to nam zacznie też mówić, co tam tak naprawdę w tym evencie powinno być i być może uniknąć tej sytuacji, że tam już będziemy szuflą dopychać 28 kolejnych pól dla Jasona, bo Jason na koniec dnia przyjmie wszystko. Tak, dokładnie. No i też zastanowić się, czy chociaż spróbować zrobić to ćwiczenie, czy inne moduły też będą potrzebowały tego i to nam też pomoże w lepszym określeniu tego kontraktu.
Pokazano wszystkie 15 dopasowań. Transkrypcja generowana automatycznie i niesprawdzana ręcznie — może zawierać błędy.
Podróżnicy opisują problem z event driven architecture, gdzie eventy stają się zbyt komplikowane i nieefektywne.
Rozmowa o problemach z eventami, takich jak dorzucanie dodatkowych informacji i użycie słowników.
Opis antywzorca Clickbait Event, gdzie zdarzenie zawiera niepełną informację, wymagając dodatkowego kliknięcia.
Rozmowa o klasyfikacji zdarzeń i zastosowaniu enrichment lub anti-corruption layer.
Analiza różnicy między zdarzeniami publicznymi a prywatnymi oraz propozycje rozwiązań.
Omówienie konceptów takich jak Context Map i propozycje modelowania komunikacji między modułami.
Ważność zastanowienia nad celami rozszerzania kontraktu lub wprowadzania nowych zdarzeń.
Rozdziały i streszczenia generowane automatycznie. Pełna transkrypcja nie jest publikowana — wyszukaj frazę, aby zobaczyć dopasowane fragmenty.
Kliknij, aby znaleźć fragmenty, w których pada.
Kontynuujemy mini-serię o antywzorcach Event-Driven Architecture - ponownie z Oskarem Dudyczem. Tym razem jednak bierzemy na początek na warsztat puchnące zdarzenia: jedno “uniwersalne” zdarzenie, które próbuje zadowolić wszystkich naraz. Kolejne pole, kolejne ID “na wszelki wypadek”, aż w końcu wysyłamy w świat pół swojej bazy danych.
Zupełnie jak w wierszyku o sznurku Jurka - ktoś dorzuci papierek, aż robi się góra śmieci. Jednak to tylko pretekst do tego, aby dotknąć właściwego tematu, czyli podziału między to, co publiczne, a to, co prywatne.