Z punktu widzenia aplikacji - tak, normalne. Z punktu widzenia domeny biznesowej, nielegalna akcja IMO.
Nie bardzo cię rozumiem. Nielegalność akcji nie ma nic wspólnego z wyjątkowością.
No dobra, tu się zgadzam.
To jest normalne działanie systemu - nie masz kasy na koncie, nie możesz wypłacić. To jest zwykła domenowa walidacja akcji, nie ma w niej nic wyjątkowego.
Ale jednak, chciałbym też móc moim podejściem ohandlować coś co faktycznie jest wyjątkowe. Np gdyby ktoś podał zły SECRET_KEY w .env, to chciałbym żeby część userowa na to zareagowała inaczej niż część adminiowa albo cronowa. A co do postu @somekind, to to nie są 3 aplikacje. To jest jedna aplikacja, do której mogą się zalogować dwa typy userów (plus job w cronie). Panel admina i panel usera to jedna aplikacja.
No dobrze, ale czy w taki sposób można zatrzymać flow programu? Jak mówiłem, jak logika biznesowa robi trzy rzeczy, A, B, C, i z B poleci wyjątek, to nie chcę żeby C się zrobiło. Z tymi ewentami tak nie ma, rozumiem? Że wykonają się tak czy tak wszystkie, i musiałbym dodać jakiś inny mechanizm który by nie dopuścił żeby C się wykonało?
Tak jak pisałem - albo robimy tam jakieś Eithery i wtedy akcja "sama" się przewie bo jak masz jakieś validateAction().map(this::doX).map(this::doY)... to pierwszy Left sprawi że kolejne map czy flatMap się już nie wykonają, albo, tak jak pisałem, możesz rzucić sobie wyjątek jeśli bardzo chcesz, ale to tylko takie ułatwienie żeby "wyskoczyć" do samej góry wywołań i zwrócić jakiś error code.
No dobra, tylko wtedy te Eithery muszą przejść przez wszystkie warstwy, nie miałbym prostych metod które zwracają jedną wartość, tylko taki Either :/ Nie jestem pewien czy chciałbym mieć coś takiego w swojej logice biznesowej. Im bardziej skomplikowana logika biznesowa, tym taki either będzie bardziej skomplikowany. To tak na prawdę, gdyby takie potencjalne źródło problemu mogło wyjść z bardzo niskiego poziomu z logiki biznesowej, to to by znaczyło że praktycznie każda funkcja u mnie musiałaby zwracać Either. I'm not sure :/
Jeśli chcesz zakomunikować komponentom systemu, że "coś się stało" to powinieneś wygenerować sobie odpowiedni event i tyle.
No, tylko w sumie nie chcę tego robić. Chcę zastopować akcję, którą zrobił user/admin/cron, i dać możliwość callerowi zareagować na to.
Wysyłanie eventów IMO byłoby spoko, gdyby to były jakieś peryferia aplikacji (typu właśnie z web do kafki), ale w samej logice biznesowej to mi się wydaje bad idea.
No, nie, kafki w ogóle w to nie chcę mieszać, i nie chcę żeby inne serwisy handlowały ten wyjątek, tylko caller.
Jasne, teraz nie, ale sam pisałeś ze dochodzą ci kolejne "handlery". Nie zdziwi mnie jak pojawi sie wymaganie że jak user wykona nielegalną akcje, to taka informacja powinna zostać przesłana do jakiegoś serwisu security czy audit ;) Chciałem tylko pokazać że opcja z eventami nie ma takich mocnych ograniczeń jak to co teraz robisz.
No, jeśli zajdzie taka potrzeba, to eventy pewnie będą oczywistym wyjściem. Ale na razie nie ma.
Kolejny problem jaki widzę z tymi twoimi wyjątkami jest taki, ze ktoś ci moze ten wyjątek złapać, mniej lub bardziej przypadkiem, i nagle w ogóle te twoje handlery się nie odpalą. Ot głupi przykład to odpalenie czegoś w innym watku albo z jakiegoś CompletableFuture. Exlpicite emitowanie eventu jest dużo bardziej niezawodne.
No, niby tak, ale ten sam problem jest z Eitherami, ktoś go może przechwycić i zwrócić inny either.
Poza tym, jeśli jakiś caller sobie złapie ten wyjątek i nie puści go dalej, to znaczy że obsłużył już błąd i nie powinien być propagowany dalej, więc nie wiem czy to tak znowu źle. A jeśli mówisz o tym że w mojej logice biznesowej coś go złapie, i nie puści, to to znaczy że jest w niej bug, i unity to powinny wykryć IMO.
Skoro masz trzy aplikacje, każda inaczej obsługuje wyjątki, to oznacza 3 catche (po jednym w każdej aplikacji). Nie trzeba żadnych wzorców.
No ale to jest jedna aplikacja.
No, tak działa wizytor, prawda?
Owszem, w ten sposób działa, i przez to jest tak bardzo nieintuicyjny. :)
Dla mnie ma sens :D Może po prostu trzeba dobrze znać wzorce, a nie tylko o nich słyszeć kiedyś :D Joke. No offence.
To jest np to że user chce wywołać jakąś akcję, ale nie ma na tyle kredytów na swoim koncie, powiedzmy. Albo, jest limit na jakąś akcję do powiedzmy 3ech dziennie, a user chce zrobić coś 4ty raz tego dnia. Ewentualnie to może być coś w stylu, "wyślij wiadomość do mojego polecającego", ale akurat ten user nie ma polecającego.
Ja taką akcję teraz stopuję wyjątkiem NotEnoughCreditsException, ActionLimitReachedException oraz RootReferalException. Być może to jest to o czym mówisz, że to jest "event domenowy", tylko jak takim sposobem zatrzymać flow? Tak jak wyjątki zatrzymują unless caught?
W ogóle nie powinieneś zaczynać flow, skoro warunki nie są spełnione. Wtedy nie trzeba byłoby niczego przerywać wyjątkiem.
No ale to są case'y których nie da się/ciężko sprawdzić przed wywołaniem flow. To jest coś w stylu
Kopiuj
user.buyItem("Monitor");
...gdy nie wiemy ile user ma kasy i nie wiemy ile "Monitor" kosztuje, cała ta sprawdzajka dzieje się w środku logiki biznesowej. Żeby to sprawdzić zanim się ją zawoła, to trzebaby ją zduplikować w sumie.
Z punktu widzenia aplikacji - tak, normalne. Z punktu widzenia domeny biznesowej, nielegalna akcja IMO. Takie jest moje zdanie, nie chcę wchodzić w dyskusje na ten temat. Jakby, naturalne wydaje mi się że jak user chce coś kupić, ale nie ma kasy, to powinien dostać wyjątek (IMO!).
Wyjątek powinien dostać np., gdy mimo walidacji na każdym etapie będzie brakowało jakichś wymaganych danych, albo gdy utraci połączenie z bazą danych, a nie wtedy, gdy próbuje wykonać coś wbrew regułom biznesowym. To, że ludzie się mylą albo kombinują to nie jest nic wyjątkowego, to normalna i oczywista rzecz. Coś oczywistego nie może być jednocześnie wyjątkowe.
No tak, i takie sytuacje też są, i takie również chcę obsłużyć - tylko że inaczej dla różnych caller'ów (inaczej dla usera, dla admina i dla crona).