Dlaczego w językach programowania błędy są nazywane „wyjątkami”, a nie „błędami”?

45

Właściwie o tym myślałem. Sam nie jestem rodzimym językiem angielskim, ale wciąż mam wieloletnie doświadczenie w programowaniu i zawsze o to pytałem. Dlaczego nazywa się wyjątek, ale nie jest błędem, ponieważ są błędami.

Może być PageNotFoundErrorzamiast PageNotFoundException.

Tarik
źródło
41
Nie wszystkie wyjątkowe sytuacje są błędami.
Andrew T Finnell,
15
Jest to różnica między skręcaniem samochodu i rozbijaniem samochodu.
Inżynier świata
6
Czy chodzi tylko o nazewnictwo określonych klas wyjątków? Następnie zauważ, że w niektórych ekosystemach są one nazywane XYError- na przykład w Pythonie.
6
Pamiętaj, że Java ma klasę Error, która dziedziczy po Throwable. Aby uzyskać więcej informacji, zobacz docs.oracle.com/javase/1.4.2/docs/api/java/lang/Error.html . Możesz także sprawdzić kategorię „Bezpośrednie znane podklasy”.
luiscubal
Chciałbym powiedzieć, że ta zagadka nie ma nic wspólnego z angielskim. To bardziej logiczna kategoryzacja w dowolnym języku mówionym, w którym zdecydujesz się być biegły.
שינתיא אבישגנת

Odpowiedzi:

59

Nie muszą wcale być błędami. Brak strony może być ciekawym faktem, a nie faktycznym błędem. Przyznaję, że niemal cały czas są wykorzystywane jako błędy. Ale czasami są one używane do przełamywania pętli lub informowania, że ​​łańcuch nie jest prawidłową liczbą. Można ich używać do przechowywania i zwracania ogromnej ilości przydatnych danych - w ramach dość normalnego zwrotu. (Niektóre języki są nieco powolne z wyjątkiem wyjątków, w takim przypadku częste ich rzucanie jest złym pomysłem.) Teoretycznie wyjątek oznacza po prostu „nie rób normalnego powrotu, idź na górę stosu wywołań, dopóki nie znajdziesz kogoś zainteresowanego w tym."

Nawet wyjątek wskaźnika zerowego może niewiele dla ciebie znaczyć. Wywołujesz kod innej osoby, a następnie wychwytujesz wyjątek wskaźnika zerowego, ponieważ wiesz, że może on wysadzić w powietrze, wydrukować komunikat z informacją, czyja to wina, i kontynuować pracę.

RalphChapin
źródło
27
Chociaż stosowanie mechanizmów wyjątków jako przepływu kontroli może być mylące i myślę, że ogólnie jest to lekceważone.
ChaosPandion
11
@ChaosPandion: Zależy od języka / kultury.
amara,
11
@DocBrown: Kiedyś napisałem solver sudoku, który wyszukuje rekurencyjnie, który cofa się, gdy nie uda się znaleźć rozwiązania w bieżącej próbie i ponów próbę z inną wartością; a gdy zostanie znalezione rozwiązanie, zgłasza wyjątek zawierający rozwiązanie. Problemem tutaj porażka jest „normalna” sytuacja, a sukces to „wyjątkowa” sytuacja; a ponieważ w rozwiązaniu jest wiele punktów, w których sam się nazywa, bez wyjątku musiałbyś napisać wiele kotłów, aby sprawdzić, czy połączenie powraca z udanego wyszukiwania, czy z nieudanego wyszukiwania.
Lie Ryan,
5
@ Falcon: tak, możesz po prostu zwrócić wartość „gotową”, co oznacza, że ​​za każdym razem, gdy się powtórzysz, musisz to zrobić: for (...) { if (func() == finished) { return finished; } else { itfailedsocheckanother(); }}ale biorąc pod uwagę, że w kodzie jest wiele punktów, w których jest to funkcja func (), rozwiązanie bez wyjątków staje się brzydsze za każdym razem, gdy dodajesz więcej rekurencji. To właśnie nazywam programami kultu-ładunku, w gruncie rzeczy symuluje wyjątki w języku, który już ma taki program, ponieważ przywódca kultu mówi: „nie będziesz używać wyjątków”.
Lie Ryan,
8
@ Falcon: Ach ... zapasowy argument „wygląda jak Goto”, argumenty te mówią, że nie należy używać pętli lub instrukcji lub wywołań funkcji, ponieważ „wszystkie wyglądają jak gotos”. Powodzenie zwrotu z wyjątkiem jest WTF tylko wtedy, gdy kojarzysz wyjątek z błędami. Dla mnie, gdy użyje się w ten sposób, blok try-catch jest jak „obietnica powrotu tutaj po długiej podróży”, zachowanie try-try + throw jest bardzo podobne do wywołań funkcji + powrotów, z wyjątkiem tego, że znacznie dłuższe podróże, które mogą wymagać bardzo głębokiego stosu połączeń, gdy zakończysz poszukiwanie rozwiązania.
Lie Ryan,
21

Mechanizm wyjątków nie zawsze jest wykorzystywany do sygnalizowania błędów. Wyjątki są zgłaszane poza zwykłymi sytuacjami, które wymagają oddzielnej ścieżki kodu do przetworzenia, w tym błędów. Na przykład użytkownik podający nazwę nieistniejącego pliku lub wprowadzający literę zamiast cyfry w polu numerycznym to wyjątkowe sytuacje wymagające specjalnej obsługi, ale nie są to błędy.

W niektórych środowiskach programowania, takich jak Java, dostępne są specjalne Errorobiekty do zgłaszania „prawdziwych błędów”, sytuacji, w których rozsądna aplikacja nie powinna podejmować prób. Obiekty te są dostarczane przy użyciu tego samego mechanizmu, który jest używany do dostarczania wyjątków, ale mają specjalne znaczenie sygnałów o sytuacjach niemożliwych do odzyskania.

dasblinkenlight
źródło
6

Nie prowadzę badań etymologicznych na temat ich pochodzenia, ale rozumiem, że użycie terminu „Błąd” może nie być precyzyjne we wszystkich sytuacjach; również, jak wspomniano prawieSharepointMaster, lepiej pomyśleć o błędzie i wyjątku zgłoszonym jako oddzielne byty.

Kiedy jesteś w języku programowania wysokiego poziomu, sensownie jest zakładać, że wyjątek zawsze jest spowodowany błędem, chociaż zgadzam się również z dasblinkenlight, że nawet wtedy wyjątek nie zawsze jest konsekwencją błędu. Na przykład używam wyjątków do wspólnego kończenia wątków.

Po raz pierwszy zobaczyłem termin „wyjątek” w instrukcji montażu 80386. Pamiętam, że kiedy zobaczyłem, wyglądało to dla mnie naturalnie. Nazywanie tego błędem nie byłoby poprawne, ponieważ nie ma błędów w asemblerze; są po prostu warunki, z którymi procesor nie może sobie poradzić (jeśli jest to błąd - od programisty, użytkownika lub systemu - cóż, procesor jest całkowicie niezależny od tego). Nie wiem, czy Intel naprawdę powstał, czy nie, ale może ...

Fabio Ceconello
źródło
3

Powszechnie stosowany jest wyjątek do nazwania zdarzenia, które jest niepoprawne, ale można je odzyskać, jak out_of_rangewyjątek w C ++, który jest zgłaszany podczas uzyskiwania dostępu do elementu w wektorze lub tablicy, który nie istnieje. Oczywiście takie zdarzenie nie jest poprawne, ale zdarza się, że nie powinno to oznaczać awarii całego programu.

Z drugiej strony błędy są zwykle używane do nazwania czegoś, co powinno spowodować awarię wszystkiego, coś takiego jak przepełnienie stosu jest przykładem zdarzenia, które powinno zakończyć program, ponieważ program nie może go obsłużyć wewnętrznie. Innymi słowy: błąd jest poważny, a wyjątek stosunkowo niewielki.

jozefg
źródło
3

Myślę, że ma to więcej wspólnego z „ewolucją” obsługi błędów. W przypadku języków C / C ++ (przed dodaniem obsługi wyjątków), jeśli funkcja się nie powiedzie, jedynym sposobem na to jest sprawdzenie wartości zwracanej (np. HRESULTW win32). Zwykle kończyło się to na łapaniu kodów wyjścia każdego wywołania funkcji i sprawdzaniu. Takie podejście sprawia, że ​​kod jest bardziej bałaganiarski. I wiele razy programiści unikają dodawania tych czeków z lenistwa.

Po wprowadzeniu obsługi wyjątków programiści mieli teraz dwie opcje zgłoszenia błędu. Tak więc słowo „wyjątek” zostało użyte do odróżnienia błędów od błędów „status wyjścia”. Po pewnym czasie obsługa wyjątków stała się popularnym sposobem propagowania błędów, ponieważ kod jest znacznie łatwiejszy do odczytania, utrzymania i może istnieć jedno miejsce, w którym można mieć logikę obsługi błędów.

Ankush
źródło
2

W Pythonie są one nazywane ABCError Np .: KeyError, IndexError

http://docs.python.org/library/exceptions.html

Myślę więc, że to zależy od używanego języka.

HVNSweeting
źródło
4
Nie zapomnij VB (klasyczny, nie. Net). W przypadku błędu zastosowano Goto. I najbardziej niesamowity wynalazek wszechczasów „On Error Resume Next”
Kibbee
1
W Pythonie błędy są podzbiorem wyjątków. Istnieją cztery standardowe wyjątki, które dziedziczą po wyjątku, ale nie dziedziczą po StandardError: StopIteration, GeneratorExit, KeyboardInterrupt i SystemExit.
Dirk Holsopple,
1

Gdy wystąpi błąd, system lub aktualnie uruchomiona aplikacja zgłasza go, zgłaszając wyjątek zawierający informacje o błędzie. Po zgłoszeniu wyjątek jest obsługiwany przez aplikację lub domyślną procedurę obsługi wyjątków.

Błąd zgłasza wyjątek, który wyszczególnia błąd, więc nie wszystko jest błędem, który jest wyjątkiem, jeśli ma to sens;), na przykład niezamknięty wyjątek nie powinien być błędem, ale zgłasza wyjątek.

http://msdn.microsoft.com/en-us/library/system.exception.aspx

Ali Jafer
źródło
0

W programowaniu na iOS / Mac mamy zarówno wyjątki, jak i błędy w jednym języku.

Przynajmniej w tym środowisku wyjątek jest „niemożliwy do odzyskania”, podczas gdy błąd jest „możliwy do odzyskania”.

Na przykład:

  • jeśli masz tablicę z 10 elementami i próbujesz uzyskać dostęp do elementu o indeksie 30 - będzie to wyjątek. Popełniłeś błąd podczas programowania.
  • jeśli spróbujesz pobrać adres URL, ale nie ma połączenia z Internetem, należy się tego spodziewać i powinieneś przekazać użytkownikowi jakąś wiadomość.

Wyjątki zwykle powodują awarię aplikacji, podczas gdy błędy zwykle zwracają się, nila obiekt błędu (zwracany jako parametr metody referencyjnej). Możesz wychwycić wyjątki za pomocą bloku try / catch / wreszcie, ale zaleca się, aby nigdy nie używać tej funkcji języka - jeśli możliwe jest odzyskanie wyjątku w jakikolwiek sposób, nie powinieneś w ogóle rzucać wyjątku (powinieneś powrócić obiekt błędu zamiast tego).

Abhi Beckert
źródło
2
Cóż, jest to zupełnie inne niż wyjątki i błędy dla innych programistów!
Tarik,
Chyba każdy język jest inny. Objective-C / Cocoa jest jednym z najstarszych aktywnych języków (od około 1983 roku), więc być może jest nieco staroświecki. Jednak jeśli definicja zmienia się z jednej społeczności do drugiej, ważne jest, aby o tym wiedzieć.
Abhi Beckert
0

Błąd jest coś, co poszło źle w realizacji programu. Często rozwiązuje się to poprzez podniesienie wyjątku , ale

  • nic nie zmusza programisty do obsługi błędu przez zgłoszenie wyjątku, oraz
  • nic nie zmusza programisty do zgłaszania wyjątków tylko w przypadku błędu.

Błąd jest pojęciem semantycznym : jest stosowany przez programistę lub użytkownika, który przychodzi do programu z oczekiwaniami, aby opisać różnicę między ich oczekiwaniami a rzeczywistością. Tylko osoba może powiedzieć, czy procedura jest w stanie błędu, czy nie.

Wyjątek stanowi koncepcja składniowa : jest to coś w samym programie, niezależnie od oczekiwań kogokolwiek na temat tego, co ten program ma zrobić. Rutyna albo nie stwarza wyjątku, bez względu na to, co ktoś myśli.


źródło
0

Wyjątki i błędy są różne.

Wyjątkiem są sytuacje, które program może przezwyciężyć, na przykład próba otwarcia pliku i nie istnieje, podczas gdy błędy to sytuacje, w których program nie może nic zrobić, na przykład awaria dysku lub awaria pamięci RAM.

Tulains Córdova
źródło
0

Zgłaszanie wyjątków i obsługa wyjątków to funkcje kontroli przepływu, a nazwa wyjątku powinna być zgodna z przeznaczeniem. Projektant kodu i interfejsu API powinien znaleźć dobre i spójne schematy nazewnictwa.

Odpowiedź na twoje pytanie brzmi: zależy to od kontekstu i perspektywy.

mmehl
źródło
0

Wyjątki ewoluowały jako uogólnienie błędów. Pierwszy język programowania do włączenia mechanizmu wyjątków był Lisp na początku 1970 roku. Jest dobre podsumowanie w A Pattern of Language Evolution autorstwa Gabriela i Steele. Wyjątki (które nie były jeszcze nazywane wyjątkami) wynikały z potrzeby określenia zachowania programu w przypadku wystąpienia błędu. Jedną z możliwości jest zatrzymanie programu, ale nie zawsze jest to pomocne. Implementacje Lisp tradycyjnie miały sposób na wejście do debuggera w przypadku błędu, ale czasami programiści chcieli włączyć obsługę błędów w swoim programie. Tak więc implementacje Lisp z lat 60. XX wieku miały sposób powiedzieć „zrób to, a jeśli wystąpi błąd, zrób to zamiast tego”. Początkowo błędy pochodziły z prymitywnych funkcji, ale programiści uznali za celowe wyzwolenie błędu, aby pominąć część programu i przejść do procedury obsługi błędów.

W 1972 roku nowoczesna forma obsługi wyjątków w Lisp pojawiła się w MacLisp: throwi catch. Software Preservation Grupa wymienia wiele materiałów na wczesnych implementacjach Lisp, w tym The maclisp Reference Manual Wersja 0 Davida Księżyca . Prymitywy catchi throwsą opisane w §5.3 str.43.

catchto funkcja LISP do wykonywania ustrukturyzowanych wyjść nielokalnych. (catch x)ocenia xi zwraca swoje wartości, z wyjątkiem tego, że jeśli podczas oceny x (throw y)powinien zostać oceniony, catchnatychmiast wraca ybez dalszej oceny x.

catchmoże być również użyty z argumentem econd, bez oceny, który służy jako znacznik do rozróżnienia zagnieżdżonych połowów. (…)

throwjest używany catchjako ustrukturyzowany nielokalny mechanizm wyjścia.

(throw x)ocenia xi zwraca wartość z powrotem do najnowszej catch.

(throw x <tag>)zwraca wartość xpowrotu do najnowszego catchoznaczonego <tag>lub nieoznaczonego.

Nacisk kładziony jest na nielokalny przepływ kontroli. Jest to forma goto (goto tylko w górę), która jest również nazywana skokiem . Metafora jest taka, że ​​jedna część programu wyrzuca wartość, aby zwrócić ją do procedury obsługi wyjątków, a procedura obsługi wyjątków przechwytuje tę wartość i zwraca ją.

Obecnie większość języków programowania pakuje znacznik i wartość w obiekt wyjątku i łączy mechanizm przechwytywania z mechanizmem obsługi.

Wyjątki niekoniecznie są błędami. Są sposobem na wyjście z bloku kodu i otaczających go bloków, uciekając, dopóki nie zostanie osiągnięty moduł obsługi wyjątku. To, czy taka rzecz jest uważana za „błąd” w sensie intuicyjnym, jest subiektywne.

W niektórych językach rozróżnia się terminy „błąd” i „wyjątek”. Na przykład niektóre dialekty Lisp muszą zarówno throwzgłosić wyjątek (przepływ sterowania dla użytkowników, mający na celu wykonanie nielokalnego wyjścia w sposób, który nie oznacza, że ​​coś poszło „nie tak”), a signaltakże zgłoszenie błędu (co oznacza, że coś poszło „nie tak” i może spowodować zdarzenie debugowania).

Gilles „SO- przestań być zły”
źródło
-1

Znajdziesz go różnie interpretowanego w różnych implementacjach języka programowania. Jak powiedział dasblinkenlight, jest to punkt widzenia java dotyczący rozgraniczenia błędu i wyjątku. W wielu językach programowania wyjątkami są naruszenia, które można obsłużyć lub zezwolić na propagację w celu przekazania do najwyższego możliwego modułu kodu. Błędy to na ogół sytuacje, w których kontener środowiska uruchomieniowego języka obsługuje (a wiele przypadków po prostu wstrzymuje wykonanie).

shibathethinker
źródło
-1

Błąd jest zawsze błędem. Wyjątkiem jest błąd w bieżącym kontekście. Oznacza to, że wyjątek jest wrażliwy na kontekst. Przykładem wyjątku byłoby dodanie ascii „a” do liczby całkowitej „1”. Błąd może przypominać użycie niezdefiniowanego operatora, takiego jak „+!” w większości języków.

Niektóre języki pozwolą Ci zdefiniować wyjście z sytuacji, jeśli naprawdę tego chcesz.

W8CCW
źródło