Podczas analizowania danych wejściowych od użytkownika ogólnie zaleca się, aby nie zgłaszać wyjątków i wychwytywać wyjątki, ale raczej stosować metody sprawdzania poprawności. W .NET BCL byłaby to różnica między, na przykład int.Parse
(zgłasza wyjątek w przypadku nieprawidłowych danych) i int.TryParse
(zwraca false
w przypadku nieprawidłowych danych).
Projektuję własne
Foo.TryParse(string s, out Foo result)
i nie jestem pewien co do wartości zwracanej. Mógłbym użyć bool
własnej TryParse
metody .NET , ale nie dałoby to żadnego wskazania na temat rodzaju błędu, ani o dokładny powód, dla s
którego nie można go przeanalizować jako Foo
. (Na przykład s
może mieć niedopasowany nawias, niewłaściwą liczbę znaków lub znak „ Bar
bez” Baz
itp.)
Jako użytkownik interfejsów API zdecydowanie nie lubię metod, które zwracają tylko logiczne powodzenie / niepowodzenie, nie mówiąc mi, dlaczego operacja się nie powiodła. To sprawia, że debugowanie jest zgadywaniem i nie chcę narzucać tego również klientom mojej biblioteki.
Mogę wymyślić wiele obejść tego problemu (zwracaj kody stanu, zwracaj ciąg błędów, dodaj ciąg błędów jako parametr wyjściowy), ale wszystkie mają swoje wady, a także chcę pozostać zgodny z konwencjami .NET Framework .
Zatem moje pytanie jest następujące:
Czy w systemie .NET Framework istnieją metody, które (a) analizują dane wejściowe bez zgłaszania wyjątków i (b) nadal zwracają bardziej szczegółowe informacje o błędach niż zwykły logiczny prawda / fałsz?
źródło
Parse()
.Odpowiedzi:
Polecam użycie wzorca monady jako typu zwrotu.
ParseResult<Foo> foo = FooParser.Parse("input");
Należy również pamiętać, że Foo nie powinno być odpowiedzialne za ustalenie, w jaki sposób należy je przeanalizować z danych wejściowych użytkownika, ponieważ bezpośrednio wiąże to warstwę domeny z warstwą interfejsu użytkownika, a także narusza zasadę pojedynczej odpowiedzialności.
W
Foo
zależności od przypadku użycia można także ustawić klasę wyników analizy jako specyficzną dla zamiast używać ogólnych.Specjalna klasa wyników analizy składni foo może wyglądać mniej więcej tak:
Oto wersja Monady:
Nie znam żadnych metod w .NET, które zwracają szczegółowe informacje o błędach analizy.
źródło
Foo.ToString
iFoo.Parse
.Func<T>
, spełniałaby te kryteria, jeśli podasz wymaganeT
informacje. Zwracanie szczegółowych informacji o błędach zależy w dużej mierze od Ciebie. Czy zastanawiałeś się nad użyciemMaybe<T>
? Zobacz mikhail.io/2016/01/monads-explained-in-csharpMożesz spojrzeć na ModelState w frameworku MVC. Reprezentuje próbę parsowania niektórych danych wejściowych i może zawierać zbiór błędów.
To powiedziawszy, nie sądzę, że istnieje powtarzający się wzorzec tego w .net BCL, ponieważ wyjątki to - na lepsze lub gorsze - ustalony wzorzec zgłaszania błędów w .net. Myślę, że powinieneś po prostu wdrożyć własne rozwiązanie odpowiadające Twojemu problemowi, na przykład
ParseResult
klasę z dwiema podklasamiSuccessfulParse
iFailedParse
gdzieSuccessfulParse
ma właściwość z przeanalizowaną wartością iFailedParse
właściwość komunikatu o błędzie. Połączenie tego z dopasowaniem wzoru w C # 7 może być dość eleganckie.źródło
Mam podobne problemy z chęcią skorzystania z
TryParse/Convert/etc.
metody, w której czasami muszę wiedzieć, jak i dlaczego zawiodła.Zacząłem czerpać inspirację z tego, jak niektóre serializatory radzą sobie z błędami i wykorzystują zdarzenia. W ten sposób składnia mojej
TryX(..., out T)
metody wygląda tak samo czysto jak każda inna i niezawodnie zwraca prostą,false
jak sugeruje wzorzec.Jednak gdy chcę potrzebować więcej szczegółów, po prostu dodaję moduł obsługi zdarzeń i uzyskuję potrzebne wyniki w pakiecie tak złożonym lub prostym, jak chcę (
MyEventArgs
poniżej). Dodaj go do listy ciągów, dodajExceptionDispatchInfo
i przechwyć wyjątki; pozwól dzwoniącemu zdecydować, czy i jak chce poradzić sobie ze wszystkim, co pójdzie nie tak.źródło