Np. ponowić wywołanie dla innych parametrów. Wydaje mi się, że po to przekazujemy w odpowiedzi informację o błędzie, żeby klient mógł z tym coś zrobić.
No ok, to od tego jest jakiś Match
, żeby można było także i błąd obsłużyć niby-funkcyjnie, albo IsError
, żeby użyć imperatywnie.
Ja takich akurat sytuacji nigdy nie miewam, bo ponawianie najczęściej robię wewnątrz klasy komunikującej się z jakimś API przy użyciu Polly, zanim jeszcze zwracam Result
.
Tak się zastanawiam, że jeśli mamy aplikację, w której jest jedynie kilka typów błędów mapowanych przez kontroler na odpowiedzi http (żaden serwis nic z tymi błędami nie robi, tylko przekazuje dalej), to jaka jest zaleta zwracania resultów nad rzucaniem wyjątków i łapaniem ich w filtrze?
Zwracany wynik to coś, co przewidziałeś, a wyjątek to coś, czego nie obsłużyłeś. Dla mnie osobiście jest bardzo istotne wiedzieć, z którą z tych sytuacji mam do czynienia, bo druga oznacza dodatkową, robotę, a pierwsza nie.
No właśnie ciekaw jestem, czy można mieć ładną obsługę błędów bez konieczności zmieniania paradygmatu całego systemu na funkcyjny.
Jak dla mnie to taki Result
z metodami pozwalającymi na wywoływanie łańcuchowe to nie jest zmiana paradygmatu. Dlatego właśnie nazywam go Result
, a nie Either
, żeby nikt nie zarzucał, że to nie jest programowanie funkcyjne, bo nie ma HKT i innych takich. Nawet nie nazwałbym tego luźną inspiracją.
Dla mnie jest wystarczająco dobre do moich potrzeb, jeśli ktoś potrzebuje więcej, to może faktycznie potrzeba zmienić paradygmat.
Hmm, ale naprawdę nie ma z takimi łańcuszkami żadnych problemów? Debuguje się to tak samo jak kod imperatywny?
No lambdy debugować można od dawna. A jak kodu jest dużo, to i tak lepiej nie robić długiej lambdy tylko metodę prywatną/funkcję anonimową.
Hmm, ale jeśli miałbym CustomerDao
, to jednak wolałbym zwrócić Option<Customer>
zamiast Result<Customer>
, gdzie Result
oprócz NotFound
zawiera też NotValid
czy Forbidden
:) Chociaż pewnie Result
będzie wystarczająco dobry.
No tak ideologicznie to pewnie masz rację. Tylko z drugiej strony, to może lepiej tych nullable reference types użyć?
Ogólnie wydaje mi się, że jak mamy więcej typów błędów do obsłużenia niż kilka, to trudno jest to zrobić w OOP. Jak jest kilka błędów, które po prostu przepychamy przez kilka warstw, to OK, ale jak jest tego więcej, to słabo to zaczyna wyglądać.
Nawet z przepychaniem przez warstwy to słabo wygląda, bo inferencja typów jest za słaba, a async
to w ogóle wszystko psuje. No moim zdaniem mimo wszystko jak się da uniknąć bezsensownych wyjątków i przydługawej ifologii, to jest lepiej. A trochę lepiej, to dużo lepiej niż trochę gorzej. :P