Czy wyłapywanie ogólnych wyjątków jest naprawdę złą rzeczą?

57

Zwykle zgadzam się z większością ostrzeżeń dotyczących analizy kodu i staram się ich przestrzegać. Mam jednak trudniejszy czas z tym:

CA1031: Nie przechwytuj ogólnych typów wyjątków

Rozumiem uzasadnienie tej reguły. Ale w praktyce, jeśli chcę podjąć to samo działanie niezależnie od zgłoszonego wyjątku, dlaczego miałbym obsługiwać każde z nich konkretnie? Co więcej, jeśli obsłużę określone wyjątki, co się stanie, jeśli kod, który wywołuję, zmieni się, aby wygenerować nowy wyjątek w przyszłości? Teraz muszę zmienić kod, aby obsłużyć ten nowy wyjątek. Natomiast jeśli po prostu złapię, Exceptionmój kod nie musi się zmienić.

Na przykład, jeśli Foo wywołuje Bar, a Foo musi przerwać przetwarzanie niezależnie od typu wyjątku zgłoszonego przez Bar, czy jest jakaś korzyść ze sprecyzowania rodzaju wyjątku, który łapię?

Może lepszy przykład:

public void Foo()
{
    // Some logic here.
    LogUtility.Log("some message");
}

public static void Log()
{
    try
    {
        // Actual logging here.
    }
    catch (Exception ex)
    {
        // Eat it. Logging failures shouldn't stop us from processing.
    }
}

Jeśli nie złapiesz tutaj ogólnego wyjątku, musisz złapać każdy możliwy wyjątek. Patrick ma rację, że OutOfMemoryExceptionnie powinno się z tym postępować w ten sposób. Co jeśli chcę zignorować każdy wyjątek, ale OutOfMemoryException?

Bob Horn
źródło
12
Co OutOfMemoryException? Taki sam kod obsługi jak wszystko inne?
Patrick,
@Patrick Dobry punkt. Dodałem nowy przykład do mojego pytania, aby opisać twoje pytanie.
Bob Horn,
1
Łapanie ogólnych wyjątków jest tak samo złe, jak składanie ogólnych oświadczeń o tym, co każdy powinien zrobić. Zasadniczo nie ma jednego uniwersalnego podejścia do wszystkiego.
4
@ Patryk, który byłby OutOfMemoryErroroddzielny od Exceptiondrzewa dziedziczenia z tego właśnie powodu
Darkhogg
Co z wyjątkami klawiatury, takimi jak Ctrl-Alt-Del?
Mawg

Odpowiedzi:

33

Zasady te są ogólnie dobrym pomysłem i dlatego należy ich przestrzegać.

Pamiętaj jednak, że są to ogólne zasady. Nie obejmują wszystkich sytuacji. Obejmują najczęstsze sytuacje. Jeśli masz konkretną sytuację i możesz argumentować, że twoja technika jest lepsza (i powinieneś być w stanie napisać komentarz w kodzie, aby wyrazić swój argument za to), to zrób to (a następnie sprawdź go).

Po przeciwnej stronie argumentu.

Nie uważam twojego powyższego przykładu za dobrą sytuację do tego. Jeśli system rejestrowania zawiedzie (prawdopodobnie rejestruje jakiś inny wyjątek), prawdopodobnie nie chcę, aby aplikacja była kontynuowana. Wyjdź i wydrukuj wyjątek na wyjściu, aby użytkownik mógł zobaczyć, co się stało.

Martin York
źródło
2
Zgodzić się. Na samym przynajmniej teraz, że regularne rejestrowanie jest nieaktywny zrobić jakiś przepis, że dam jakiś rodzaj wyjścia debugowania, na stderr jeśli nic innego.
Shadur
6
Poparłem was obu, ale myślę, że myślicie jak programiści, a nie użytkownicy. Użytkownik zasadniczo nie dba o to, czy rejestrowanie się dzieje, dopóki aplikacja jest użyteczna.
Mawg,
1
Ciekawe, ponieważ log4net wyraźnie nie chce zatrzymać aplikacji tylko dlatego, że logowanie nie powiedzie się. I myślę, że to zależy od tego, co logujesz; audyty bezpieczeństwa, oczywiście, zabijają proces. Ale dzienniki debugowania? Nie tak ważne.
Andy,
1
@Andy: Tak, wszystko zależy od tego, co robisz.
Martin York,
2
Dlaczego ich nie rozumiesz? A nie powinieneś starać się tego robić?
Mawg
31

Tak, łapanie ogólnych wyjątków to zła rzecz. Wyjątek zwykle oznacza, że ​​program nie może zrobić tego, o co go poprosiłeś.

Istnieje kilka typów wyjątków, które mogłyby obsługiwać:

  • Śmiertelne wyjątki : brak pamięci, przepełnienie stosu itp. Pewna nadprzyrodzona siła właśnie popsuła wszechświat i proces już umiera. Nie możesz poprawić sytuacji, więc się poddaj
  • Zgłoszono wyjątek, ponieważ błędy w używanym kodzie : Nie próbuj sobie z nimi radzić, a raczej napraw źródło problemu. Nie używaj wyjątków do kontroli przepływu
  • Wyjątkowe sytuacje : obsługuj wyjątki tylko w tych przypadkach. Możemy tu zaliczyć: kabel sieciowy odłączony, połączenie internetowe przestało działać, brakujące uprawnienia itp.

Aha, i jako ogólna zasada: jeśli nie wiesz, co zrobić z wyjątkiem, jeśli go złapiesz, lepiej po prostu szybko zawieść (przekaż wyjątek dzwoniącemu i pozwól mu to obsłużyć)

Victor Hurdugaci
źródło
1
Co z konkretnym przypadkiem w pytaniu? Jeśli w kodzie logowania jest błąd, prawdopodobnie zignoruj ​​wyjątek, ponieważ kod, który ma znaczenie, nie powinien mieć na niego wpływu.
svick,
4
Dlaczego zamiast tego nie naprawić błędu w kodzie logowania?
Victor Hurdugaci,
3
Victor, to chyba nie jest błąd. Jeśli na dysku, na którym znajduje się dziennik, zabraknie miejsca, to czy to błąd w kodzie logowania?
Carson63000,
4
@ Carson63000 - cóż, tak. Dzienniki nie są zapisywane, dlatego: błąd. Wdrożyć dzienniki obrotowe o stałym rozmiarze.
detly
5
To jest najlepsza odpowiedź imo, ale brakuje w niej jednego kluczowego aspektu: bezpieczeństwa . Istnieją pewne wyjątki, które występują w wyniku złych facetów próbujących udoskonalić twój program. Jeśli zostanie zgłoszony wyjątek, którego nie jesteś w stanie obsłużyć, niekoniecznie możesz już zaufać temu kodowi. Nikt nie lubi słyszeć, że napisali kod, który wpuszcza złych facetów.
riwalk
15

Najwyższa zewnętrzna pętla powinna mieć jedną z nich, aby wydrukować wszystko, co może, a następnie umrzeć straszliwą, gwałtowną i SZKODLIWĄ śmiercią (ponieważ to nie powinno się zdarzyć i ktoś musi to usłyszeć).

W przeciwnym razie na ogół powinieneś być bardzo ostrożny, ponieważ najprawdopodobniej nie przewidziałeś wszystkiego, co może się zdarzyć w tym miejscu, a zatem najprawdopodobniej nie potraktujesz go poprawnie. Bądź tak dokładny, jak to możliwe, aby złapać tylko tych, o których wiesz, że się zdarzy, i pozwól tym, których wcześniej nie widziałeś, wznieść się na wyżej wspomnianą głośną śmierć.


źródło
1
Teoretycznie zgadzam się z tym. Ale co z powyższym przykładem logowania? Co jeśli po prostu chcesz zignorować wyjątki rejestrowania i kontynuować? Czy musisz wychwycić każdy wyjątek, który można by zgłosić, i zająć się każdym z nich, pozwalając na poważniejszy wyjątek?
Bob Horn,
6
@BobHorn: Dwa sposoby patrzenia na to. Tak, możesz powiedzieć, że logowanie nie jest szczególnie ważne, a jeśli się nie powiedzie, nie powinno zatrzymać aplikacji. I to w porządku. Ale co się stanie, jeśli aplikacja nie będzie się logować przez pięć miesięcy i nie masz pojęcia? Widziałem, jak to się dzieje. A potem potrzebowaliśmy dzienników. Nieszczęście. Sugeruję zrobienie wszystkiego, co możesz wymyślić, aby zatrzymać rejestrowanie błędów, jest lepsze niż ignorowanie go, gdy to robi. (Ale nie osiągniesz większego konsensusu w tej sprawie.)
pdr
@pdr W moim przykładzie logowania zazwyczaj wysyłam powiadomienie e-mail. Lub mamy systemy do monitorowania dzienników, a jeśli dziennik nie jest aktywnie wypełniany, nasz zespół wsparcia otrzyma alert. W ten sposób dowiemy się o problemie z logowaniem na inne sposoby.
Bob Horn,
@BobHorn swój przykład rejestrowania jest raczej wymyślony - większość ram rejestrowania wiem, idź do wielkiego długości nie rzucać żadnych wyjątków i nie będzie wywoływany tak (jak to zrobić każdy „oświadczenie zalogować się na linii X w pliku Y” bezużyteczny )
@pdr Podniosłem pytanie na liście logback (Java), jak sprawić, aby środowisko rejestrowania zatrzymało aplikację, jeśli konfiguracja logowania się nie powiedzie, po prostu dlatego, że tak ważne jest, abyśmy mieli dzienniki, a każda cicha awaria jest nie do przyjęcia. Dobre rozwiązanie jest nadal w toku.
9

Nie jest tak, że jest źle, tylko że konkretne połowy są lepsze. Kiedy jesteś konkretny, oznacza to, że faktycznie, bardziej konkretnie, rozumiesz, co robi twoja aplikacja i masz nad nią większą kontrolę. Ogólnie rzecz biorąc, jeśli natkniesz się na sytuację, w której po prostu złapiesz wyjątek, zaloguj go i kontynuuj, prawdopodobnie i tak dzieje się prawdopodobnie kilka złych rzeczy. Jeśli wychwytujesz wyjątki, o których wiesz, że blok kodu lub metoda mogą generować, istnieje większe prawdopodobieństwo, że możesz je odzyskać zamiast rejestrować i mieć nadzieję na najlepsze.

Ryan Hayes
źródło
5

Dwie możliwości nie wykluczają się wzajemnie.

W idealnej sytuacji wychwyciłbyś wszystkie możliwe typy wyjątków, które twoja metoda mogłaby wygenerować, obsłużyłby je dla poszczególnych wyjątków, a na końcu dodałaby ogólną catchklauzulę, aby wychwycić wszelkie przyszłe lub nieznane wyjątki. W ten sposób uzyskasz to, co najlepsze z obu światów.

try
{
    this.Foo();
}
catch (BarException ex)
{
    Console.WriteLine("Foo has barred!");
}
catch (BazException ex)
{
    Console.WriteLine("Foo has bazzed!");
}
catch (Exception ex)
{
    Console.WriteLine("Unknown exception on Foo!");
    throw;
}

Pamiętaj, że aby uchwycić bardziej szczegółowe wyjątki, musisz je ustawić na pierwszym miejscu.

Edycja: Z powodów podanych w komentarzach dodano powtórkę w ostatnim połowie.

Rotem
źródło
2
Czekać. Dlaczego miałbyś kiedykolwiek chcieć zapisać nieznany wyjątek w konsoli i kontynuować? Jeśli jest to wyjątek, o którym nawet nie wiedziałeś, że może zostać zgłoszony przez kod, prawdopodobnie mówisz o awarii systemu. Kontynuacja tego scenariusza jest prawdopodobnie złym pomysłem.
pdr
1
@pdr Na pewno zdajesz sobie sprawę, że to wymyślony przykład. Chodziło o to, aby wykazać wyłapywanie zarówno szczególnych, jak i ogólnych wyjątków, a nie jak sobie z nimi radzić.
Rotem,
@Rotem Myślę, że masz tutaj dobrą odpowiedź. Ale pdr ma rację. Kod w obecnej postaci sprawia, że ​​wygląda na łapanie i kontynuowanie jest w porządku. Niektórzy początkujący, widząc ten przykład, mogą pomyśleć, że to dobre podejście.
Bob Horn,
Pomysłowy czy nie, sprawia, że ​​twoja odpowiedź jest zła. Gdy tylko zaczniesz wychwytywać wyjątki, takie jak brak pamięci i zapełnienie dysku, i po prostu je połykasz, udowadniasz, dlaczego wychwytywanie wyjątków ogólnych jest w rzeczywistości złe.
pdr
1
Jeśli złapiesz wyjątek ogólny tylko po to, aby go zarejestrować, powinieneś go ponownie po zalogowaniu.
Victor Hurdugaci,
5

Zastanawiałem się nad tym niedawno, a mój wstępny wniosek jest taki, że samo pytanie powstaje, ponieważ hierarchia wyjątków .NET jest poważnie zawalona.

Weźmy na przykład niski, ArgumentNullExceptionktóry może być rozsądnym kandydatem na wyjątek, którego nie chcesz wychwytywać, ponieważ zwykle wskazuje on na błąd w kodzie, a nie na uzasadniony błąd w czasie wykonywania. O tak. Tak samo NullReferenceException, z wyjątkiem tego, że NullReferenceExceptionpochodzi SystemExceptionbezpośrednio, więc nie ma segmentu, w którym można umieścić wszystkie „błędy logiczne”, aby je złapać (lub nie złapać).

Potem jest poważna robota IMNSHO polegająca na SEHExceptionwyprowadzeniu (via ExternalException), SystemExceptiona tym samym uczynieniu go „normalnym”.SystemException Kiedy dostajeszSEHException, chcesz napisać zrzut i zakończyć tak szybko, jak to możliwe - i zaczynając od .NET 4 przynajmniej niektóre Wyjątki SEH są uważane za wyjątki dotyczące stanu skorumpowanego , które nie zostaną wyłapane. To dobra rzecz i fakt, żeCA1031regułaczyni jąjeszcze bardziej bezużyteczną, ponieważ teraz leniwi icatch (Exception)tak nie złapią tych najgorszych typów.

Następnie wydaje się, że inne rzeczy z frameworka wywodzą się raczej niekonsekwentnie albo Exceptionbezpośrednio, albo za pośrednictwem SystemException, próbując pogrupować klauzule catch według czegoś w rodzaju ważności.

Jest taki kawałek C#sławy pana Lipperta , zatytułowany Vexing Exception , w którym wyróżnia kilka użytecznych kategoryzacji wyjątków: Można argumentować, że chcesz złapać tylko te „egzogeniczne”, z wyjątkiem… C#języka i wyglądu .NET wyjątki ramowe uniemożliwiają „złapanie tylko egzogennych” w zwięzły sposób. (i np. bardzo dobrzeOutOfMemoryException może być całkowicie normalnym, możliwym do odzyskania błędem dla interfejsu API, który musi przydzielić bufory, które są w jakiś sposób duże)

Najważniejsze dla mnie jest to, że sposób C#działania bloków przechwytujących i sposób projektowania hierarchii wyjątków Framework, zasada CA1031jest całkowicie bezużyteczna . To udaje się pomóc w wydaniu głównym „nie połykać wyjątki”, ale połykania wyjątków ma zero do czynienia z tym, co można złapać, ale z tego, co wtedy zrobić:

Istnieją co najmniej 4 sposoby legalnej obsługi złapanego Exceptioni CA1031wydaje się, że powierzchownie obsługuje tylko jeden z nich (mianowicie przypadek ponownego rzucenia).


Na marginesie, istnieje funkcja C # 6 o nazwie Filtry wyjątków, która sprawi, że będą CA1031nieco bardziej poprawne, ponieważ od tego momentu będziesz w stanie poprawnie, poprawnie, odpowiednio odfiltrować wyjątki, które chcesz złapać, i jest mniej powodów, aby pisać niefiltrowane catch (Exception).

Martin Ba
źródło
1
Poważny problem OutOfMemoryExceptionpolega na tym, że nie ma dobrego sposobu, aby kod był pewien, że „tylko” oznacza awarię określonego przydziału, dla którego przygotowano błąd. Możliwe, że został zgłoszony inny poważniejszy wyjątek i OutOfMemoryExceptionwystąpił podczas odwijania stosu od tego innego wyjątku. Java mogła spóźnić się na imprezę ze swoimi „próbami z zasobami”, ale obsługuje wyjątki podczas rozwijania stosu nieco lepiej niż .NET.
supercat
1
@supercat - to prawda, ale jest tak w zasadzie w przypadku każdego innego ogólnego wyjątku systemowego, gdy coś się psuje w dowolnym końcu bloku.
Martin Ba
1
To prawda, ale można (i ogólnie należy) chronić finallybloki przed wyjątkami, których realistycznie można się spodziewać w taki sposób, że zarówno oryginalne, jak i nowe wyjątki zostaną zarejestrowane. Niestety robienie tego często wymaga alokacji pamięci, co może powodować własne awarie.
supercat
4

Obsługa wyjątków Pokemon (muszę złapać je wszystkie!) Z pewnością nie zawsze jest zła. Udostępniając metodę klientowi, a zwłaszcza użytkownikowi końcowemu, często lepiej jest złapać wszystko i wszystko, niż spowodować awarię i nagrywanie aplikacji.

Ogólnie jednak należy ich unikać tam, gdzie to możliwe. O ile nie możesz podjąć konkretnych działań w zależności od rodzaju wyjątku, lepiej nie obsługiwać go i pozwolić, aby wyjątek się rozwinął, a następnie połknąć wyjątek lub nieprawidłowo go obsłużyć.

Wystarczy popatrzeć na to SO odpowiedzieć więcej czytania.

Tom Squires
źródło
1
Ta sytuacja (gdy programista musi być trenerem Pokemon) pojawia się, gdy sam tworzysz całe oprogramowanie: tworzysz warstwy, połączenia z bazą danych i GUI użytkownika. Twoja aplikacja musi się zregenerować po utracie łączności, usunięciu folderu użytkownika, uszkodzeniu danych itp. Użytkownicy końcowi nie lubią aplikacji, które ulegają awarii i nagrywają się. Lubią aplikacje, które mogą działać na płonącym, eksplodującym komputerze ulegającym awarii!
Broken_Window
Do tej pory o tym nie myślałem, ale w Pokemonach ogólnie zakłada się, że „złap je wszystkie” chcesz dokładnie jednego z nich i musisz poradzić sobie ze złapaniem go dokładnie, co jest przeciwieństwem powszechnego użycia tego wyrażenia wśród programistów.
Mag
2
@Magus: Przy pomocy metody podobnej LoadDocument()do niemożliwej jest zidentyfikowanie wszystkich rzeczy, które mogą pójść nie tak, ale 99% wyjątków, które można by zgodzić, oznacza po prostu: „Nie można interpretować zawartości pliku o podanej nazwie jako dokument; załatw go. ” Jeśli ktoś spróbuje otworzyć coś, co nie jest prawidłowym plikiem dokumentu, nie powinno to spowodować awarii aplikacji i zabić żadnych innych otwartych dokumentów. Obsługa błędów pokemonów w takich przypadkach jest brzydka, ale nie znam dobrych alternatyw.
supercat
@ superupat: Właśnie mówiłem o języku. Nie sądzę jednak, aby nieprawidłowa zawartość pliku brzmiała jak coś, co powinno wywołać więcej niż jeden rodzaj wyjątku.
Mag
1
@Magus: Może generować różnego rodzaju wyjątki - to jest problem. Często bardzo trudno jest przewidzieć wszelkiego rodzaju wyjątki, które mogą zostać zgłoszone w wyniku nieprawidłowych danych w pliku. Jeśli nie używa się obsługi PokeMon, ryzykuje się śmiercią aplikacji, ponieważ np. Ładowany plik zawierał wyjątkowo długi ciąg cyfr w miejscu, które wymagało 32-bitowej liczby całkowitej w formacie dziesiętnym, a w wyniku logika analizy.
supercat,
1

Złapanie ogólnego wyjątku jest złe, ponieważ pozostawia program w nieokreślonym stanie. Nie wiesz, gdzie coś poszło nie tak, więc nie wiesz, co twój program faktycznie zrobił lub czego nie zrobił.

Pozwoliłbym złapać wszystko podczas zamykania programu. Tak długo, jak możesz to wyczyścić w porządku. Nic tak irytującego jak program, który zamykasz, który po prostu wyświetla okno dialogowe błędu, które nic nie robi, tylko siedzieć tam, nie odchodząc i uniemożliwiając zamknięcie komputera.

W środowisku rozproszonym metoda dziennika może się nie udać: wyłapanie ogólnego wyjątku może oznaczać, że program nadal blokuje plik dziennika, uniemożliwiając innym użytkownikom tworzenie dzienników.

Pieter B.
źródło
0

Rozumiem uzasadnienie tej reguły. Ale w praktyce, jeśli chcę podjąć to samo działanie niezależnie od zgłoszonego wyjątku, dlaczego miałbym obsługiwać każde z nich konkretnie?

Jak powiedzieli inni, naprawdę trudno jest (jeśli nie niemożliwe) wyobrazić sobie jakąś akcję, którą chciałbyś podjąć niezależnie od zgłoszonego wyjątku. Tylko jeden z przykładów są sytuacje, w których stan Program został uszkodzony i dowolne dalsze przetwarzanie może prowadzić do problemów (jest to uzasadnienie Environment.FailFast).

Co więcej, jeśli obsłużę określone wyjątki, co się stanie, jeśli kod, który wywołuję, zmieni się, aby wygenerować nowy wyjątek w przyszłości? Teraz muszę zmienić kod, aby obsłużyć ten nowy wyjątek. Natomiast jeśli po prostu złapałem wyjątek, mój kod nie musi się zmieniać.

W przypadku kodu hobby dobrze jest go złapać Exception, ale w przypadku kodu klasy profesjonalnej wprowadzenie nowego typu wyjątku powinno być traktowane z takim samym szacunkiem, jak zmiana podpisu metody, tj. Być traktowane jako zmiana przełomowa. Jeśli zasubskrybujesz ten punkt widzenia, natychmiast stanie się oczywiste, że powrót do zmiany (lub weryfikacji) kodu klienta jest jedynym prawidłowym działaniem.

Na przykład, jeśli Foo wywołuje Bar, a Foo musi przerwać przetwarzanie niezależnie od typu wyjątku zgłoszonego przez Bar, czy jest jakaś korzyść ze sprecyzowania rodzaju wyjątku, który łapię?

Jasne, bo nie będziesz wychwytywał tylko wyjątków Bar. Będą również wyjątki, które klienci Bar, a nawet środowisko wykonawcze mogą zgłaszać w czasie, który Barjest na stosie wywołań. Dobrze napisany Barpowinien zdefiniować własny typ wyjątku, jeśli to konieczne, aby osoby dzwoniące mogły dokładnie wychwycić wyjątki emitowane przez siebie.

Co jeśli chcę zignorować każdy wyjątek oprócz OutOfMemoryException?

IMHO to zły sposób myślenia o obsłudze wyjątków. Powinieneś działać na białych listach (łapanie typów wyjątków A i B), a nie na czarnych listach (łap wszystkie wyjątki oprócz X).

Jon
źródło
Często można określić akcję, która powinna zostać wykonana dla wszystkich wyjątków wskazujących, że próba operacji zakończyła się niepowodzeniem bez efektu ubocznego i / lub niekorzystnego wpływu na stan systemu. Na przykład, jeśli użytkownik wybierze plik dokumentu do załadowania, program przekazuje swoją nazwę do metody „utwórz obiekt dokumentu z danymi z pliku dyskowego”, a metoda ta zawiedzie z określonego powodu, którego aplikacja nie spodziewała się (ale który spełnia powyższe kryteria), właściwym zachowaniem powinno być wyświetlanie komunikatu „Nie można załadować dokumentu” zamiast awarii aplikacji.
supercat
Niestety nie ma standardowych środków, za pomocą których wyjątek może wskazywać najważniejszą rzecz, którą kod klienta chciałby wiedzieć - czy sugeruje coś złego w stanie systemu poza tym, co wynikałoby z niemożności wykonania żądanej operacji. Tak więc, mimo że sytuacje, w których wszystkie wyjątki powinny być obsługiwane, są rzadkie, istnieje wiele sytuacji, w których wiele wyjątków powinno być traktowanych w ten sam sposób, i nie ma żadnego kryterium, które byłyby spełnione przez wszystkie takie wyjątki, byłyby również spełnione przez niektóre rzadkie, które należy traktować inaczej.
supercat
0

Może . Istnieją wyjątki od każdej reguły i żadnej zasady nie należy bezwzględnie przestrzegać. Przykład może być jednym z przypadków, w których sensowne jest połknięcie wszystkich wyjątków. Na przykład, jeśli chcesz dodać śledzenie do krytycznego systemu produkcyjnego i chcesz mieć absolutną pewność, że zmiany nie zakłócają głównego zadania aplikacji.

Jednakże , należy dokładnie przemyśleć temat możliwych przyczyn awarii, zanim zdecydujesz się cicho zignorować je wszystkie. Na przykład, co jeśli przyczyną wyjątku jest:

  • błąd programowania w metodzie rejestrowania, który powoduje, że zawsze wyrzuca określony wyjątek
  • niepoprawna ścieżka do pliku rejestrowania w konfiguracji
  • dysk jest pełny

Czy nie chcesz natychmiast otrzymywać powiadomień o tym problemie, aby go naprawić? Połknięcie wyjątku oznacza, że ​​nigdy nie wiesz, że coś poszło nie tak.

Niektóre problemy (takie jak dysk jest pełny) mogą również powodować awarie innych części aplikacji - ale ta awaria nie jest teraz rejestrowana, więc nigdy nie wiadomo!

JacquesB
źródło
0

Chciałbym zająć się tym z logicznej perspektywy, a nie technicznej,

Teraz muszę zmienić kod, aby obsłużyć ten nowy wyjątek.

Cóż, ktoś musiałby sobie z tym poradzić. To jest pomysł. Autorzy kodu bibliotecznego byliby ostrożni w dodawaniu nowych typów wyjątków, ponieważ ponieważ może to zepsuć klientów, nie powinieneś się z tym często spotykać.

Twoje pytanie brzmi: „Co, jeśli nie obchodzi mnie, co poszło nie tak? Czy naprawdę muszę się męczyć, aby dowiedzieć się, co to było?”

Oto część piękna: nie, nie.

„Czy mogę po prostu spojrzeć w drugą stronę i sprawić, by cokolwiek paskudnego wyskoczyło automatycznie pod dywan i skończyło się na tym?”

Nie, to też tak nie działa.

Chodzi o to, że zbiór możliwych wyjątków jest zawsze większy niż zbiór, którego oczekujesz i interesuje Cię kontekst małego lokalnego problemu. Radzisz sobie z tymi, których spodziewasz się, a jeśli wydarzy się coś nieoczekiwanego, pozostawiasz to handlerom wyższego poziomu, zamiast je połykać. Jeśli nie obchodzi Cię wyjątek, którego się nie spodziewałeś, zakładasz się, że ktoś podniesie stos wywołań, a zabicie wyjątku przed dotarciem do niego byłoby sabotażem.

„Ale… ale… to jeden z tych innych wyjątków, na których mi nie zależy, może spowodować, że moje zadanie się nie powiedzie!”

Tak. Ale zawsze będą ważniejsze niż te obsługiwane lokalnie. Jak alarm przeciwpożarowy lub szef mówi ci, abyś przestał robić i wybierał pilniejsze zadanie, które się pojawiło.

Martin Maat
źródło
-3

Powinieneś wychwycić ogólne wyjątki na najwyższym poziomie każdego procesu i obsłużyć go, zgłaszając błąd tak dobrze, jak to możliwe, a następnie kończąc proces.

Nie należy wychwytywać ogólnych wyjątków i próbować kontynuować wykonywanie.

ddyer
źródło