Dlaczego powinienem pisać wszystkie wyciągi w ramach Try-Catch?

12

Szef mojej firmy mówi, że muszę napisać wszystko, tj. CAŁY mój kod w instrukcjach Try-catch. Teraz rozumiem podejście „lepiej bądź bezpieczny niż żałuj” tutaj, ale czy to nie jest zbyt serdeczne myślenie, że będzie wyjątek podczas tworzenia Etykiet, pozycja formularza jest ustalona. zdarzały się przypadki wyjątków w tak prostych operacjach.

Cypr
źródło
4
To brzmi jak warunki buzz przez te same osoby, które mówią, że wszystkie SQL powinny być zapisywane jako procedury składowane dla lepszej wydajności.
gąbka
5
Czy wolisz: „Jeśli Twój kod powoduje błąd w czasie wykonywania, jesteś zwolniony”. Gra w kurczaka jest fajna, dopóki nie zobaczysz, jak przeciwnik rzuca kierownicą i pedał hamulca przez okno.
JeffO,
4
@Jeff O - Właściwie uważam, że w rozwoju oprogramowania przeciwnikiem jest pociąg towarowy.
Joris Timmermans,
5
Najlepszym wyrażeniem, jakie słyszałem w tym stylu obsługi wyjątków jest „Przybicie zwłok w pozycji pionowej”, co oznacza, że ​​pozostawia aplikację w nieoczekiwanym stanie. Fail Fast, Fail Loudly to znacznie nowocześniejsze podejście, więc możesz naprawdę rozwiązać wszystkie błędy.
Brook
2
Temat wniosku jest nieistotny ... samo powiedzenie „szef mojej firmy mówi, że powinienem kodować ...” to duża czerwona flaga. To mikrozarządzanie ... to nie jest jego praca.
JoelFan

Odpowiedzi:

14

Szef mojej firmy mówi, że muszę napisać wszystko, tj. CAŁY mój kod w instrukcjach Try-catch.

Jest to trochę przesadzone i po prostu prowadzi do hałaśliwego kodu. Jakie są korzyści z posiadania całego kodu (np. Każdej metody) w programie obsługi catch try? Mówi tylko, że w większości przypadków istnieje błąd do naprawienia. Często wyjątek można i należy przede wszystkim unikać.

Spojrzenie na ślad stosu jest w większości wystarczające, aby ujawnić przyczynę w kodzie, nawet jeśli metoda powodująca błąd nie wykonuje samego przechwytywania. Są chwile, kiedy programiści niszczą ślady stosu w wyjątkach, ale o wiele częściej ma to miejsce, gdy masz wiele programów obsługi wyjątków. Jak wszystko: trochę jest dobre, ale za dużo to trucizna.

Obsługa wyjątków jest rzeczywiście bardzo prosta:

Wyjątki połowowe

  • ilekroć potrzebujesz specjalnej akcji w reakcji na wyjątek
  • za każdym razem, gdy wyjątek pozostawiłby program w niespójnym stanie, gdyby nie został obsłużony

Jeśli się nad tym zastanowić, to najczęściej jest tylko jedno miejsce, w którym można poradzić sobie z występującym wyjątkiem. I tak przewodnik powinien być w tym miejscu.

Wiele wyjątków nie powinno nawet być rzucanych w pierwszej kolejności, więc nie buduj struktur kontrolnych wokół obsługi wyjątków, raczej staraj się unikać możliwego występowania wyjątków zawsze i wszędzie, gdzie to możliwe.

Pamiętaj, aby wcześnie upaść, gdy coś pójdzie (nieodwracalnie) źle. Umieszczenie całego kodu w instrukcjach try-catch jest absurdalne, ale nie zapomnij zgłosić i zapisać WSZYSTKICH wyjątków.

Sokół
źródło
+1 prowadzi nie tylko do hałaśliwego kodu, ale nawet do gorszej wydajności. Gdy umieścisz instrukcje w bloku try, kompilator HotSpot nie będzie w stanie zastosować optymalizacji, które zrobiłby inaczej.
Oliver Weiler,
@Oliver Weiler: Czy masz cytat wyjaśniający, jakich optymalizacji kompilator HotSpot nie robi w blokach try / catch?
Kaypro II,
16

ale czy nie jest to zbyt serdeczne, aby myśleć, że będzie wyjątek podczas tworzenia Etykiet, pozycja formularza jest ustalona. zdarzały się przypadki wyjątków w tak prostych operacjach.

Absolutnie tak! Zawsze jest coś, co może pójść źle, czego nie przewidziałeś. „Kurczak-serce” to absurdalne wyrażenie, którego można użyć w tym kontekście; rozwój oprogramowania nie polega na udowodnieniu swojego machismo poprzez ignorowanie potencjalnych problemów.

Co jest ważne pytanie o to, czy jest to przydatne dla wyjątki być złapany w miejscu gdzie standardy kodowania powiedzieć muszą. Twoje stwierdzenie brzmi tak, jakbyś musiał zablokować try / catch wokół każdego elementu metody, co jest absurdalne, ponieważ często nie można od razu zrobić czegoś użytecznego z wyjątkiem, i to jest cały sedno wyjątków: że możesz pozwolić im rozpropaguj stos wywołań w odpowiednim miejscu.

Michael Borgwardt
źródło
13
Moje aplikacje wiedzą, że nie należy rzucać wyjątków, bo inaczej pobiją ich życie. Gdy pomyślą, że masz serce kurze, rozbiją się na tobie.
JeffO,
@Michael Borgwardt: hehe, więc oddałeś mi głos. Głosowałeś w dół na to pytanie, a jedyny głos jest w moim poście. Wygląda na to, że masz poważny problem ze swoim ego lub poczuciem własnej wartości. Zauważyłem to również w innych pytaniach. Wiesz, inni programiści też mają dobre odpowiedzi.
Falcon
@ Falcon: Nie głosowałem nic na to pytanie. Nie mam pojęcia, co prowadzi cię do przekonania, że ​​jest inaczej, ale jeśli ktoś ma poważny problem z ego, to ty.
Michael Borgwardt,
@Michael Borwardt: Może się mylę. W takim razie przepraszam. Może to być tylko głosowanie na twoje własne pytanie, które spowodowało, że pomyślałem, że głosowałeś tutaj. Przepraszam.
Falcon
8

Odwróciłbym to na odwrót. Tak, ogólnie rzecz biorąc, obsługa wyjątków jest dobrą rzeczą, ale czy faktycznie możesz właściwie obsłużyć każdy możliwy wyjątek w miejscu, w którym został on złapany? Czasami, szczególnie jeśli nie piszesz o znaczeniu krytycznym oprogramowania, to jest lepiej po prostu rozbić i spalić w pewnym połowie drogi sterowany sposób, gdy coś idzie strasznie źle.

Jeśli nie możesz być w 100% pewien, że poradzisz sobie z każdym wyjątkiem, który może zostać złapany, prawdopodobnie lepiej jest napisać jakąś ogólną procedurę obsługi wyjątków, owijając w nią główną pętlę programu - dokładną mechanikę tego, jak to zrobić, oczywiście zależy od tego, w jakim języku pracujesz. Tam zapisz jak najwięcej szczegółów na temat wyjątku, zapisz stan programu (gdzieś indziej niż w jakimkolwiek magazynie danych, w którym użytkownik aktualnie pracuje - pamiętaj, że w tym momencie wszystko może być uszkodzone ), i tak dalej. Następnie zwróć wyjątek i pozwól systemowi operacyjnemu obsłużyć go w dowolny sposób. W tym uniwersalnym module obsługi wyjątków przygotuj się na katastrofalną awarię. Następnie, po ponownym uruchomieniu programu, sprawdź, czy ten stan jest w jakikolwiek sposób użyteczny, i przywróć to, co można uratować, jeśli jest; i ewentualnie zaoferować użytkownikowi odesłanie do ciebie raportu o błędzie.

CVn
źródło
5
+1: Nigdy nie wychwytuj wyjątku, jeśli nie możesz od razu poprawnie go rozwiązać. (Niestety, czasami trzeba go złapać w pułapkę, aby pozwolić mu ponownie wędrować, ale oznaczono go jako inny typ, w ramach wymuszania interfejsu API: Nienawidzę tego.)
Donal Fellows
6

Ogólnie rzecz biorąc, użycie metody try / catch jest przestarzałe, ponieważ blok catch jest tak drogi z punktu widzenia zasobów. Wykorzystanie try / catch przypomina mi zarządzanie ryzykiem . Zarządzanie ryzykiem ma dwa wymiary:

  1. Prawdopodobieństwo wystąpienia ryzyka
  2. Szkody, jakie może mieć

Teraz, jeśli wyjdziesz z domu, fortepian spadnie gdzieś na głowę, podczas gdy jest tak mało prawdopodobne (może 0,001%), ale może cię zabić.

Tak wygląda obsługa wyjątków. Blok próbny nie jest drogi. Ale catch block jest naprawdę drogi, ponieważ musi stworzyć tabelę śledzenia stosu i robić inne rzeczy. Dlatego podejmując decyzję o blokach try / catch, powinieneś rozważyć, ile razy prawdopodobnie trafiłeś w blok catch. Jeśli spośród 10 000 zastosowań trafisz go tylko raz, użyj go. Ale jeśli jest to formularz, a użytkownik prawdopodobnie nie wypełnia go poprawnie 50% razy, powinieneś unikać wykonywania tam bloku try / catch.

W miejscach, w których prawdopodobieństwo wystąpienia wyjątku jest wysokie, zaleca się stosowanie if {} else {}bloków, aby uniknąć wystąpienia wyjątku. Na przykład, gdzie chcesz podzielić dwie liczby zamiast pisać:

try
{
    int result = a/b;
}
catch (DivisionByZeroException ex)
{
    // Showing a message here, and logging of course.
}

powinieneś napisać:

if (b == 0)
{
    int result = a/b;
}
else
{
    // Showing a message to user to change the value of b, etc.
}
Saeed Neamati
źródło
2
+1 za używanie if / else do radzenia sobie z „wyjątkami”, które są po prostu logiką aplikacji.
Morgan Herlocker
Jeśli jest to związane z użytkownikiem, pamiętaj, że komputery są znacznie szybsze niż ludzie. Wyjątek zgłoszony w 50% przesłanych formularzy prawdopodobnie zdarza się tylko kilka razy na sekundę, nawet w przypadku wielu użytkowników.
Donal Fellows,
1
Nie zgadzam się z tobą w kwestii unikania bloków try / catch. Ciągłe próby przewidywania wyjątków są podatne na błędy, drogie w czasie programowania i utrudniają odczytanie kodu. Pętla, która zgłasza milion wyjątków i je łapie, zajmuje 500 ms na uruchomienie na moim komputerze (w porównaniu z 1 ms dla pustej pętli), co nie jest rzeczywistą różnicą wydajności w 99,99% przypadków (i całego kodu interfejsu użytkownika). Powinieneś stosować wyjątki, z wyjątkiem przypadków, w których wiesz, że liczy się kara za wydajność, ponieważ zwiększają one niezawodność twojego kodu i pozwalają założyć, że poprzedni kod został wykonany pomyślnie.
Kaypro II,
@ cosmic.osmo, czy pobierasz ślad stosu, czy po prostu go łapiesz?
3

W razie potrzeby powinieneś użyć try-catch, ale proszę, nie wychwytuj wszystkich wyjątków, a nawet nie rejestruj. W tym momencie jest to zapach kodu i tandetna praca.

ist_lion
źródło
1
+1 za logowanie. Programy na wolności to czarne skrzynki. Gdy zawiodą, dziennik z napisem „Oto, co się stało” bardzo pomaga rozwiązać problem. Mam błędy w moich programach, które nie zostały zgłoszone, i zostały wykryte dopiero po ich znalezieniu w dzienniku.
Andrew Neely,
2

Osobiście nie znoszę wyjątków, są one BARDZO, BARDZO, BARDZO trudne do prawidłowego obchodzenia się. A próba odkrycia uszkodzonych danych jest BARDZO, BARDZO, BARDZO trudna!

http://blogs.msdn.com/b/mgrier/archive/2004/02/18/75324.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx

http://www.joelonsoftware.com/items/2003/10/13.html

Jeśli nie wywołujesz wszystkich funkcji, takich jak:

try
{
    TrivialFunction();
}
catch(TypeAException)
{
    //MaybeFix
}
catch(TypeBException)
{
    //MaybeFix
}
catch(TypeCException)
{
    //NO FIX - CORRUPT DATA
}
catch(TypeDException)
{
    //NO FIX - UNKNOWN STATE
}
catch(OutOfMemoryException)
{
    //Try to fix this one! Destructors might allocate on their own ;)
}
catch(Exception)
{
    //Nothing to see here, move on, everything is OK ;)
}

Nie ma możliwości prawidłowego czyszczenia w każdym punkcie wyjścia. Wyjątki są trudne!

Jedyną dobrą rzeczą w wyjątkach jest to, że jeśli ich nie złapiesz, aplikacja zawiesza się w wyniku nieoczekiwanego zachowania.

Koder
źródło