Sławomir Sobótka, Jakub Pilimon
Model Cynefin
O BP ES
- Dobre pytania na start:
- Na czym projekt zarabia/oszczędza/traci?
- Jaki jest cel projektu?
- Jak różnicujemy się od konkurencji?
- Jakie jest otoczenie projektu (inne zintegrowane systemy)?
- Jakie są limity (prawne, budżetowe)?
- Pod co optymalizujecie proces wytwórczy? (I jak to mierzycie?)
- Event Storming nie działa tylko w jedną stronę (w stronę kodu). Działa także do odkrywania szans, zagrożeń i absurdów biznesu,
Inne
Analiza top-down (BP ES, PL ES, DL ES): gdy problem jest COMPLICATED (patrz Cynefin). Czyli wiemy co chcemy zrobić, ale nie wiemy jak.
Analiza bottom-up (DL ES, poznawanie jakiś regułek): Gdy problem jest COMPLEX, nie jest ułożony i reguły nie są jeszcze znane. Zaczynamy od modelowania tego co się na pewno nie zmieni i tego co nie możemy zrobić (bo wynika z regulacji, fizyki itp).
Deep Model
Często zbyt specyficzne modele są przyczyną przekomplikowanych systemów.
“Uogólnianie poprzez usuwanie przypadków szczególnych”. Zamiast mówić isFireCase
, isGasLeak
, itp. Można po prostu modelować Accident
Czasem przypadków szczególnych usunąć się po prostu nie da. Ale jeśli na dole mamy generalny problem to można je wypchnąć wyżej.
To daje możliwość budowania funkcjonalności dla Ekspertów (ludzi, którzy chcą mieć dostęp bezpośredni do jakiś operacji, inductive UI) i Zwykłych Użytkowników, przy jednoczesnym zachowaniu tych samych reguł (task based UI).
Z User Stories ciężko wyciągnąć deep model. Będzie to raczej suma przypadków.
Czasami uda się wyabstrachować 8/10 przypadków. Wtedy deep model też spoko, można resztę doklepać ifami. Albo jak mamy 12, ale ultra stabilnych case-ów, to szybciej może być po prostu je zahardcodować, jeśli faktycznie nigdy się nie będą zmieniać.
Przydatne do tego może być przeglądnie gotowych archetypów, paternów, struktur. Można zrobić taki brute-force, jest duża szansa, że się coś znajdzie.
Dużo łatwiej jest ocenić sensowność rozwiązania, gdy już mamy przykładowe rozwiązania.
Dużo łatwiej jest zredukować problem który chcesz rozwiązać, gdy wiemy JAK go rozwiązać.
Można szukać generalizacji, np. faktura/zwrot/korekta to po prostu dokument.
Można też eksperymentować z zminą reprezentacji. Zamiast trasa jako rekordy w tabeli to np. graf.
Wiele problemów można sprowadzić to jakiegoś generalnego problemu (e.g. knapsack packing). Wtedy algorytm można wziąć z gotowca. A samo rozwiązanie może być generycznym algorytmem, które nie wie co konkretnie przelicza (pakuje plecak, albo dopasowywuje ludzi do projektu).
Opracowanie dobrego modelu w kontekście konkretnego problemu to klucz do zwycięstwa.
O modelowaniu procesów
BP ES praktycznie zawsze warto zrobić. Później warto spróbować wyłonić problemy COMPLEX. Te ciężko sprawdzić za pomocą analizy top-down, biznes nie jest w stanie wskazać konkretnych procesów i/lub reguł. Dlatego używamy tutaj bottom-up.
Po rozprawieniu się z problemami COMPLEX, można przejść do COMPLICATED. Organizacja wie jak rozwiązać te problemy. Tutaj przyda się top-down i PL ES.
Podczas PL ES skupiamy się na przyczynach i skutkach. Ważne są przyczyny i konsekwencje zdarzeń, nie co w tych zdarzeniach się dzieje. O tym JAK się dzieje będzie na DL ES.
Kształt myślenia w czasie PL ES w czasie. Najpierw zbieramy pomysły (Divergent), potem je analizujemy (Emergent), na koniec zawężamy póle pomysłów (Convergent).
Warto to ten obrazek przedstawić na początku spotkania, aby osoby analitycznie nie zraziły się po pierwszej fazie i wiedziały po co ona służy, jest częścią większej całości, dążenia do celu.
! Wyjątkiem jest modelowanie AS IS, wtedy nie ma tego diamentu.
Przed rozpoczęciem ES:
- Zakomunikuj cel spotkania i powołuj się na niego w razie problemów,
- Wprowadzaj notację stopniowo
- zdarzenia - istotne wydarzenia w procesie. Czyli takie które wpływają na kierunek kolejnych zdarzeń (coś się może wydarzyć bądź nie, lub w innej kolejności, lub w inny sposób). > Warto podać przykłady, następnie poprosić uczestników o podanie ich przykładów i zweryfikowanie ich
- komendy - mogą być triggerowane przez użytkowników lub inne systemy. Może zostać odrzucona przez proces (narusza reguły). e.g. add user → user added
- widoki - UI albo dane dla innych systemów/raportów,
- reguły procesowe - nienaruszalna reguła procesowa, wpływa na rozwidlenie procesu na osobne gałęzie. Tylko reguły procesowe, nie walidacyjne, spójności danych, algorytmiczne, zmiany stanu.
- Jeśli potrzeba to dodaj swimlanes:
- poziom poza systemem,
- UI,
- domena,
- infrastruktura (wrzucono event na kafkę <3),
- poziom innych systemów,
- Rozpocznij od istotnych zdarzeń
- dla sesji TO BE – pivotal events (”milestone events”, takie których odwrócenie jest trudne, może okazać się całym osobnym procesem)
- dla sesji AS IS – zdarzenia ramowe, czyli początkowe i końcowe zdarzenia
Stara indiańska sztuczka na zrozumienie tego jak ktoś rozumie dany problem – poproś o go narysowanie tego problemu 🙂
Jeśli znasz już domenę, masz ogólne pojęcie o rozwiązaniu, nie trzeba zwoływać ludzi na storming. Można przeprowadzić go samemu. Trochę nad nim pokminić, następnie wysłać w formie maila do przejrzenia. Można zaoszczędzić ogrom $$$.
Jeśli zdarzenia są parafrazami komend, to mogą być dwa powody tego:
- Albo domena płytka, CRUD.
- Musisz bardziej pytać o szczegóły, dochodzić do sedna.
Modelować można 3 rzeczy: Being, behaving, becoming (struktury danych, zachowania, zmiany istoty). Struktury danych (Being) nie przybliżają do zrozumienia działania biznesu. Zachowania (modelowane na PL ES) pozwalają zadać prawdziwie wartościowe pytania:
- kto zmienia?
- dlaczego zmienia?
- jaki skutek zmiany?
- jaki powód zmiany?
- czy zmianę można wycofać/powtórzyć?
- (Jak widzimy bardzo generyczny event typu “Edytowano ChargeCode”, Albo bardzo specyficzny “Edytowano alternatywne zdjęcie projektu”) 5 Why:
- TOP - dlaczego to jest ważne?
- DOWN - jaki jest skutek?
Becoming to niższy poziom, DL ES.
Niektóre nazwy komend mogą się powtarzać, ale to nie musi oznaczać, że znaczą to samo. Warto sprawdzić skutki (zdarzenia) po komendzie.
Złe pomysły (karteczki), też można zbierać w szufladzie “zaoszczędzone pieniądze” i dać na koniec sponsorowi spotkania.
Frazy praktycznie zakazane podczas ES:
- zmieniono status,
- zapisano rekord do BD,
- usunięto,
- itp. techniczne zdarzenia,
Najlepiej powiedzieć, że na potrzeby takiego modelowania zapominamy o istnieniu serwerów, BD … są tylko kartki i ołówki.
Biznes warto zapytać o części systemu, które są ważne dla nich, tzw. core. Następnie zapytaj ekspertów o to co łatwo tam zrefactorować. Wtedy wyłaniają się low-hanging fruits - win-win dla biznesu i ekspertów (devów, technicznych).
Uwaga na ekspertów!
- Użytkownikiem może być ekspert, który wie jak coś działa, nie chce się babrać z UI lub “wie lepiej” co chce zoptymalizować/osiągnąć (np. wystawia konkretną fakturę).
- A czasami użytkownikiem jest laik, który nie chce/nie zna technikaliów pod spotem i chce mieć tylko przycisk, który coś robi (np. generuje fakturę z płatności).
- A czasami obydwoje korzystają z tego systemu.
Warto zrozumieć z kim mamy do czynienia. Żebyśmy czasami nie modelowali Capability dla Laika!
Problemy mogą leżeć też po stronie samego procesu. Może on być niepotrzebnie skomplikowany, albo aktualny model implementuje coś za dużo/za mało. Warto przedstawić wtedy model As-is biznesowi i zapytać go o walidację tego modelu. Jak rozumiecie daną funkcjonalność? Co jest zbędne i na nic nie wpływa? A czego brakuje? Wadliwy proces trzeba jak najszybciej i dokładniej wychwycić, w innym wypadku tylko usztywnimy granice złego procesu!
Nie myśl rozwiązaniem technicznym. Wszystko da się zrobić. Celem jest zrozumienie jak działa biznes. Zaoszczędzone skupienie można poświęcić na odczytywanie komunikacji werbalnej i niewerbalnej.
Komunikacja podczas ES
Dla osób nastawionych na różnicowanie i szczegóły - pytaj w górę (dlaczego to jest ważne?). I przeciwnie. Dla osób które operują na zbyt dużym poziomie ogólności, a ty czujesz, że unika wam sedno problemu, pytaj w dół. Uwaga! Warto te przejścia robić w sposób świadomy. Te informacje pozwalają nam zarysować ogólny kształt projektu. Ale aby jeszcze bardziej zrozumieć istotę problemu i zmniejszyć ryzyko, musimy zejść niżej. Odnoś się do celu spotkania.
Jeżeli osoby nastawione na ogół odpływają za mocno, to odnoś się do celu spotkania i procesu, do ostatniego zdarzenia. Jeżeli chcesz uwypuklić problem, to poproś osoby zorientowane na problemy o zaznaczenie ich na procesie w miejscach gdzie zagrażają celu.
Heurystyki szukania modeli
Przed audytem systemu, trzeba zapytać o drivery architektoniczne. Bez nich nie da się stwierdzić czy podjęte decyzje są poprawne czy nie. Drivery powinny mieć atrybuty jakościowe (metryki, np. np. awarie tego modułu nie mogą wpływać na działanie innych). Te pozwalają na agregowanie/sugerowanie heurystyk. A dzięki temu można przeprowadzać znacznie symulacje. Symulacje można robić od początku, ale ilość wariantów jest przeogromna. A tak mamy takie sita, przez które filtrowane są niepoprawne rozwiązania.
Czyli to taki ciąg:
Drivery Architektoniczne — posiadają → Atrybuty Jakościowe — sugerują → Heurystyki — zawężają → Symulacje
Heurystyka: Główne Pytania
- Zapisz aktorów i aktory korzystajace z systemu,
- Dla każdego z nich: zapisz na jakie pytania będą szukać odpowiedzi,
- Sprawdź czy pytania te są istotne:
- w ilu miejscach procesu są zadawane?
- czy wpływają na proces?
- jak często są zadawane?
- jak wpływają na cele strategiczne?
- Oznacz zdarzenia, które wpływają na te pytania
- Dowiedz się, które muszą być spójne atomowo
Pytania muszą być odpowiednio zadane, bo mogą wpływać odpowiedź.
Czy X musi być spójne z Y?
Co by się stało jeśli stan X zsynchronizujemy z Y za klika sekund?
Jeśli do jednego eventu są doczepione dwa pytania to znaczy, że tak naprawdę to są te same pytania, tylko zadane przez dwóch różnych aktorów.
Można mieć deep model, który nie operuje bezpośrednio na zapisanych danych. Np. możemy polegać na tym, że graf zostanie dostarczony do deep modelu, deep model policzy coś na nim (np. reguły na krawędziach, przejścia) i wypluje odpowiedź typu “Nie da się/da się, Spełnione w 7/9 przypadkach, itp.”. Wtedy mamy single rule, multiple source of data.
Możemy mieć sekcję krytyczna, gdzie stan musi być perzystowany i spójny atomowo (availability), bo wiele rzeczy może działać na tym współbieżnie (np. symulacje). To czy coś jest dostępne czy nie to single rule, i jest w zakresie single source of truth (data).
Możemy mieć model, który operuje i na wielu regułach, i na wielu zasobach (symulacja czy w danym momencie coś jest “robialne”, jak wpłynie to na wiele innych projektów aktualnie prowadzonych). Czyli mamy multiple rules, multiple source of data.
Heurystyka: Alternatywne Wejścia i Wyjścia
Firmy naciskają na budowanie procesów, bo procesy pomagają usystematyzować pewne działania. Zmniejszają też bus factor, przez co zwiększają zastępowalność. To oczywista optymalizacja kosztów.
Najpierw są pewne reguły (prawne, fizyczne, itp.) do których dopasowują się procesy. Nie na odwrót, reguł nie naciągamy aby pasowały nam pod proces.
Sama logika w tych punktach może się zmieniać, ale nie musi wpływać na przebieg procesu. Tak oto mamy koleją z heurystyk wyszukiwania modeli.
Podczas zakupu blokujemy towary. Dlaczego jeszcze możemy blokować towary?
Np. dlatego, że ktoś je dostał w gratisie. Albo coś jest z nimi nie tak i chcemy zweryfikować co.
Aby rozmowa nie brzmiała jak naciągnie klienta na $$$, marnowanie czasu, można zastosować konstrukcję:
Po to, aby <korzyść dla klienta>, potrzebujemy zrobić <aktywność>.
Przykład:
Po to, aby sprawdzić czy nie dałoby się użyć gotowych rozwiązań w postaci dostępnych modeli, potrzebujemy zadać klika pytań w specyficzny sposób. Pytania mogą brzmieć jak niepotrzebne rozdmuchiwanie zakresu projektu, zdajemy sobie z tego sprawę, ale nie pytam po to by to realizować, a złapać punkty swobody modelu, aby dobrać gotowe rozwiązania
Heurystyka: Pivotal Events
Pivotal event to milestone. Coś dużego zostało osiągnięte. Można to rozpoznać po tym, że:
- ciężko się z tego wycofać, np. osobny proces na reklamację,
- zmienia się reprezentacja, np. oferta (na stronie) → zamówienie (można jeszcze dodać rabat itp.)
Przydatne pytania:
- Czym operujemy przed, a czym po zdarzeniu?
- Czy zmienia się struktura danych (dochodzą jakieś nowe informacje)?
- Czy te struktury mogą być użyte w innych procesach?
Heurystyka: Capability vs Product
Moduły można podzielić na Capabilities (Generyki) i Products (Orkiestratory).
Generyki - coś do czego nigdy nie powinny przeciekać specyficzne pojęcia nie mające zastosowania w innych modułach, nie powinny wiedzieć o kolejnych krokach procesu.
Produkty - biorą na siebie odpowiedzialność za coupling pomiędzy generykami.
Podsumowanie
Jeśli ekspert domenowy używa tego samego słowa i wysyła sprzeczne komunikaty, to prawdopodobnie mówi o czymś w dwóch różnych kontekstach, gdzie to coś ma różne znaczenia i reguły.
Podczas spotkania ES nie można zerwać cienkiej lini porozumienia i zarzucać uczestników spotkania pomysłami na gotowe generyki (nie zmieniamy ich słownictwa). Możliwe, że oni nie potrafią abstrahować i istnieje ryzyko, że odciągniesz ich od clue problemów.
Im więcej modułów, tym bardziej SLA spada (SLA modułów trzeba przez siebie pomnożyć)
Rolą projektanta jest zredukować ilość decyzji, których zmiana jest kosztowna
Mapa autonomicznych modeli
Mapa kontekstów to najważniejszy artefakt w projekcie.
Sposoby mapowania kontekstów
- Free
- Published Language - dobrze udokumentowany i współdzielony język pomiędzy różnymi kontekstami. Każdy w swoim kontekście jest w stanie tłumaczyć na i z tego języka. [Wzorzec Organizacyjny]
- Separate Ways - Gdy zespoły wg nie mają ze sobą komunikacji. Godzimy się na możliwe duplikacje w danych i zachowaniach. [Wzorzec Organizacyjny]
- Mutually Dependant
- Shared Kernel - dwa zespoły współdzielą jakiś artefakt. [Wzorzec Techniczny]
- Partnership - dwa zespoły muszą razem dowozić kontent. Muszą się synchronizować z swoimi zmianami. [Wzorzec Organizacyjny]
- Upstream-Downstream
- Conformist - przyjmuje wszystkie zmiany jak leci, ciągle się dostosowuję, nie mam strefy zgniotu. [Wzorzec Organizacyjny]
- Anti-Corruption Layer - tłumaczy na wejściu model zewnętrzny. Minimalizuje problem bycia konformistą. [Wzorzec Techniczny]
- Customer-Supplier - typ relacji gdzie downstream ma wpływ na upstream. “Możecie nam klepnąć taką funkcję? I jeszcze to dodajcie. A nam tego brakuje…”. Wtedy upstream (supplier) cały czas zarządza priorytetami co dla kogo klepnąć. [Wzorzec Organizacyjny],
- Open-Host Service - oferuje generyczne API dla wielu konsumentów. Minimalizuje problem bycia dostawcą w Customer-Supplier. [Wzorzec Techniczny]
Core Domains nie powinny być w relacji downstream do innych.
Zbyt dużo specyficznych wymagań może podkreślać brak odpowiedniego wyabstrahowania generyka.
Logiczne poziomy integracji kontekstów
Zamiana fizycznego kierunku przepływu informacji (czyli podmiana Query/Command na Event) nie zmieni logicznego kierunku przepływu informacji. W tym modelu nadal Simulation zależy od Allocation (co jest złe, simulation to core-generic. Powinno być zaimplementowane jako komenda z Allocation do Simulation)
Wyeliminowanie temporal couplingu, nie zmienia logical couplingu.
Wszystko da się wymienić na eventy. Można emitować ”Zapytano o symulacje (stan)”. Ale to niczym nie różni się od komendy, a znacznie skomplikuje. Jeśli znamy kolejny krok w procesie biznesowym - użyj komendy.
Są dwa typy Eventów emitowanych pomiędzy modułami:
- Event notification (
ProjectCreated
) - jak najmniej informacji, event z “wynikami”, skrojone pod konsumerów, - Event carried-state (
ProjectStatusEdited
) - cały stan z statusami.
Tutaj trzeba być świadomym użycia. carried-state może być spoko do odświeżenia cache-a (albo nawet read modelu?). Ale jeśli użyjemy go do czegoś innego, np. kontynuacji procesu w innym module, to wycieknie nam model i rozleje logika biznesowa.
Klasyfikacja Problemów Modelarskich
- W złożonych formularzach warto odseparować pola które są zwykłymi CRUDami, od tych z bogatą logiką domenową,
- Potem można to rozdzielić na dwa osobne contollery, jeden do obsługi CRUDa, drugi do obsługi złożonej logiki,
- W przypadku gdy CRUD może wpływać (lub dane dostępne są do zmiany tylko w pewnym stanie) na bogaty model, to wtedy idzie to przesłać sygnałem
edited(updatedFields)
- wtedy bogaty model może zaktualizować się, lub odrzucić zmiany CRUDa
- logika nadal po stronie bogatego modelu
Problem Transformacji i Prezentacji
Read model można budować na parę sposobów:
- Query do DB - najprostsze,
- Materialised view - wygodne, jeśli nie potrzeba wydajności,
- cache odświeżany eventami z źródeł prawdy - najwydajniejszy, ale najbardziej skomplikowany. State-transefer events są spoko. Można dodać TTL, żeby cache sam sie przeliczył
Ważne jest tutaj, aby odseparować model zapisu od odczytu.
Cache to zawsze powinno być coś co można usunąć i odtworzyć z źródeł prawdy, bez utraty danych.
Problem Integracji
Capabilities, które zawsze będę OHSami, muszą być przez coś zarządzane. Potrzebują jakiegoś orkiestratora.
Jeśli musimy synchronicznie wywołać parę command/queries, wtedy, w pierwszej kolejności warto wywołać coś, co:
- Łatwo jest wycofać,
- Ma dużą szansę niepowodzenia,
Moduły integracyjne (Ryzyko, Scoring) mają często wiele połączeń przychodzących i wychodzących. I tak, awaria każdego z zależnych modułów, wpływa na moduł integracyjny. Ale często życia nie oszukasz 🙂. Za to awaria integratora nie wpływa na inne moduły.
Problem zaczyna się, jak wszystkie problemy (moduły) byłyby integracyjne. Wszystko gada z wszystkim i zależy od wszystkiego. Integrator integruje się z integratorami 😫
Problem Rywalizacji o zasoby
Tutaj wymagany jest DL ES. Zależy nam na regułach domenowych (te nie zostały odkryte podczas PL ES), jak np. saldo nie może być niższe nić limit debetowy. To całkiem inne rodzaje reguł, niż reguły procesowe (procesowe zmieniają flow procesu). Tutaj użycie agregatów ma sens.
Aby wydobyć więcej reguł, można zadać proste pytanie: Czy może się ono wydarzyć jeśli wcześniej zaszło ono samo lub inne zdarzenie?
Dobre pytanie o atomowość:
Jaka byłaby konsekwencja, jeśli sprawdzilibyśmy drugą regułę (np. not disabled) nieco później, za 1 minutę? Czy ktoś równolegle mógłby coś tu namieszać?
Model wielkiej skali
Policy to domknięcia, strategie dobierane przez Decision Support (Strategy Factory?).
Problem modelarski: Transformata
Jeśli dobrze zamodelujemy system, to możliwe jest posiadanie bezstanowych serwisów. To wcale nie musi być utopia, żeby problem był bezstanowy.
W przypadku gdy Policy miesza się z Decision Support, istnieje możliwość wprowadzania bugów (When wpływa na inne How). Kod również łatwiej testowalny.
Rywalizacja o zasoby - jednostki spójności
^ To to jeszcze jest CRUD 🙂
asd
Najczęściej poruszane kwestie w rozmowie co jest lepsze to:
- “obiektowe lepsze”, “bo wypada”, (argument z pizdy)
- testowalność (już lepiej, choć integracyjnie też da radę, bo jak już 1 test jest to potem z górki z takimi ifami)
- ponownie użycie, ukrycie reguł (też git, ale jeśli reguły użyte tylko raz to argument ma małą moc)
- Model mentalny. W przypadku skryptu building blocki to encje (tabele) i skrypty (serwisy). Transaction skrypt w łatwy sposób pozwala na sięganie do różnych tabel w różnych skryptach. Aż zachęca do pomijania tych reguł, a w Agregacie ciężej.
- Jednostki spójności. W trans. scriptcie można (często) dotykać wiele tabel jednocześnie. Wtedy, jeśli chcemy coś zablokować, to możemy operacją zmiany opisu blokować coś całkiem innego, ważniejszego
Celem nie jest OOP. Celem jest:
- ukrycie stanu i pewność sprawdzenia reguł,
- prywatność stanu który będzie blokowany,
- szybki i spójny odczyt,
Implementacja nie jest ważna (procedura vs OOP). Ważny jest kształt jednostki spójności (jak najmniejsze możliwe).
Proces biznesowy może być tak skonstruowany, że niektóre komendy mogą się dziać jedna po drugiej. Ryzyka blokowania wtedy nie ma.
Jeśli Proces A i Proces B mogą dziać się równolegle, to to powinno się blokować.
Chcemy mieć jak największą kohezję (Czyli jak dobrze grupujemy obiekty, które są wspólnie używane), bo chcemy wczytywać jak najmniej potrzebnych danych do podjęcia decyzji. W agregatach to jest pożądane. W fasadach może być nisko, bo tam to nie jest celem.
Metryka LoC dla agregatów nie ma sensu. Dla dobrze skonstruowanego agegata LoC może być małe albo duże (2 pola, 16 metod lub odwrotnie). Ale to nie o to chodzi. Chodzi o to, żeby zachować atomowość tam gdzie musi zostać zachowana.
Wybierając pola do jednostki spójności, powstaje nam graf obiektów. Celem jest atomowość, graf jest konsekwencją.
Jeśli musimy zapisywać kolekcję zależną w agregacie (najprawdopodobniej IDków), to to może być code-smell. Dlaczego agregat musi rozpinać się na tak wiele tabel? Rodzi to wiele ryzyk.
Jeśli już faktycznie potrzebujemy to perzystować, to można to zapisać jako JSONB
.
Elementy konstrukcyjne wokół agregatów
ApplicationService
- koordynuje proces biznesowy,
- loguje,
- ogarnia security,
- odświeża widoki,
- zakłada transakcje,
- wysyła zdarzenia,
- komunikuje się z światem zewnętrznym.
Logika prezentacyjna i integracyjna
Dane są nieaktualne w momencie opuszczenia transakcji bazodanowej. A to też zależy od rodzaju transakcji […]. Dane na UI to też forma ceche-u. To nie wynika z wzorca CQRS, a z architektury klient-server.
CQRS na 3 poziomie (dedicated read-models) daje:
- możliwość użycia innej bazy do write-modeli (np. Event Sourcing, grafowa). Również zmiany w przyszłości nie odbijają się na read-modelach.
- uwolnienie modeli dziedzinowych od kwerend (łatwiejszy refactor)
- niski koszt utrzymania
Zdarzenie opresyjne - anty-patern. Zdarzenie, na które:
- nasłuchuje tylko jeden model,
- jest kontynuacją jakiegoś procesu (wiemy jaki jest następny krok),
- dobrze wie, kto jest zainteresowany tym zdarzeniem,
- payload jest robiony pod to zdarzenie
Pytania przy rozważaniu choreografia vs orkiestracja
- Czy interesuje mnie kolejność wykonywania kroków procesu?
- Czy interesuje mnie atomowość procesu (wszystkie albo żaden, kompensacje nieudanych)
- Czy trzeba monitorować?
- Czy często się zmienia?
- Czy muszę go wersjonować?
- Czy kończy się zdarzeniami opresyjnymi?
- Czy mam logikę wyliczającą kolejny krok w zależności od wielu czynników?
- Czy proces może zakończyć się bez ostatniego kroku?
- Czy jeśli mam większą ilość listenerów, to czy interesuje mnie kolejność przetwarzania ich?
Jeśli odpowiedź na aby jedno to twarde TAK - to prawdopodobnie jest to orkiestracja.
Process Manager - odpowiedzialny za wyliczanie następnych kroków.
Saga - odpowiedzialna za atomowość procesu przez kompensacje.
Często jedno zawiera drugie.
Projektując systemy rozproszone, trzeba pamietać, że Exact once delivery nie istnieje. Ale celem jest exactly one processing, czyli idempotenty konsument + producent z at-least-once delivery.
Breakthrough i Architektura Aplikacyjna
Często mówi się, że:
Zadanie świadomego programisty/programistki: Dowiezienie tematu oraz wzięcie odpowiedzialności za swoje decyzje i ich uargumentowanie (nawet jeśli łamią jakieś ogólnie przyjęte dobre praktyki).
Warto wtedy zadać pytanie: Jak inaczej zaimplementowałbyś to, gdybyś miał więcej czasu?
Nowe, nieoczywiste wymagania biznesowe mogą być benchmarkiem dla istniejącej architektury.
- Albo będzie git, wszystko będzie smooth i nawet usprawni istniejącą architekturę,
- albo pogrąży projekt jeszcze bardziej, dołoży więcej couplingu i bugów.
Generyki (jeśli dobrze wydzielone) powinny zostać generykami. Ale sporo można ugrać tworząc modele które mapują dane w różny sposób do tych generyków.
Architektura warstwowa/hexagon
Od warstw się nie ucieknie. Zawsze jakieś są. Występują na wielu płaszczyznach (infra, domena, między modułami). To po prostu różne poziomy abstrakcji. Warto modelować je świadomie.
Za pomocą 3 warstw też można daleko zajść. Tylko trzeba pamiętać o programowaniu do interfejsu a nie do konkretów. Wtedy różnice pomiędzy hexagonem nie są tak wielkie
Kluczową rolą portów i adapterów jest izolacja warstw domeny od zmian interfejsu warstw niższych (np. perzystencji)
DDD Lean
Warto odseparowywać to co jest stałe od zmiennego → reguły aplikacyjne od procesowych. Oraz reguły spójne natychmiastowo od spójnych końcowo.
Można nie znać DDD a nadal mając pewne pryncypia w głowie pisać dobry kod. Można znać DDD ale bez głębokiego zrozumienia i tak pisać paździerz.