Dlaczego wiele komunikatów o wyjątkach nie zawiera przydatnych informacji?


220

Wydaje się, że istnieje pewna zgoda co do tego, że komunikaty o wyjątkach powinny zawierać przydatne szczegóły .

Dlaczego wiele typowych wyjątków od składników systemu nie zawiera użytecznych szczegółów?

Kilka przykładów:

  • NET Listdostęp wskaźnik ArgumentOutOfRangeExceptionnie nie mów mi, że wartość indeksu został osądzony i był nieprawidłowy, ani nie mów mi dozwolony zakres.
  • Zasadniczo wszystkie komunikaty wyjątków ze standardowej biblioteki MSVC C ++ są całkowicie bezużyteczne (w takim samym brzmieniu jak powyżej).
  • Wyjątki Oracle w .NET, mówiąc (sparafrazowane) „TABELA LUB WIDOK nie znaleziono”, ale nie który .

Wydaje mi się więc, że komunikaty wyjątków w przeważającej części nie zawierają wystarczających szczegółów, aby były przydatne. Czy moje oczekiwania nie są zgodne? Czy źle stosuję wyjątki, że to zauważam? A może moje wrażenie jest błędne: większość wyjątków czy rzeczywiście dostarczyć użytecznych szczegółów?


59
Należy zauważyć, że ze strony specjalistów ds. Bezpieczeństwa „komunikaty o błędach nie powinny zawierać żadnych szczegółów na temat wewnętrznych elementów systemu” to ogólna zasada.
Telastyn

118
@Telastyn: Tylko jeśli twój system jest otwarty dla atakujących. Na przykład, jeśli korzystasz z serwera WWW, chcesz wyświetlać użytkownikom końcowym nijakie komunikaty o błędach, ale nadal chcesz otrzymywać bardzo szczegółowe komunikaty o błędach na końcu. A w oprogramowaniu klienckim, w którym użytkownik nie jest atakującym, zdecydowanie chcesz, aby te komunikaty o błędach były tak szczegółowe, jak to możliwe, aby gdy coś poszło nie tak i wysłano Ci raport o błędzie, masz tyle informacji do pracy jak to możliwe, ponieważ wiele razy to wszystko, co dostajesz.
Mason Wheeler,

9
@Snowman: Co jest niedostępne dla użytkownika, jeśli jest to oprogramowanie po stronie klienta? Właściciel maszyny jest właścicielem maszyny i może dostać się do wszystkiego.
Mason Wheeler,


6
Zawsze są jakieś dodatkowe informacje, które chciałbyś mieć. Uważam, że wiadomości, które podajesz za przykłady, są całkiem dobre. Możesz z nimi debugować problem. Znacznie lepiej niż „błąd 0x80001234” (przykład inspirowany Windows Update).
usr

Odpowiedzi:


204

Wyjątki nie zawierają użytecznych szczegółów, ponieważ koncepcja wyjątków nie jest jeszcze wystarczająco dojrzała w dyscyplinie inżynierii oprogramowania, więc wielu programistów nie rozumie ich w pełni, a zatem nie traktuje ich odpowiednio.

Tak, IndexOutOfRangeExceptionpowinien zawierać dokładny indeks, który był poza zakresem, a także zakres, który był ważny w momencie jego wyrzucenia, i jest to godne pogardy dla twórców środowiska uruchomieniowego .NET, że tak nie jest. Tak, table or view not foundwyjątek Oracle powinien zawierać nazwę tabeli lub widoku, która nie została znaleziona, i ponownie fakt, że nie jest to godne pogardy dla każdego, kto jest za to odpowiedzialny.

W dużej mierze zamieszanie wynika z błędnego pierwotnego pomysłu, że wyjątki powinny zawierać wiadomości czytelne dla człowieka, co z kolei wynika z niezrozumienia, o co chodzi w wyjątkach, więc jest to błędne koło.

Ponieważ ludzie uważają, że wyjątek powinien zawierać komunikat czytelny dla człowieka, uważają, że wszelkie informacje przenoszone przez wyjątek powinny być również sformatowane w komunikacie czytelnym dla człowieka, a następnie albo znudzeni są pisaniem całej wiadomości czytelnej dla człowieka budowanie kodu lub obawiają się, że może to ujawnić niewskazaną ilość informacji wszystkim wścibskim oczom, którzy mogą zobaczyć wiadomość. (Problemy bezpieczeństwa wymienione w innych odpowiedziach).

Ale prawda jest taka, że ​​nie powinni się tym martwić, ponieważ wyjątek nie powinien zawierać przesłania czytelnego dla człowieka. Wyjątki to rzeczy, które tylko programiści powinni widzieć i / lub sobie z nimi radzić. Jeśli kiedykolwiek istnieje potrzeba przedstawienia użytkownikowi informacji o awarii, należy to zrobić na bardzo wysokim poziomie, w wyrafinowany sposób oraz w języku użytkownika, który, statystycznie rzecz biorąc, prawdopodobnie nie jest angielskim.

Zatem dla nas, programistów, „komunikat” wyjątku jest nazwą klasy wyjątku i wszelkie inne informacje dotyczące wyjątku powinny zostać skopiowane do (końcowych / tylko do odczytu) zmiennych składowych obiektu wyjątku. Najlepiej, jeśli jest to możliwe. W ten sposób żadna wiadomość nie musi (lub powinna) zostać wygenerowana i dlatego żadne wścibskie oczy nie mogą jej zobaczyć.

Aby rozwiązać problem wyrażony przez Thomasa Owensa w komentarzu poniżej:

Tak, oczywiście, na pewnym poziomie, to będzie tworzyć wiadomości dziennika dotyczące wyjątku. Ale już widzisz problem z tym, co mówisz: z jednej strony komunikat dziennika wyjątków bez śladu stosu jest bezużyteczny, ale z drugiej strony nie chcesz, aby użytkownik widział cały ślad stosu wyjątków. Ponownie naszym problemem jest to, że nasza perspektywa jest wypaczona przez tradycyjne praktyki. Pliki dziennika były tradycyjnie zwykłym tekstem, co mogło być w porządku, gdy nasza dyscyplina była w powijakach, ale być może już nie: jeśli istnieje obawa o bezpieczeństwo, plik dziennika musi być binarny i / lub szyfrowany.

Niezależnie od tego, czy jest to tekst binarny, czy zwykły, plik dziennika należy traktować jako strumień, w którym aplikacja serializuje informacje debugowania. Taki strumień byłby tylko dla programistów, a zadanie generowania informacji debugowania dla wyjątku powinno być tak proste, jak serializacja wyjątku do strumienia dziennika debugowania. W ten sposób, patrząc na dziennik, zobaczysz nazwę klasy wyjątku (która, jak już wspomniałem, jest dla wszystkich praktycznych celów „komunikatem”), każdą zmienną składową wyjątku, która opisuje wszystko, co jest istotne - oraz -praktyczne do włączenia do dziennika i śledzenia całego stosu. Zwróć uwagę, że w tym procesie wyraźnie brakuje formatowania czytelnego dla człowieka komunikatu o wyjątku .

PS

Jeszcze kilka moich przemyśleń na ten temat można znaleźć w odpowiedzi: Jak napisać dobry komunikat o wyjątku

PPS

Wygląda na to, że wiele osób zostało odreagowanych przez moją sugestię dotyczącą binarnych plików dziennika, więc ponownie poprawiłem odpowiedź, aby jeszcze bardziej wyjaśnić, że to, co sugeruję tutaj, nie polega na tym, że plik dziennika powinien być binarny, ale że plik dziennika może być binarny, jeśli to konieczne.


4
Przejrzałem niektóre klasy wyjątków w .NET Framework i okazuje się, że istnieje wiele możliwości programowego dodawania tego rodzaju informacji. Sądzę więc, że pytanie rozwiązuje pytanie „dlaczego nie”. Ale +1 za całą rzecz „czytelną dla człowieka”.
Robert Harvey

7
Nie zgadzam się, że wyjątki nie powinny zawierać elementu czytelnego dla człowieka. Na pewnym poziomie możesz chcieć utworzyć komunikat dziennika dotyczący wyjątku. Argumentowałbym, że rejestrowanie śledzenia stosu do pliku dziennika czytelnego dla użytkownika ujawnia szczegóły implementacji, których nie chcesz ujawniać, więc wiadomość czytelna dla człowieka powinna zostać zarejestrowana. Po przedstawieniu pliku dziennika zawierającego błąd programiści powinni mieć punkt wyjścia do rozpoczęcia debugowania i wymuszenia wystąpienia wyjątku. Element czytelny dla człowieka powinien być odpowiednio szczegółowy bez ujawniania implementacji.
Thomas Owens

44
więc programiści nie są ludźmi? Patrząc na moich kolegów, potwierdza to pewne podejrzenia, które miałem od jakiegoś czasu ...
gbjbaanb

51
Ponownie, nie ma nic złego w pozwoleniu użytkownikowi zobaczyć cały stos śledzenia , o ile oprogramowanie jest po stronie klienta. Każdy profesjonalny projekt oprogramowania, nad którym kiedykolwiek pracowałem, a także większość projektów amatorskich, zawierała system rejestrowania, który generowałby pełny zrzut błędów po zgłoszeniu nieobsługiwanego wyjątku, w tym pełne stosy wszystkich aktualnie działających wątków w proces. A użytkownik może (wzdycha, och zgroza!) Spojrzeć na to w dowolnym momencie, ponieważ jest to konieczne (nie tylko przydatne, ale wymagane ), aby odesłać nam komunikat o błędzie! Co jest z tym nie tak?
Mason Wheeler,

13
Nie jestem również przekonany co do plików dziennika zawierających wyłącznie pliki binarne . Głównie z powodu mojego doświadczenia z systememd. Jego specjalne narzędzie do przeglądania tych dzienników jest dość mylące i wydaje się, że zostało zaprojektowane przez komitet małp Szekspira. Weź pod uwagę, że w przypadku aplikacji sieciowej pierwszą osobą, która zobaczy Twój wyjątek, będzie często sysadmin , a on będzie chciał ustalić, czy jest to coś, co należy naprawić (np. Zabrakło miejsca na dysku) lub przekazać dla programistów.
Michael Hampton

46

Dlaczego wiele typowych wyjątków od składników systemu nie zawiera użytecznych szczegółów?

Z mojego doświadczenia wynika, że ​​istnieje wiele powodów, dla których wyjątki nie zawierają użytecznych informacji. Oczekuję, że tego rodzaju powody będą dotyczyć również komponentów systemu - ale nie jestem tego pewien.

  • Ludzie skoncentrowani na bezpieczeństwie widzą wyjątki jako źródło wycieku informacji (na przykład ). Ponieważ domyślnym zachowaniem wyjątków jest wyświetlanie tych informacji użytkownikowi, programiści czasami popełniają błędy po stronie ostrożności.
  • W C ++ słyszałem argumenty przeciwko alokacji pamięci w blokach catch (gdzie przynajmniej część kontekstu stanowi dobre wiadomości). Alokacja jest trudna do zarządzania, a co gorsza, może powodować wyjątek braku pamięci - często powoduje awarię aplikacji lub wyciek pamięci. Trudno ładnie sformatować wyjątki bez alokacji pamięci, a ta praktyka mogła migrować między językami, tak jak robią to programiści.
  • Nie wiedzą. To znaczy, że sytuacje, w których kod ma żadnego pojęcia, co poszło źle. Jeśli kod nie wie - nie może ci powiedzieć.
  • Pracowałem w miejscach, w których obawy związane z lokalizacją uniemożliwiały wprowadzenie do systemu tylko ciągów w języku angielskim - nawet z wyjątkami, które byłyby czytane tylko przez personel anglojęzyczny.
  • W niektórych miejscach widziałem wyjątki używane bardziej jak twierdzenia. Są tam po to, aby zapewnić wyraźny, głośny komunikat podczas opracowywania, że ​​coś nie zostało zrobione lub dokonano zmiany w jednym miejscu, ale nie w innym. Często są na tyle wyjątkowe, że dobra wiadomość byłaby powieleniem wysiłku lub po prostu myląca.
  • Ludzie są leniwi, programiści bardziej niż większość. Spędzamy znacznie mniej czasu na ścieżce wyjątkowej niż na ścieżce szczęśliwej, a to efekt uboczny.

Czy moje oczekiwania nie są zgodne? Czy źle używam wyjątków, że to zauważam?

Trochę? To znaczy, wyjątki powinny mieć fajne wiadomości, ale są też wyjątkami . Powinieneś spędzać czas na projektowaniu kodu, aby uniknąć wyjątkowych warunków, lub na pisaniu kodu, aby poradzić sobie z wyjątkowymi warunkami (ignorowanie wiadomości), nie wykorzystując ich jako rodzaju interaktywnego mechanizmu sprzężenia zwrotnego podczas kodowania. Nie można ich używać do celów debugowania, ale w większości sytuacji należy to ograniczyć do minimum. To, że zauważyłeś ten problem, niepokoi mnie, że nie robisz wystarczająco dobrej roboty, aby im zapobiegać.


Wiem, że to oznaczono jako C, ale powinienem dodać, że twój ostatni akapit nie dotyczy wszystkich języków, ponieważ niektóre (słusznie lub nie) mogą w dużym stopniu polegać na obsłudze błędów i raportowaniu w oparciu o wyjątki .
Lilienthal,

1
@Lilienthal - takie jak? Żaden znajomy język nie zna tego typu rzeczy regularnie.
Telastyn

1
Myślę, że ta odpowiedź ma wiele dobrych treści, ale unika się powiedzenia dolnej linii, która brzmi „powinny”.
djechlin

3
Dzięki. Twoje obawy są bezpodstawne (mam nadzieję :-). Ale za każdym razem, kiedy wydać dodatkową minutę tropienia, co poszło źle w tym testów jednostkowych lub spędzić więcej czasu analizując kod, ponieważ logfile brakuje informacji, jestem odrobinę zirytowany przez do uniknięcia crappiness niektórych komunikatów :-)
Martin Ba

@Telastyn SAP zastrzeżony ABAP ma konstrukcję klasy wyjątków, która może zawierać komunikat, który jest w zasadzie obiektem specjalnie przeznaczonym do zgłaszania użytkownikowi stanu programu (sukces, niepowodzenie, ostrzeżenie) wraz z dynamicznym (wielojęzycznym) komunikatem. Przyznaję, że nie wiem, jak rozpowszechniona jest tego rodzaju rzecz, a nawet jeśli jest to zalecane w językach, w których jest to możliwe, ale jest co najmniej jedna, w której jest (niestety) powszechną praktyką.
Lilienthal,

12

Nie mam nadmiaru doświadczenia w C #, a konkretnie w C ++, ale mogę ci to powiedzieć - wyjątki napisane przez programistów 9 na 10 razy są bardziej przydatne niż jakikolwiek ogólny wyjątek, jaki kiedykolwiek znajdziesz, kropka.

Idealnie tak, ogólny wyjątek wskaże ci dokładnie, dlaczego wystąpił błąd i będziesz mógł go naprawić z łatwością - ale realistycznie, w dużych aplikacjach z wieloma klasami, które mogą generować wiele różnych rodzajów wyjątków lub z takimi samymi wyjątkami, zawsze bardziej wartościowe jest pisanie własnych danych wyjściowych do powrotu po błędzie, niż poleganie na domyślnym komunikacie.

Tak powinno być, ponieważ jak zauważyło wiele osób, niektóre aplikacje nie chcą wyświetlać komunikatu o błędzie, którego nie chcą widzieć użytkownicy ze względów bezpieczeństwa lub aby ich nie pomylić.

Zamiast tego powinieneś przewidzieć w swoim projekcie, jakie rodzaje błędów mogą być zgłaszane w Twojej aplikacji (i zawsze będą występować błędy) i pisać komunikaty wychwytujące błędy, które pomogą Ci zidentyfikować problem.

Nie zawsze ci to pomoże - ponieważ nie zawsze możesz przewidzieć, jaki komunikat o błędzie będzie przydatny - ale jest to pierwszy krok do lepszego zrozumienia własnej aplikacji w dłuższej perspektywie.


7

Pytanie dotyczy w szczególności tego, dlaczego tak wiele wyjątków zgłaszanych przez „komponenty systemu” (znane również jako standardowe klasy bibliotek) nie zawiera użytecznych szczegółów.

Niestety większość programistów nie pisze podstawowych komponentów w standardowych bibliotekach, a szczegółowe dokumenty projektowe lub inne uzasadnienia projektowe niekoniecznie są upubliczniane. Innymi słowy, możemy nigdy nie mieć pewności.

Należy jednak pamiętać o dwóch kluczowych kwestiach, dlaczego szczegółowe informacje o wyjątkach mogą nie być pożądane lub ważne:

  1. Można użyć wyjątku, wywołując kod w dowolny sposób: standardowa biblioteka nie może nakładać ograniczeń na sposób wykorzystania wyjątku. W szczególności może być wyświetlany użytkownikowi. Rozważ indeks tablicy poza granicami: może to dać użyteczne informacje atakującemu. Projektant języka nie ma pojęcia, w jaki sposób aplikacja wykorzysta zgłoszony wyjątek, a nawet jaki to rodzaj aplikacji (np. Aplikacja internetowa lub komputer stacjonarny), więc pominięcie informacji może być bezpieczniejsze z punktu widzenia bezpieczeństwa.

  2. Wyjątki nie powinny być wyświetlane użytkownikowi. Zamiast tego wyświetl przyjazny komunikat o błędzie i zaloguj wyjątek do lokalizacji, do której atakujący nie ma dostępu (jeśli dotyczy). Po zidentyfikowaniu błędu programista powinien debugować kod, sprawdzając ramki stosu i ścieżki logiczne. W tym momencie programista ma więcej informacji, niż wyjątek mógłby kiedykolwiek mieć nadzieję.


3
1. Na podstawie tych kryteriów wydaje się stosunkowo arbitralne, co to jest informacja („Indeks poza zakresem”, ślad stosu) i nie jest pokazywana (wartość indeksu). 2. Debugowanie może potencjalnie być znacznie szybsze i łatwiejsze, gdy znane są odpowiednie wartości dynamiczne. Na przykład często od razu mówi ci, czy problem polega na wprowadzeniu śmieci do fragmentu kodu, który nie powiódł się, czy też ten kod nie radzi sobie poprawnie z dobrym wprowadzeniem
Ben Aaronson

@BenAaronson tożsamość / klasa wyjątku mówi nam o rodzaju błędu. Chodzi mi o to, że szczegóły można pominąć (tj. Jaka konkretna wartość spowodowała błąd) ze względów bezpieczeństwa. Ta wartość może być identyfikowalna z powrotem do danych wejściowych użytkownika, ujawniając informacje atakującemu.

@Snowman Nie sądzę, aby bezpieczeństwo było brane pod uwagę, gdy dostępne jest śledzenie pełnego stosu, a numer indeksu nie. Jasne, że rozumiem atakującego próbującego przepełnienia bufora, ale wiele wyjątków
pomija

@ gbjbaanb, który mówi, że musimy pokazać użytkownikowi pełny ślad stosu?

1
Dzięki za podzielenie się tym spostrzeżeniem. Osobiście nie zgadzam się i uważam, że argument bezpieczeństwa jest całkowitym błędem, ale może być uzasadnieniem.
Martin Ba

4

Po pierwsze, pozwól mi rozbić bańkę, mówiąc, że nawet jeśli wiadomość diag jest załadowana informacjami, które prowadzą do dokładnej linii kodu i polecenia podrzędnego w ciągu 4 sekund, istnieje prawdopodobieństwo, że użytkownicy nigdy go nie zapisają ani nie przekażą pracownikom pomocy technicznej i powiedzą ci: „Cóż, to mówiło coś o naruszeniu ... Nie wiem, czy to wyglądało na skomplikowane!”

Piszę oprogramowanie i wspieram wyniki innych programów od ponad 30 lat i osobiście obecna jakość komunikatu o wyjątku nie ma praktycznie nic wspólnego z bezpieczeństwem, niezależnie od tego, jak wyniki końcowe pasowały do ​​ich modelu wszechświat, o wiele więcej wspólnego z faktem, że tak wielu w naszej branży było pierwotnie samoukami i po prostu nigdy nie zawierało lekcji komunikacji. Może gdybyśmy WYMUSIŁY wszystkich nowych programistów na kilka lat do pozycji serwisowej, gdzie musieliby się dowiedzieć, co poszło źle, zrozumieliby znaczenie przynajmniej pewnej formy precyzji.

Niedawno w trakcie przebudowy aplikacji podjęto decyzję, że kody zwrotne będą należeć do jednej z trzech grup:

  • Od 0 do 9 byłby sukcesem poprzez sukces z dodatkowymi informacjami.
  • 10 do 99 byłoby błędami krytycznymi (możliwymi do odzyskania), oraz
  • 101 do 255 to błędy krytyczne.

(100 zostało z jakiegoś powodu pominięte)

W każdym konkretnym przepływie pracy nasza myśl została ponownie wykorzystana lub kod ogólny użyłby ogólnych zwrotów (> 199) dla błędów krytycznych, pozostawiając nam 100 błędów krytycznych możliwych dla przepływu pracy. Przy lekkim rozróżnieniu danych w komunikacie błędy takie jak nie znaleziono pliku mogą używać tego samego kodu i różnicować się z komunikatami.

Gdy kod wrócił od kontrahentów, nie uwierzyłbyś w nasze zdziwienie, gdy praktycznie KAŻDY JEDEN FATALNY BŁĄD był kodem zwrotnym 101.

Uważam, że odpowiedzią na twoje pytanie jest to, że wiadomości są tak bezsensowne, ponieważ po ich utworzeniu miały być symbolami zastępczymi, do których nikt nie wrócił. W końcu ludzie wymyślili, jak rozwiązać problemy nie z powodu wiadomości, ale DISPITE je.

Od tego czasu samoukowie nigdy nie mieli dobrego przykładu, co powinien zawierać wyjątek. Dodaj do tego, że więcej użytkowników nie czyta wiadomości, a tym bardziej spróbuj przekazać je do obsługi (widziałem komunikaty o błędach, które zostały wycięte i wklejone przez używane, które zostały następnie zredagowane przed wysłaniem z późniejszym komentarzem, że to wydawało mi się, że to dużo informacji i prawdopodobnie nie mogłem tego wszystkiego chcieć, więc losowo usunęli kilka z nich.

I spójrzmy prawdzie w oczy, ze zdecydowanie za dużo (nie wszystkie, ale za dużo) nowej generacji koderów, jeśli jest to więcej pracy i nie dodaje flasha, po prostu nie jest tego warte ...

Ostatnia uwaga: jeśli komunikat o błędzie zawiera kod błędu / powrotu, wydaje mi się, że gdzieś w wykonanych modułach powinna znajdować się linia czytająca coś w rodzaju „jeśli warunek zwraca wartość-kod” i warunek powinien powiedzieć, dlaczego kod powrotu wystąpił. Wydaje się to prostym logicznym podejściem, ale na całe życie spróbuj po prostu przekonać Microsoft, co się stało, gdy aktualizacja systemu Windows nie powiodła się na CODE 80241013 lub innym bardzo unikalnym identyfikatorze. Trochę smutne, prawda?


8
„... nie uwierzyłbyś naszemu zaskoczeniu, gdy praktycznie KAŻDY JEDEN FATALNY BŁĄD był kodem zwrotnym 101.” Masz rację. Nie wierzę, że byłeś zaskoczony, gdy wykonawca zastosował się do twoich instrukcji.
Odalrick

3
chances are the users will never write it down... and you will be told "Well it said something about a violation..." Dlatego używasz narzędzia do rejestrowania wyjątków, aby automatycznie wygenerować raport o błędach zawierający ślad stosu, a nawet wysłać go na serwer. Raz miałem jednego użytkownika, który nie był zbyt techniczny. Za każdym razem, gdy przesyłała komunikat z rejestratora błędów, pojawiało się coś takiego: „Nie jestem pewien, co zrobiłem źle, ale ...” bez względu na to, ile razy wyjaśniłem, że ten błąd oznaczał błąd po mojej stronie . Ale zawsze otrzymywałem od niej raporty o błędach!
Mason Wheeler

3

Chociaż zgadzam się, że wyjątki powinny zawierać jak najwięcej informacji, a przynajmniej być mniej ogólne. W przypadku nie znalezienia tabeli, nazwa tabeli byłaby miła.

Ale wiesz więcej o tym, co próbowałeś zrobić w miejscu w kodzie, w którym otrzymałeś wyjątek. Chociaż często naprawdę nie możesz wiele zrobić, aby naprawić sytuację, gdy coś pójdzie nie tak w bibliotece, na którą nie masz wpływu, możesz dodać o wiele bardziej przydatne informacje, w której sytuacji coś poszło nie tak.

W przypadku braku tabeli nie pomoże ci to, jeśli powiesz, że tabela, której nie można znaleźć, nazywa się STUDENCI, ponieważ nie masz takiej tabeli, a łańcucha nie ma w twoim kodzie.

Ale jeśli złapiesz wyjątek i wrzucisz go ponownie za pomocą instrukcji SQL, którą próbujesz wykonać, będzie ci lepiej, ponieważ okazuje się, że próbowałeś wstawić rekord o polu nazwy Robert ”); UCZNIOWIE STOŁU; (Zawsze jest xkcd!)

Aby więc walczyć z mniej niż informacyjnymi wyjątkami: spróbuj złapać ponownie, podając więcej informacji specyficznych dla tego, co próbujesz zrobić.

Powinienem chyba dodać, że jest to raczej odpowiedź na pytanie, dlaczego w pytaniu, że prawdopodobnym powodem, dla którego twórcy bibliotek nie skupili się na ulepszaniu komunikatów wyjątków, jest to, że nie wiedzą dlaczego próbowano czegoś, co nie powiodło się, logika ta znajduje się w kodzie wywołującym.


np. w C ++ powinieneś throw_with_nesteddużo używać .
Miles Rout

3

Aby dać nieco inną odpowiedź: prawdopodobnie został naruszony kod, aby sprecyzować:

  • Funkcja otrzymuje X i zwraca Y
  • Jeśli X jest nieprawidłowy, wyrzuć wyjątek Z

Dodaj presję, aby dostarczać dokładnie do specyfikacji (w obawie przed odrzuceniem podczas przeglądu / testowania) w jak najkrótszym czasie i przy minimalnym zamieszaniu, wtedy masz przepis na całkowicie zgodny i niepomocny wyjątek w bibliotece.


3

Wyjątki wiążą się z kosztami specyficznymi dla języka i wdrożenia.

Na przykład wyjątki w C ++ są wymagane do zniszczenia wszystkich żywych danych między wyrzucaniem ramki wywołania a przechwytywaniem ramki wywołania, a to jest kosztowne. Dlatego programiści nie chcą zbyt często używać wyjątków.

W Ocaml zgłaszanie wyjątków jest prawie tak szybkie jak C setjmp(jego koszt nie zależy od liczby przemieszczanych ramek wywołań), więc programiści mogą z niego korzystać bardzo często (nawet w nietypowych, bardzo częstych przypadkach). W przeciwieństwie do tego wyjątki w C ++ są wystarczająco ciężkie, więc prawdopodobnie nie będziesz ich używać tak, jak w Ocaml.

Typowym przykładem jest wyszukiwanie rekursywne lub eksploracja, które można „zatrzymać” wewnątrz dość głębokiej rekurencji (np. Znaleźć liść na drzewie lub funkcję unifikacyjną). W niektórych językach propagowanie tego warunku wśród każdego dzwoniącego jest szybsze (a więc bardziej idiomatyczne). W innych językach zgłoszenie wyjątku jest szybsze.

Tak więc w zależności od języka (i nawyków programistów używających go) wyjątek może zawierać wiele użytecznych szczegółów, lub wręcz przeciwnie może być użyty jako szybki skok nielokalny i zawierać tylko bardzo przydatne dane.


6
„Na przykład wyjątki w C ++ są wymagane, aby zniszczyć wszystkie żywe dane między rzucaniem ramki wywołania a przechwytywaniem ramki wywołania, a to jest kosztowne. Dlatego programiści nie chcą zbyt często używać wyjątków.” Bzdury. Główną zaletą wyjątków C ++ jest to, że destruktory są nazywane deterministycznie. Nikt ich nie użyłby, gdyby tylko skoczył.
Miles Rout

Wiem o tym, ale faktem jest, że wyjątki w C ++ nie są podobne do Ocaml i nie używasz ich tak jak w Ocaml.
Basile Starynkevitch,

5
Nie używasz wyjątków C ++ do sterowania przepływem w C ++ głównie dlatego, że powoduje to, że kod jest nieczytelny i trudny do zrozumienia.
Miles Rout

-2

Co sprawia, że ​​uważasz, że wartość indeksu lub wymagany zakres lub nazwa tabeli jest użytecznym szczegółem, na przykład w wyjątku?

Wyjątki nie są mechanizmem obsługi błędów; są mechanizmem odzyskiwania .

Wyjątkiem jest bąbelkowanie do poziomu kodu, który może obsłużyć wyjątek. Gdziekolwiek to jest poziom, albo ty masz informacje potrzebne, czy to nie jest istotne. Jeśli potrzebujesz informacji, ale nie masz do nich bezpośredniego dostępu, wyjątek nie jest obsługiwany na odpowiednim poziomie.

Pewnego razu mogę wymyślić, gdzie dodatkowe informacje mogą być pomocne, na absolutnym najwyższym poziomie aplikacji, w której następuje awaria i zrzut zrzutu błędu; ale wyjątek stanowi dostęp do tych informacji, ich kompilacja i przechowywanie.

Nie twierdzę, że można po prostu wszędzie „rzucić nowy wyjątek” i nazwać to dobrym, można napisać złe wyjątki. Ale dołączanie nieistotnych informacji nie jest konieczne do ich prawidłowego wykorzystania.


Nie opisałbym nazwy brakującej tabeli bazy danych jako nieistotnej, chociaż rozumiem i współczuję temu, o czym mówisz. Dałem ci głos.
Daniel Hollinrake,

1
@DanielHollinrake Tak, nazwa tabeli jest zdecydowanie najmniej nieistotna z przykładów. W kodzie, z którym pracuję, ten problem jest przygnębiająco powszechny, a patrzenie na to, jak nazwa tabeli została zniekształcona, daje wskazówki, co jest nie tak. Próbowałem wymyślić przykład, dlaczego te rzeczy nie mają znaczenia dla wyjątku; może mogę to wykorzystać ...
Odalrick

Nie zgadzam się. Do obsługi wyjątku mogą nie być wymagane dodatkowe szczegóły, ponieważ chcesz po prostu zabezpieczyć aplikację przed awarią, ale w końcu będziesz musiał powiedzieć, dlaczego nie działała, i będziesz w stanie to naprawić. Jeśli nie masz żadnych wskazówek poza typem wyjątku, to dobrze wygląda debugowanie.
t3chb0t

@ t3chb0t Do tego właśnie służy śledzenie stosu i klasa wyjątku oraz zrzut pamięci i wszystko inne. Jak mogłoby ci to pomóc , gdyby klient zadzwonił i powiedział: „Komputer mówi mi, że próbował uzyskać dostęp do indeksu 5, ale go tam nie było”. Może to pomóc tylko wtedy, gdy serializujesz listę, jej kontekst i wszystko, co może być przydatne. Nie należy serializować całego stanu aplikacji za każdym razem, gdy zgłaszasz wyjątek.
Odalrick

@Odalrick dla klienta może nie mieć żadnego znaczenia, ale jako programista Cenię każdą informację mogę dostać ;-) to może kolejny przykład: powiedzmy, że SqlExeption występuje i to wszystko wiesz ... To jest o wiele łatwiejsze do naprawienia go jeśli wiesz, który ciąg połączenia, baza danych, tabela itp. nie działał .... a jest to jeszcze ważniejsze, jeśli twoja aplikacja korzysta z kilku baz danych. Szczegółowe śledzenie stosu wymaga, aby pliki pdb zostały dostarczone wraz z aplikacją ... nie zawsze jest to możliwe. Zrzuty pamięci mogą stać się bardzo duże i nie zawsze można je przenieść.
t3chb0t
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.