Mam wyjątki utworzone dla każdego warunku, którego moja aplikacja nie oczekuje. UserNameNotValidException
, PasswordNotCorrectException
Itd.
Powiedziano mi jednak, że nie powinienem tworzyć wyjątków od tych warunków. W moim UML TO SĄ wyjątki od głównego przepływu, więc dlaczego nie miałby to być wyjątek?
Wszelkie wskazówki lub najlepsze praktyki dotyczące tworzenia wyjątków?
exception
language-agnostic
Kwan Cheng
źródło
źródło
IsCredentialsValid(username,password)
nie powinna zgłaszać wyjątku, jeśli nazwa użytkownika lub hasło są nieprawidłowe, ale zwraca wartość false. Ale powiedzmy, że metoda, która odczytuje dane z bazy danych, może legalnie wyrzucić taki wyjątek, jeśli uwierzytelnienie się nie powiedzie. W skrócie: Powinieneś zgłosić wyjątek, jeśli metoda nie jest w stanie wykonać zadania, które powinna wykonać.Odpowiedzi:
Moja osobista wytyczna: wyjątek jest zgłaszany, gdy fundamentalne założenie dotyczące obecnego bloku kodu jest fałszywe.
Przykład 1: powiedz, że mam funkcję, która ma badać dowolną klasę i zwraca true, jeśli klasa ta dziedziczy z List <>. Ta funkcja zadaje pytanie: „Czy ten obiekt jest potomkiem Listy?” Ta funkcja nigdy nie powinna zgłaszać wyjątku, ponieważ w jej działaniu nie ma szarych obszarów - każda pojedyncza klasa dziedziczy z Listy <>, więc odpowiedź zawsze brzmi „tak” lub „nie”.
Przykład 2: powiedz, że mam inną funkcję, która bada listę <> i zwraca true, jeśli jej długość jest większa niż 50, i false, jeśli długość jest mniejsza. Ta funkcja zadaje pytanie: „Czy ta lista zawiera więcej niż 50 pozycji?” Ale to pytanie przyjmuje założenie - zakłada, że obiekt, który mu podano, jest listą. Jeśli podam mu wartość NULL, to założenie jest fałszywe. W takim przypadku, jeśli funkcja zwraca albo prawdziwe albo fałszywe, to łamie własne zasady. Funkcja nie może niczego zwrócić i twierdzi, że poprawnie odpowiedziała na pytanie. Więc nie wraca - zgłasza wyjątek.
Jest to porównywalne z logicznym błędem „załadowanego pytania” . Każda funkcja zadaje pytanie. Jeśli podane dane wejściowe sprawiają, że to pytanie jest błędne, należy zgłosić wyjątek. Ta linia jest trudniejsza do narysowania za pomocą funkcji, które zwracają wartość void, ale dolna linia jest następująca: jeśli założenia funkcji dotyczące jej danych wejściowych zostaną naruszone, powinna ona wygenerować wyjątek zamiast normalnego powrotu.
Drugą stroną tego równania jest: jeśli często zdarza się, że funkcje generują wyjątki, prawdopodobnie trzeba doprecyzować ich założenia.
źródło
Ponieważ są to rzeczy, które będą się normalnie dziać. Wyjątkami nie są mechanizmy kontroli przepływu. Użytkownicy często mylą hasła, nie jest to wyjątkowy przypadek. Wyjątki powinny być naprawdę rzadkie,
UserHasDiedAtKeyboard
sytuacje typowe.źródło
Na moje małe wytyczne duży wpływ ma wspaniała książka „Kod zakończony”:
źródło
NIE jest wyjątkiem, jeśli nazwa użytkownika jest niepoprawna lub hasło jest nieprawidłowe. Tego należy się spodziewać w normalnym trybie pracy. Wyjątkami są rzeczy, które nie są częścią normalnego działania programu i są raczej rzadkie.
EDYCJA: Nie lubię używać wyjątków, ponieważ nie można stwierdzić, czy metoda zgłasza wyjątek, patrząc tylko na wywołanie. Właśnie dlatego wyjątków należy używać tylko wtedy, gdy nie da się poradzić sobie z sytuacją w przyzwoity sposób (pomyśl „brak pamięci” lub „komputer się pali”).
źródło
Jedną z praktycznych zasad jest stosowanie wyjątków w przypadku czegoś, czego normalnie nie można przewidzieć. Przykładami są połączenia z bazą danych, brakujący plik na dysku itp. W przypadku scenariuszy, które można przewidzieć, np. Użytkownicy próbujący zalogować się przy użyciu złego hasła, powinieneś używać funkcji zwracających wartości logiczne i wiedzieć, jak z wdzięcznością poradzić sobie z sytuacją. Nie chcesz nagle przerywać wykonywania, zgłaszając wyjątek tylko dlatego, że ktoś pomylił hasło.
źródło
Inni sugerują, że nie należy stosować wyjątków, ponieważ złego logowania należy się spodziewać w normalnym przepływie, jeśli użytkownik pomyli się. Nie zgadzam się i nie rozumiem. Porównaj go z otwarciem pliku. Jeśli plik nie istnieje lub z jakiegoś powodu nie jest dostępny, środowisko zgłosi wyjątek. Zastosowanie powyższej logiki było błędem firmy Microsoft. Powinny zwrócić kod błędu. To samo dotyczy analizowania, żądań internetowych itp. Itp.
Nie uważam złego logowania za część normalnego przepływu, jest wyjątkowy. Zwykle użytkownik wpisuje poprawne hasło, a plik istnieje. Wyjątkowe przypadki są wyjątkowe i można w nich doskonale zastosować wyjątki. Komplikowanie kodu przez propagowanie zwracanych wartości przez n poziomów w górę stosu jest marnotrawstwem energii i spowoduje bałagan w kodzie. Zrób najprostszą rzecz, która może działać. Nie przedwcześnie optymalizuj przy użyciu kodów błędów, rzadko zdarza się wyjątkowa sytuacja, a wyjątki nic nie kosztują, chyba że je wyrzucisz.
źródło
login
metody typu może być niepoprawne hasło, może być ono faktycznie użyte do ustalenia tego i nie chciałby mieć wyjątku w tym przypadku; podczas gdy wfile open
scenariuszu typu, który ma określony pożądany wynik - jeśli system nie jest w stanie dostarczyć wyniku z powodu niepoprawnych parametrów wejściowych lub jakiegoś czynnika zewnętrznego, jest to całkowicie logiczne zastosowanie wyjątku.Wyjątki są dość kosztownym efektem, jeśli na przykład masz użytkownika, który podaje nieprawidłowe hasło, zazwyczaj lepiej jest przekazać flagę błędu lub inny wskaźnik, że jest on nieprawidłowy.
Wynika to ze sposobu, w jaki obsługiwane są wyjątki, naprawdę złych danych wejściowych i unikalnych elementów zatrzymania krytycznego powinny być wyjątki, ale nie informacje o niepowodzeniu logowania.
źródło
Myślę, że powinieneś rzucić wyjątek tylko wtedy, gdy nie możesz nic zrobić, aby wyjść z obecnego stanu. Na przykład, jeśli przydzielasz pamięć, ale nie masz nic do przydzielenia. W przypadkach, o których wspominasz, możesz wyraźnie odzyskać te stany i odpowiednio zwrócić kod błędu z powrotem do dzwoniącego.
Zobaczysz wiele porad, w tym w odpowiedziach na to pytanie, że należy wprowadzać wyjątki tylko w „wyjątkowych” okolicznościach. Wydaje się to pozornie uzasadnione, ale jest błędną radą, ponieważ zastępuje jedno pytanie („kiedy powinienem rzucić wyjątek”) innym subiektywnym pytaniem („co jest wyjątkowego”). Zamiast tego postępuj zgodnie z radą Herb Sutter (dla C ++, dostępną w artykule Dr Dobbs Kiedy i jak korzystać z wyjątków , a także w jego książce z Andrei Alexandrescu, Standardy kodowania C ++ ): zrzuć wyjątek, jeśli i tylko jeśli
Dlaczego to jest lepsze? Czy to nie zastępuje pytania kilkoma pytaniami o warunki wstępne, warunki dodatkowe i niezmienniki? Jest to lepsze z kilku powiązanych powodów.
throw
jest szczegółowa. Zmusza nas to do pamiętania, że musimy rozważyć projekt i jego wdrożenie osobno, a naszym zadaniem przy wdrażaniu metody jest stworzenie czegoś, co spełnia ograniczenia projektowe.catch
klauzul.źródło
Powiedziałbym, że nie ma twardych i szybkich zasad określających, kiedy należy stosować wyjątki. Istnieją jednak dobre powody, aby z nich korzystać lub nie:
Powody korzystania z wyjątków:
Powody, dla których nie należy używać wyjątków:
Ogólnie rzecz biorąc, byłbym bardziej skłonny do stosowania wyjątków w Javie niż w C ++ lub C #, ponieważ jestem zdania, że wyjątek, zadeklarowany lub nie, jest zasadniczo częścią formalnego interfejsu funkcji, ponieważ zmiana gwarancji wyjątku może zerwać kod wywoławczy. Największą zaletą korzystania z nich w Javie IMO jest to, że wiesz, że Twój rozmówca MUSI obsłużyć wyjątek, a to zwiększa szansę na prawidłowe zachowanie.
Z tego powodu w każdym języku zawsze czerpałbym wszystkie wyjątki w warstwie kodu lub interfejsu API ze wspólnej klasy, aby kod wywołujący zawsze gwarantował wychwycenie wszystkich wyjątków. Również uważam, że źle jest rzucać klasy wyjątków, które są specyficzne dla implementacji, podczas pisania interfejsu API lub biblioteki (tj. Zawijanie wyjątków z niższych warstw, aby wyjątek otrzymany przez program wywołujący był zrozumiały w kontekście interfejsu).
Zauważ, że Java rozróżnia wyjątki ogólne i wyjątki wykonawcze, ponieważ nie trzeba ich deklarować. Używałbym klas wyjątków środowiska wykonawczego tylko wtedy, gdy wiesz, że błąd jest wynikiem błędu w programie.
źródło
Klasy wyjątków są jak „normalne” klasy. Tworzysz nową klasę, gdy „jest” innym typem obiektu, z różnymi polami i różnymi operacjami.
Zasadniczo należy wypróbować równowagę między liczbą wyjątków a ich szczegółowością. Jeśli twoja metoda generuje więcej niż 4-5 różnych wyjątków, możesz prawdopodobnie połączyć niektóre z nich w bardziej „ogólne” wyjątki (np. W twoim przypadku „AuthenticationFailedException”) i użyć komunikatu wyjątku, aby szczegółowo opisać, co poszło nie tak. O ile Twój kod nie obsługuje każdego z nich inaczej, nie musisz tworzyć wielu klas wyjątków. A jeśli tak, to powinieneś po prostu zwrócić wyliczenie z wystąpieniem błędu. W ten sposób jest trochę czystszy.
źródło
Jeśli kod działa w pętli, co prawdopodobnie spowoduje ciągły wyjątek, wówczas generowanie wyjątków nie jest dobrą rzeczą, ponieważ są one dość powolne dla dużych N. Jednak nie ma nic złego w rzucaniu niestandardowych wyjątków, jeśli wydajność nie jest problem. Upewnij się tylko, że masz podstawowy wyjątek, który wszyscy dziedziczą, o nazwie BaseException lub coś w tym rodzaju. BaseException dziedziczy System.Exception, ale wszystkie wyjątki dziedziczą BaseException. Możesz nawet mieć drzewo typów wyjątków, aby pogrupować podobne typy, ale może to być lub nie przesada.
Krótka odpowiedź brzmi więc, że jeśli nie spowoduje to znacznego ograniczenia wydajności (czego nie powinno, chyba że wprowadzisz wiele wyjątków), to idź dalej.
źródło
int.MaxValue
i generujący w niej wyjątek „dziel przez zero”. Wersja IF / ELSE, w której sprawdzałem, czy dywidenda nie jest zerowa przed operacją podziału , ukończona w 6082 ms i 15407722 zaznacza, podczas gdy wersja TRY / CATCH, w której generowałem wyjątek i łapałem wyjątek , ukończona w 28174385 ms i 71371326155 tyka: aż 4632 razy więcej niż wersja if / else.Zgadzam się z tam japollock - wyślij akceptację, gdy nie masz pewności co do wyniku operacji. Połączenia z interfejsami API, dostęp do systemów plików, połączenia z bazami danych itp. Za każdym razem, gdy przekraczasz „granice” języków programowania.
Chciałbym dodać, możesz rzucić standardowy wyjątek. Chyba że masz zamiar zrobić coś „innego” (zignoruj, wyślij e-mailem, zaloguj, pokaż, że twitter wieloryb jest podobny, itp.), To nie przejmuj się niestandardowymi wyjątkami.
źródło
ogólna zasada rzucania wyjątków jest dość prosta. robisz to, gdy Twój kod wejdzie w stan NIEODWRACALNY NIEPRAWIDŁOWY. jeśli dane zostaną naruszone lub nie możesz wycofać przetwarzania, które nastąpiło do tego momentu, musisz je zakończyć. co właściwie możesz zrobić? Twoja logika przetwarzania ostatecznie zawiedzie gdzie indziej. jeśli możesz jakoś odzyskać, zrób to i nie wyrzucaj wyjątków.
w twoim szczególnym przypadku, jeśli zostałeś zmuszony zrobić coś głupiego, na przykład zaakceptować wypłatę pieniędzy, a dopiero potem sprawdzić użytkownika / hasło, powinieneś zakończyć proces, zgłaszając wyjątek, aby powiadomić, że stało się coś złego i zapobiec dalszym szkodom.
źródło
Ogólnie rzecz biorąc, chcesz zgłosić wyjątek dla wszystkiego, co może się zdarzyć w Twojej aplikacji, co jest „Wyjątkowe”
W twoim przykładzie oba wyjątki wyglądają tak, jakbyś do nich dzwonił poprzez sprawdzenie poprawności hasła / nazwy użytkownika. W takim przypadku można argumentować, że tak naprawdę nie jest wyjątkowe, że ktoś pomyliłby nazwę użytkownika / hasło.
Są to „wyjątki” od głównego przepływu twojego UML, ale są bardziej „gałęziami” w przetwarzaniu.
Jeśli próbowałeś uzyskać dostęp do pliku passwd lub bazy danych i nie mógłbyś tego zrobić, byłby to wyjątkowy przypadek i uzasadniałby zgłoszenie wyjątku.
źródło
Po pierwsze, jeśli użytkownicy Twojego interfejsu API nie są zainteresowani konkretnymi, drobnoziarnistymi awariami, to posiadanie określonych wyjątków dla nich nie ma żadnej wartości.
Ponieważ często nie jest możliwe ustalenie, co może być przydatne dla użytkowników, lepszym podejściem jest posiadanie określonych wyjątków, ale upewnienie się, że dziedziczą one od wspólnej klasy (np. Std :: wyjątek lub jego pochodne w C ++). To pozwala Twojemu klientowi wyłapać określone wyjątki, jeśli tak zdecydują, lub bardziej ogólny wyjątek, jeśli ich to nie obchodzi.
źródło
Wyjątki są przeznaczone dla zdarzeń, które są nietypowymi zachowaniami, błędami, awariami itp. Zachowanie funkcjonalne, błąd użytkownika itp. Powinny być obsługiwane przez logikę programu. Ponieważ złe konto lub hasło są oczekiwaną częścią logiki w procedurze logowania, powinno być w stanie poradzić sobie z tymi sytuacjami bez wyjątków.
źródło
Mam filozoficzne problemy z używaniem wyjątków. Zasadniczo spodziewasz się wystąpienia określonego scenariusza, ale zamiast jawnego radzenia sobie z nim, odsuwasz problem, aby zająć się nim „gdzie indziej”. I gdzie to „gdzie indziej” może się domyślić.
źródło
Powiedziałbym, że ogólnie każdy fundamentalizm prowadzi do piekła.
Na pewno nie chciałbyś skończyć z przepływem opartym na wyjątkach, ale unikanie wyjątków jest również złym pomysłem. Musisz znaleźć równowagę między obiema metodami. Nie chciałbym stworzyć typu wyjątku dla każdej wyjątkowej sytuacji. To nie jest produktywne.
Generalnie wolę stworzyć dwa podstawowe typy wyjątków, które są używane w całym systemie: LogicalException i TechnicalException . W razie potrzeby można je dalej rozróżnić według podtypów, ale generalnie nie jest to konieczne.
Wyjątek techniczny oznacza naprawdę nieoczekiwany wyjątek, taki jak niedziałający serwer bazy danych, połączenie z usługą internetową spowodowało wyjątek IOException i tak dalej.
Z drugiej strony, logiczne wyjątki są wykorzystywane do propagowania mniej poważnej błędnej sytuacji do górnych warstw (ogólnie niektóre wyniki sprawdzania poprawności).
Należy pamiętać, że nawet wyjątek logiczny nie jest przeznaczony do regularnego używania do kontrolowania przebiegu programu, ale raczej do podkreślenia sytuacji, w której przepływ powinien się naprawdę skończyć. W Javie oba typy wyjątków są podklasami RuntimeException, a obsługa błędów jest wysoce zorientowana na aspekty.
Dlatego w przykładzie logowania rozsądne może być utworzenie czegoś takiego jak AuthenticationException i rozróżnienie konkretnych sytuacji według wartości wyliczeniowych, takich jak UsernameNotExisting , PasswordMismatch itp. Wtedy nie skończysz z ogromną hierarchią wyjątków i możesz utrzymać bloki catch na utrzymywalnym poziomie. . Możesz także z łatwością zastosować ogólny mechanizm obsługi wyjątków, ponieważ masz skategoryzowane wyjątki i dość dobrze wiesz, co i jak przekazać do użytkownika.
Nasze typowe użycie polega na zgłoszeniu wyjątku LogicalException podczas wywołania usługi sieci Web, gdy dane wejściowe użytkownika są nieprawidłowe. Wyjątek zostaje przydzielony do szczegółów SOAPFault, a następnie ponownie zostaje usunięty z wyjątku na kliencie, co powoduje wyświetlenie błędu sprawdzania poprawności w jednym polu wejściowym określonej strony internetowej, ponieważ wyjątek ma odpowiednie odwzorowanie na to pole.
Z pewnością nie jest to jedyna sytuacja: nie musisz uruchamiać usługi internetowej, aby zgłosić wyjątek. Możesz to zrobić w każdej wyjątkowej sytuacji (na przykład w przypadku awarii w trybie awaryjnym) - wszystko zależy od ciebie.
źródło
dla mnie wyjątek powinien zostać zgłoszony w przypadku niepowodzenia wymaganej reguły technicznej lub biznesowej. na przykład, jeśli jednostka samochodu jest powiązana z tablicą 4 opon ... jeśli jedna lub więcej opon jest pustych ... należy zwolnić wyjątek „NotEnoughTiresException”, ponieważ można go złapać na innym poziomie systemu i mieć znaczny czyli poprzez logowanie. poza tym, jeśli tylko spróbujemy kontrolować przepływ zerowy i zapobiegać instynktowi samochodu. możemy nigdy nie znaleźć źródła problemu, ponieważ opona nie powinna być zerowa.
źródło
głównym powodem unikania zgłaszania wyjątku jest to, że generowanie wyjątku wiąże się z dużym nakładem pracy.
W poniższym artykule stwierdzono, że wyjątek dotyczy wyjątkowych warunków i błędów.
Zła nazwa użytkownika niekoniecznie jest błędem programu, ale błędem użytkownika ...
Oto dobry punkt wyjścia do wyjątków w .NET: http://msdn.microsoft.com/en-us/library/ms229030(VS.80).aspx
źródło
Zgłaszanie wyjątków powoduje, że stos się odpręża, co ma pewien wpływ na wydajność (przyznaje się, że nowoczesne środowiska zarządzane poprawiły to). Ciągle powtarzanie i łapanie wyjątków w sytuacji zagnieżdżonej byłoby złym pomysłem.
Prawdopodobnie ważniejsze niż to, wyjątki dotyczą wyjątkowych warunków. Nie należy ich używać do zwykłego przepływu sterowania, ponieważ wpłynie to na czytelność kodu.
źródło
Mam trzy rodzaje warunków, które łapię.
Złe lub brakujące dane wejściowe nie powinny być wyjątkiem. Użyj zarówno wyrażeń regularnych po stronie klienta, jak i wyrażenia regularnego po stronie serwera, aby wykrywać, ustawiać atrybuty i przekazywać wiadomości z powrotem do tej samej strony.
AppException. Jest to zwykle wyjątek wykrywany i wprowadzany do kodu. Innymi słowy, są to te, których oczekujesz (plik nie istnieje). Zaloguj się, ustaw komunikat i przejdź z powrotem do strony ogólnego błędu. Ta strona zazwyczaj zawiera trochę informacji o tym, co się stało.
Nieoczekiwany wyjątek. To są te, o których nie wiesz. Zaloguj się ze szczegółami i prześlij je na stronę ogólnego błędu.
Mam nadzieję że to pomoże
źródło
Bezpieczeństwo jest powiązane z twoim przykładem: nie powinieneś informować atakującego, że istnieje nazwa użytkownika, ale hasło jest nieprawidłowe. To dodatkowe informacje, których nie musisz udostępniać. Po prostu powiedz „nazwa użytkownika lub hasło są nieprawidłowe”.
źródło
Prosta odpowiedź brzmi: ilekroć operacja jest niemożliwa (z powodu dowolnej aplikacji LUB z powodu naruszenia logiki biznesowej). Jeśli metoda jest wywoływana i nie można zrobić tego, co metoda została napisana, wykonaj wyjątek. Dobrym przykładem jest to, że konstruktory zawsze zgłaszają wyjątki ArgumentException, jeśli instancji nie można utworzyć przy użyciu podanych parametrów. Innym przykładem jest InvalidOperationException, który jest zgłaszany, gdy operacja nie może zostać wykonana z powodu stanu innego członka lub członków klasy.
W twoim przypadku, jeśli wywoływana jest metoda taka jak Login (nazwa użytkownika, hasło), jeśli nazwa użytkownika jest niepoprawna, to rzeczywiście poprawne jest wygenerowanie UserNameNotValidException lub PasswordNotCorrectException, jeśli hasło jest niepoprawne. Nie można się zalogować przy użyciu dostarczonych parametrów (tj. Jest to niemożliwe, ponieważ naruszyłoby to uwierzytelnianie), więc zgłoś wyjątek. Chociaż mogę mieć dwa wyjątki dziedziczone z ArgumentException.
Powiedziawszy to, jeśli nie chcesz zgłaszać wyjątku, ponieważ niepowodzenie logowania może być bardzo częste, jedną ze strategii jest utworzenie metody zwracającej typy reprezentujące różne niepowodzenia. Oto przykład:
Większość programistów uczy się unikać wyjątków ze względu na narzut związany z ich rzucaniem. Wspaniale jest być świadomym zasobów, ale zwykle nie kosztem projektowania aplikacji. To prawdopodobnie powód, dla którego kazano ci nie rzucać dwoma wyjątkami. To, czy użyć wyjątków, czy nie, zwykle sprowadza się do częstotliwości występowania wyjątku. Jeśli jest to dość powszechny lub dość oczekiwany wynik, wtedy większość programistów uniknie wyjątków i zamiast tego stworzy inną metodę sygnalizowania niepowodzenia z powodu domniemanego zużycia zasobów.
Oto przykład unikania używania wyjątków w scenariuszu opisanym właśnie przy użyciu wzorca Try ():
źródło
Moim zdaniem fundamentalnym pytaniem powinno być to, czy można oczekiwać, że osoba dzwoniąca będzie chciała kontynuować normalny przebieg programu, jeśli wystąpi jakiś warunek. Jeśli nie wiesz, albo masz oddzielne metody doSomething i trySomething, przy czym pierwsza zwraca błąd, a druga nie, lub procedurę, która akceptuje parametr wskazujący, czy wyjątek powinien zostać zgłoszony, jeśli się nie powiedzie. Rozważ klasę, która wysyła polecenia do zdalnego systemu i zgłasza odpowiedzi. Niektóre polecenia (np. Restart) powodują, że system zdalny wysyła odpowiedź, ale przez pewien czas nie reaguje. Przydaje się zatem możliwość wysłania polecenia „ping” i sprawdzenia, czy zdalny system zareaguje w rozsądnym czasie bez konieczności zgłaszania wyjątku, jeśli nie „ t (osoba dzwoniąca prawdopodobnie oczekiwałaby, że pierwsze kilka prób „pingowania” zakończy się niepowodzeniem, ale w końcu jedna zadziała). Z drugiej strony, jeśli ktoś ma sekwencję poleceń takich jak:
chciałoby się, aby żadna operacja nie przerwała całej sekwencji. Chociaż można sprawdzić każdą operację, aby upewnić się, że się powiodła, bardziej pomocne jest, aby procedura exchange_command () zgłaszała wyjątek, jeśli polecenie się nie powiedzie.
W rzeczywistości w powyższym scenariuszu pomocne może być posiadanie parametru do wyboru wielu trybów obsługi awarii: nigdy nie zgłaszaj wyjątków, zgłaszaj wyjątki tylko w przypadku błędów komunikacji lub zgłaszaj wyjątki w przypadkach, gdy polecenie nie zwróci „sukcesu” „wskazanie.
źródło
„PasswordNotCorrectException” nie jest dobrym przykładem użycia wyjątków. Należy się spodziewać, że użytkownicy błędnie podają swoje hasła, więc nie jest to wyjątek IMHO. Prawdopodobnie nawet możesz się z niego zregenerować, wyświetlając ładny komunikat o błędzie, więc jest to tylko sprawdzenie poprawności.
Nieobsługiwane wyjątki ostatecznie zatrzymają wykonanie - co jest dobre. Jeśli zwracasz kody false, null lub error, musisz samodzielnie zająć się stanem programu. Jeśli zapomnisz sprawdzić gdzieś warunki, Twój program może nadal działać z nieprawidłowymi danymi i możesz mieć trudności z ustaleniem, co się stało i gdzie .
Oczywiście możesz wywoływać ten sam problem z pustymi instrukcjami catch, ale przynajmniej ich wykrycie jest łatwiejsze i nie wymaga zrozumienia logiki.
Zasadniczo:
Używaj ich tam, gdzie nie chcesz lub po prostu nie możesz naprawić błędu.
źródło
Możesz użyć trochę ogólnych wyjątków dla tych warunków. Na przykład ArgumentException ma być stosowany, gdy coś pójdzie nie tak z parametrami metody (z wyjątkiem ArgumentNullException). Zasadniczo nie potrzebujesz wyjątków, takich jak LessThanZeroException, NotPrimeNumberException itp. Pomyśl o użytkowniku swojej metody. Liczba warunków, które konkretnie będzie chciała obsłużyć, jest równa liczbie typów wyjątków, które twoja metoda musi zgłosić. W ten sposób możesz określić, jak szczegółowe będą wyjątki.
Nawiasem mówiąc, zawsze staraj się zapewnić użytkownikom bibliotek pewne sposoby na uniknięcie wyjątków. TryParse jest dobrym przykładem, istnieje, więc nie musisz używać int.Parse i wychwytywać wyjątek. W twoim przypadku możesz podać pewne metody, aby sprawdzić, czy nazwa użytkownika jest poprawna lub hasło jest prawidłowe, aby Twoi użytkownicy (lub Ty) nie musieli wykonywać wielu wyjątków. Miejmy nadzieję, że spowoduje to bardziej czytelny kod i lepszą wydajność.
źródło
Ostatecznie decyzja sprowadza się do tego, czy bardziej przydatne jest radzenie sobie z błędami na poziomie aplikacji, takimi jak ta, za pomocą obsługi wyjątków, czy za pomocą własnego mechanizmu domowego, takiego jak zwracanie kodów stanu. Nie sądzę, żeby istniała twarda i szybka zasada, która jest lepsza, ale rozważyłbym:
źródło
Istnieją dwie główne klasy wyjątków:
1) Wyjątek systemowy (np. Utrata połączenia z bazą danych) lub 2) Wyjątek użytkownika. (np. sprawdzanie poprawności przez użytkownika, „hasło jest nieprawidłowe”)
Uznałem, że pomocne jest utworzenie własnej klasy wyjątków użytkownika, a kiedy chcę zgłosić błąd użytkownika, chcę być traktowany inaczej (tj. Błąd zasobów wyświetlany użytkownikowi), wtedy wszystko, co muszę zrobić w mojej głównej procedurze obsługi błędów, to sprawdzić typ obiektu :
źródło
Kilka przydatnych rzeczy do przemyślenia przy podejmowaniu decyzji, czy wyjątek jest odpowiedni:
jaki poziom kodu chcesz uruchomić po wystąpieniu kandydata na wyjątek - to znaczy ile warstw stosu wywołań powinno się rozwinąć. Zasadniczo chcesz obsłużyć wyjątek jak najbliżej miejsca jego wystąpienia. W przypadku sprawdzania poprawności nazwy użytkownika / hasła normalnie radzisz sobie z awariami w tym samym bloku kodu, a nie pozwalasz na pojawienie się wyjątku. Dlatego wyjątek prawdopodobnie nie jest odpowiedni. (OTOH, po trzech nieudanych próbach logowania przepływ kontroli może się przenieść w inne miejsce, a tutaj może być odpowiedni wyjątek).
Czy to zdarzenie jest czymś, co chciałbyś zobaczyć w dzienniku błędów? Nie każdy wyjątek jest zapisywany w dzienniku błędów, ale warto zapytać, czy ten wpis w dzienniku błędów byłby przydatny - tzn. Spróbowałbyś coś z tym zrobić, czy też byłby śmieciem, który ignorujesz.
źródło