W sprawach wysokiego poziomu wyjątki; w sprawach niskiego poziomu, kody błędów.
Domyślnym zachowaniem wyjątku jest rozwinięcie stosu i zatrzymanie programu, jeśli piszę skrypt i idę po klucz, którego nie ma w słowniku, prawdopodobnie jest to błąd i chcę, aby program się zatrzymał i pozwolił mi wiedzieć wszystko o tym.
Jeśli jednak piszę fragment kodu, który muszę znać w każdej możliwej sytuacji, to chcę mieć kody błędów. W przeciwnym razie muszę znać każdy wyjątek, który może zostać zgłoszony przez każdą linię w mojej funkcji, aby wiedzieć, co zrobi (przeczytaj wyjątek, który uziemił linię lotniczą, aby dowiedzieć się, jak trudne to jest). Pisanie kodu, który odpowiednio reaguje na każdą sytuację (w tym te nieszczęśliwe) jest żmudne i trudne, ale to dlatego, że pisanie kodu wolnego od błędów jest żmudne i trudne, a nie dlatego, że przekazujesz kody błędów.
Zarówno Raymond Chen, jak i Joel przedstawili wymowne argumenty przeciwko używaniu wyjątków do wszystkiego.
nodiscard
atrybut, który będzie generował ostrzeżenie kompilatora, jeśli wartość zwracana funkcji nie jest przechowywana. Pomaga trochę wyłapać zapomniany kod błędu. Przykład: godbolt.org/g/6i6E0BZwykle wolę wyjątki, ponieważ zawierają one więcej informacji kontekstowych i mogą przekazać (jeśli są właściwie użyte) błąd programistom w jaśniejszy sposób.
Z drugiej strony kody błędów są lżejsze niż wyjątki, ale trudniejsze w utrzymaniu. Sprawdzanie błędów można nieumyślnie pominąć. Kody błędów są trudniejsze do utrzymania, ponieważ musisz zachować katalog ze wszystkimi kodami błędów, a następnie włączyć wynik, aby zobaczyć, jaki błąd został zgłoszony. Zakresy błędów mogą być tutaj pomocne, ponieważ jeśli jedyną rzeczą, która nas interesuje, jest to, czy jesteśmy w obecności błędu, czy nie, łatwiej jest to sprawdzić (np. Kod błędu HRESULT większy lub równy 0 to sukces i mniej niż zero oznacza awarię). Można je nieumyślnie pominąć, ponieważ nie ma programowego wymuszenia, że programista będzie sprawdzał kody błędów. Z drugiej strony nie możesz ignorować wyjątków.
Podsumowując, wolę wyjątki niż kody błędów w prawie wszystkich sytuacjach.
źródło
Wolę wyjątki, ponieważ
źródło
goto
Kody błędów mogą być ignorowane (i często są!) Przez wywołujące funkcje. Wyjątki przynajmniej zmuszają ich do radzenia sobie z błędem w jakiś sposób. Nawet jeśli ich wersja radzenia sobie z tym polega na tym, że ma pustą obsługę połowu (westchnienie).
źródło
Bez wątpienia wyjątki od kodów błędów. Wyjątki dają wiele takich samych korzyści, jak w przypadku kodów błędów, ale także znacznie więcej, bez wad związanych z kodami błędów. Jedynym wyjątkiem jest to, że jest nieco bardziej napowietrzny; ale w dzisiejszych czasach ten narzut powinien być uważany za nieistotny dla prawie wszystkich zastosowań.
Oto kilka artykułów omawiających, porównujących i przeciwstawiających te dwie techniki:
W tych jest kilka dobrych linków, które mogą dać ci dalsze czytanie.
źródło
Nigdy nie pomieszałbym tych dwóch modeli ... zbyt trudno jest przekonwertować jeden na drugi, gdy przechodzisz z jednej części stosu, która używa kodów błędów, do wyższej części, która używa wyjątków.
Wyjątki dotyczą „wszystkiego, co zatrzymuje lub uniemożliwia metodzie lub podprogramowi wykonanie tego, o co go prosiłeś” ... NIE przekazywać komunikatów o nieprawidłowościach lub nietypowych okolicznościach, lub o stanie systemu itp. Używaj wartości zwracanych lub ref (lub out) parametry do tego.
Wyjątki pozwalają na pisanie (i wykorzystywanie) metod z semantyką zależną od funkcji metody, tj. Metoda zwracająca obiekt pracownika lub listę pracowników może być wpisana w tym celu i można ją wykorzystać przez wywołanie.
W przypadku kodów błędów wszystkie metody zwracają kod błędu, więc dla tych, które muszą zwrócić coś innego do użycia przez kod wywołujący, musisz przekazać zmienną referencyjną, która ma zostać wypełniona tymi danymi, i przetestować zwracaną wartość dla kod błędu i obsłuż go przy każdym wywołaniu funkcji lub metody.
Jeśli kodujesz tak, że każda metoda wykonuje jedną i tylko jedną prostą rzecz, powinieneś zgłosić wyjątek, gdy metoda nie może osiągnąć pożądanego celu metody. Wyjątki są znacznie bogatsze i łatwiejsze w użyciu w ten sposób niż kody błędów. Twój kod jest znacznie bardziej przejrzysty - Standardowy przepływ „normalnej” ścieżki kodu może być poświęcony ściśle przypadkowi, w którym metoda JEST w stanie wykonać to, co chcesz, a następnie kod do wyczyszczenia lub obsługi „Wyjątkowe” okoliczności, w których dzieje się coś złego, co uniemożliwia pomyślne wykonanie metody, można oddzielić od normalnego kodu. Dodatkowo, jeśli nie możesz obsłużyć wyjątku, w którym wystąpił, i musisz przekazać go w górę stosu do interfejsu użytkownika (lub gorzej, przez przewód od składnika średniej warstwy do interfejsu użytkownika), to w przypadku modelu wyjątku
źródło
W przeszłości dołączyłem do obozu kodów błędów (zbyt dużo programowałem w C). Ale teraz zobaczyłem światło.
Tak, wyjątki są trochę obciążeniem dla systemu. Ale upraszczają kod, zmniejszając liczbę błędów (i WTF).
Więc używaj wyjątków, ale używaj ich mądrze. I będą twoimi przyjaciółmi.
Na marginesie. Nauczyłem się dokumentować, który wyjątek można zgłosić za pomocą jakiej metody. Niestety nie jest to wymagane w większości języków. Ale zwiększa szansę na obsługę właściwych wyjątków na odpowiednim poziomie.
źródło
Może zaistnieć kilka sytuacji, w których używanie wyjątków w czysty, jasny i prawidłowy sposób jest uciążliwe, ale zdecydowana większość wyjątków czasowych jest oczywistym wyborem. Największą zaletą obsługi wyjątków w przypadku kodów błędów jest to, że zmienia przepływ wykonywania, co jest ważne z dwóch powodów.
Gdy wystąpi wyjątek, aplikacja nie podąża już swoją „normalną” ścieżką wykonywania. Pierwszym powodem, dla którego jest to tak ważne, jest to, że jeśli autor kodu nie zrobi dobrze i naprawdę nie zrobi wszystko, aby być złym, program zatrzyma się i nie będzie kontynuował wykonywania nieprzewidywalnych rzeczy. Jeśli kod błędu nie zostanie sprawdzony, a odpowiednie działania nie zostaną podjęte w odpowiedzi na zły kod błędu, program będzie dalej robił to, co robi i kto wie, jaki będzie wynik tego działania. Jest wiele sytuacji, w których wykonanie programu „cokolwiek” może okazać się bardzo kosztowne. Rozważ program, który pobiera informacje o wynikach dla różnych instrumentów finansowych sprzedawanych przez firmę i dostarcza te informacje brokerom / hurtownikom. Jeśli coś pójdzie nie tak, a program będzie działał dalej, mogłoby to wysłać błędne dane dotyczące wyników do brokerów i hurtowników. Nie wiem o nikim innym, ale nie chcę być tym, który siedzi w biurze wiceprezesa i wyjaśnia, dlaczego mój kod spowodował, że firma otrzymała 7-cyfrowy mandat regulacyjny. Dostarczanie klientom komunikatów o błędach jest generalnie lepsze niż dostarczanie błędnych danych, które mogą wyglądać na „prawdziwe”, a ta ostatnia sytuacja jest znacznie łatwiejsza do wykonania przy znacznie mniej agresywnym podejściu, takim jak kody błędów.
Drugim powodem, dla którego lubię wyjątki i ich zerwanie z normalnym wykonywaniem, jest to, że znacznie, dużo łatwiej jest oddzielić logikę „normalnych rzeczy się dzieje” od logiki „coś poszło nie tak”. Dla mnie to:
... jest lepsze od tego:
Są też inne fajne rzeczy związane z wyjątkami. Posiadanie garści logiki warunkowej do śledzenia, czy którakolwiek z metod wywoływanych w funkcji zwróciła kod błędu, i zwraca ten kod błędu wyżej, to dużo błędów. W rzeczywistości jest to dużo płyt kotłowych, które mogą się nie udać. O wiele bardziej wierzę w system wyjątków w większości języków, niż w szczurzą grono stwierdzeń „jeśli jeszcze, jeśli-inaczej”, które napisał „Świeżo po studiach” Fred i mam o wiele lepsze rzeczy do zrobienia z moim czasem niż przeglądanie kodu wspomnianego gniazda szczurów.
źródło
Powinieneś użyć obu. Chodzi o to, aby zdecydować, kiedy użyć każdego z nich .
Istnieje kilka scenariuszy, w których wyjątki są oczywistym wyborem :
W niektórych sytuacjach nie możesz nic zrobić z kodem błędu i po prostu musisz obsłużyć go na wyższym poziomie w stosie wywołań , zwykle po prostu zarejestruj błąd, wyświetl coś użytkownikowi lub zamknij program. W takich przypadkach kody błędów wymagałyby ręcznego uzupełniania kodów błędów na poziomie, co jest oczywiście znacznie łatwiejsze w przypadku wyjątków. Chodzi o to, że dotyczy to nieoczekiwanych i trudnych do rozwiązania sytuacji.
Jednak w przypadku sytuacji 1 (gdy dzieje się coś nieoczekiwanego i nie do obsłużenia, po prostu nie chcesz tego zarejestrować), wyjątki mogą być pomocne, ponieważ możesz dodać informacje kontekstowe . Na przykład, jeśli otrzymam SqlException w moich pomocnikach danych niższego poziomu, będę chciał złapać ten błąd na niskim poziomie (gdzie znam polecenie SQL, które spowodowało błąd), aby móc przechwycić te informacje i ponownie przesłać z dodatkowymi informacjami . Zwróć uwagę na magiczne słowo: rzuć ponownie, a nie połykać . Pierwsza zasada obsługi wyjątków: nie połykaj wyjątków . Zwróć również uwagę, że mój wewnętrzny zaczep nie musi niczego rejestrować, ponieważ zewnętrzny zaczep będzie zawierał cały ślad stosu i może go rejestrować.
W niektórych sytuacjach masz sekwencję poleceń i jeśli którekolwiek z nich zawiedzie , powinieneś wyczyścić / pozbyć się zasobów (*), niezależnie od tego, czy jest to sytuacja nieodwracalna (która powinna zostać wyrzucona), czy sytuacja dająca się naprawić (w takim przypadku możesz obsłużyć lokalnie lub w kodzie dzwoniącego, ale nie potrzebujesz wyjątków). Oczywiście znacznie łatwiej jest umieścić wszystkie te polecenia za jednym razem, zamiast testować kody błędów po każdej metodzie i czyścić / usuwać w ostatnim bloku. Zwróć uwagę, że jeśli chcesz, aby błąd się wypalił (co prawdopodobnie jest tym, czego chcesz), nie musisz go nawet łapać - po prostu użyj ostatniego do czyszczenia / usuwania - powinieneś używać tylko catch / retrow, jeśli chcesz aby dodać informacje kontekstowe (patrz punktor 2).
Jednym z przykładów może być sekwencja instrukcji SQL wewnątrz bloku transakcji. Ponownie, jest to również sytuacja „nie do rozwiązania”, nawet jeśli zdecydujesz się ją wcześnie złapać (lecz lokalnie zamiast bulgotać do góry), nadal jest to fatalna sytuacja, w której najlepszym wynikiem jest przerwanie wszystkiego lub przynajmniej przerwanie dużego część procesu.
(*) To jest podobne do
on error goto
tego, którego używaliśmy w starym Visual BasicuW konstruktorach możesz zgłaszać tylko wyjątki.
To powiedziawszy, we wszystkich innych sytuacjach, w których zwracasz informacje, na temat których dzwoniący MOŻE / POWINIEN podjąć jakąś akcję , użycie kodów powrotnych jest prawdopodobnie lepszą alternatywą. Obejmuje to wszystkie oczekiwane „błędy” , ponieważ prawdopodobnie powinny być obsługiwane przez bezpośredniego wywołującego i prawie nie będą musiały być zwiększane zbyt wiele poziomów w stosie.
Oczywiście zawsze można traktować oczekiwane błędy jako wyjątki, a następnie natychmiast przechwytywać jeden poziom wyżej, a także można objąć każdą linię kodu w try catch i podjąć działania dla każdego możliwego błędu. IMO, to zły projekt, nie tylko dlatego, że jest dużo bardziej szczegółowy, ale szczególnie dlatego, że możliwe wyjątki, które mogą zostać wyrzucone, nie są oczywiste bez czytania kodu źródłowego - a wyjątki mogą być wyrzucane z dowolnej głębokiej metody, tworząc niewidoczne goto . Łamią strukturę kodu, tworząc wiele niewidocznych punktów wyjścia, które sprawiają, że kod jest trudny do odczytania i sprawdzenia. Innymi słowy, nigdy nie powinieneś używać wyjątków jako kontroli przepływu, ponieważ innym byłoby to trudne do zrozumienia i utrzymania. Zrozumienie wszystkich możliwych przepływów kodu do testowania może być nawet trudne.
Ponownie: w celu prawidłowego oczyszczenia / usunięcia możesz użyć try-last bez łapania czegokolwiek .
Najpopularniejsza krytyka dotycząca kodów powrotnych mówi, że „ktoś mógłby zignorować kody błędów, ale w tym samym sensie ktoś może również połknąć wyjątki. Zła obsługa wyjątków jest łatwa w obu metodach. Jednak pisanie dobrego programu opartego na kodzie błędów jest nadal znacznie łatwiejsze niż pisanie programu opartego na wyjątkach . A jeśli z jakiegoś powodu zdecydujesz się zignorować wszystkie błędy (stare
on error resume next
), możesz to łatwo zrobić za pomocą kodów powrotu i nie możesz tego zrobić bez wielu standardowych schematów try-catch.Drugą najpopularniejszą krytyką dotyczącą kodów powrotnych jest to, że „trudno jest wypalić” - ale to dlatego, że ludzie nie rozumieją, że wyjątki dotyczą sytuacji, których nie można odzyskać, podczas gdy kody błędów nie.
Wybór między wyjątkami a kodami błędów to szara strefa. Jest nawet możliwe, że musisz uzyskać kod błędu z jakiejś metody biznesowej wielokrotnego użytku, a następnie zdecydujesz się opakować go w wyjątek (prawdopodobnie dodając informacje) i pozwolić mu się rozwinąć. Ale błędem projektowym jest założenie, że WSZYSTKIE błędy powinny być odrzucane jako wyjątki.
Podsumowując:
Lubię używać wyjątków, gdy mam nieoczekiwaną sytuację, w której nie ma zbyt wiele do zrobienia, a zwykle chcemy przerwać duży blok kodu lub nawet całą operację lub program. To jest jak stare „przy błędzie goto”.
Lubię używać kodów powrotnych, gdy spodziewałem się sytuacji, w których kod dzwoniącego może / powinien podjąć jakieś działanie. Dotyczy to większości metod biznesowych, interfejsów API, walidacji i tak dalej.
Ta różnica między wyjątkami a kodami błędów jest jedną z zasad projektowania języka GO, który używa wyrażenia „panika” w przypadku krytycznych nieoczekiwanych sytuacji, podczas gdy zwykłe oczekiwane sytuacje są zwracane jako błędy.
Jednak w przypadku GO pozwala również na wiele zwracanych wartości , co jest czymś, co bardzo pomaga w używaniu kodów powrotu, ponieważ możesz jednocześnie zwrócić błąd i coś innego. W C # / Javie możemy to osiągnąć bez parametrów, krotek lub (moich ulubionych) typów generycznych, które w połączeniu z wyliczeniami mogą zapewnić wywołującemu wyraźne kody błędów:
Jeśli dodam nowy możliwy zwrot w mojej metodzie, mogę nawet sprawdzić wszystkich wywołujących, jeśli na przykład pokrywają tę nową wartość w instrukcji switch. Naprawdę nie możesz tego zrobić z wyjątkami. Korzystając z kodów zwrotnych, zazwyczaj znasz z wyprzedzeniem wszystkie możliwe błędy i je testujesz. Z wyjątkami zazwyczaj nie wiesz, co może się stać. Zawijanie wyliczeń wewnątrz wyjątków (zamiast Generics) jest alternatywą (o ile jest jasne, jaki typ wyjątków będzie generować każda metoda), ale IMO to nadal zły projekt.
źródło
Moje rozumowanie byłoby takie, jeśli piszesz sterownik niskiego poziomu, który naprawdę potrzebuje wydajności, a następnie użyj kodów błędów. Ale jeśli używasz tego kodu w aplikacji wyższego poziomu i może on obsłużyć trochę narzutów, opakuj ten kod interfejsem, który sprawdza te kody błędów i zgłasza wyjątki.
We wszystkich innych przypadkach prawdopodobnie najlepszym rozwiązaniem są wyjątki.
źródło
Może siedzę tu na płocie, ale ...
W Pythonie używanie wyjątków jest standardową praktyką i z przyjemnością definiuję własne wyjątki. W C nie masz żadnych wyjątków.
W C ++ (przynajmniej w STL) wyjątki są zwykle generowane tylko w przypadku naprawdę wyjątkowych błędów (sam ich praktycznie nigdy nie widzę). Nie widzę powodu, by robić cokolwiek innego we własnym kodzie. Tak, łatwo jest zignorować zwracane wartości, ale C ++ również nie wymusza wychwytywania wyjątków. Myślę, że po prostu musisz nabrać nawyku robienia tego.
Podstawą kodu, nad którym pracuję, jest głównie C ++ i używamy kodów błędów prawie wszędzie, ale jest jeden moduł, który zgłasza wyjątki dla każdego błędu, w tym bardzo nietypowych, a cały kod, który używa tego modułu, jest dość okropny. Ale może to być spowodowane tym, że pomieszaliśmy wyjątki i kody błędów. Kod, który konsekwentnie używa kodów błędów, jest znacznie łatwiejszy w obsłudze. Gdyby nasz kod konsekwentnie używał wyjątków, może nie byłoby tak źle. Mieszanie tych dwóch nie wydaje się działać tak dobrze.
źródło
Ponieważ pracuję z C ++ i mam RAII, aby były bezpieczne w użyciu, używam wyjątków prawie wyłącznie. Wyciąga obsługę błędów z normalnego przepływu programu i sprawia, że intencja jest jaśniejsza.
Jednak zostawiam wyjątki dla wyjątkowych okoliczności. Jeśli spodziewam się, że jakiś błąd będzie się często zdarzał, sprawdzę przed wykonaniem operacji, czy operacja się powiedzie, lub wywołam wersję funkcji, która zamiast tego używa kodów błędów (Lubię to
TryParse()
)źródło
Podpisy metod powinny informować o tym, co robi metoda. Coś w rodzaju long errorCode = getErrorCode (); może być w porządku, ale long errorCode = fetchRecord (); jest mylący.
źródło
Moje podejście jest takie, że możemy używać jednocześnie kodów wyjątków i błędów.
Jestem przyzwyczajony do definiowania kilku typów wyjątków (np .: DataValidationException lub ProcessInterruptExcepion), a wewnątrz każdego wyjątku definiuję bardziej szczegółowy opis każdego problemu.
Prosty przykład w Javie:
W ten sposób używam wyjątków do definiowania błędów kategorii i kodów błędów do definiowania bardziej szczegółowych informacji o problemie.
źródło
throw new DataValidationException("The input is too small")
? Jedną z zalet wyjątków jest umożliwienie szczegółowych informacji.Wyjątki dotyczą wyjątkowych okoliczności - tj. Gdy nie są one częścią normalnego przepływu kodu.
Dość zasadne jest mieszanie wyjątków i kodów błędów, gdzie kody błędów reprezentują stan czegoś, a nie błąd w działaniu kodu jako takiego (np. Sprawdzanie kodu powrotu z procesu potomnego).
Ale kiedy zdarzają się wyjątkowe okoliczności, uważam, że Wyjątki są najbardziej wyrazistym modelem.
Istnieją przypadki, w których wolisz lub musisz używać kodów błędów zamiast wyjątków i zostały one już odpowiednio omówione (inne niż inne oczywiste ograniczenia, takie jak obsługa kompilatora).
Ale idąc w innym kierunku, użycie wyjątków umożliwia tworzenie abstrakcji na jeszcze wyższym poziomie do obsługi błędów, co może uczynić Twój kod jeszcze bardziej wyrazistym i naturalnym. Gorąco polecam przeczytanie tego znakomitego, ale niedocenianego artykułu eksperta C ++ Andrei Alexandrescu na temat tego, co nazywa „Enforcements”: http://www.ddj.com/cpp/184403864 . Chociaż jest to artykuł w języku C ++, zasady mają ogólne zastosowanie i całkiem pomyślnie przetłumaczyłem koncepcję wymuszania na język C #.
źródło
Po pierwsze, zgadzam się z odpowiedzią Toma, że dla rzeczy wysokiego poziomu używaj wyjątków, a dla rzeczy niskiego poziomu używaj kodów błędów, o ile nie jest to architektura zorientowana na usługi (SOA).
W SOA, gdzie metody mogą być wywoływane na różnych maszynach, wyjątki nie mogą być przekazywane przez sieć, zamiast tego używamy odpowiedzi sukcesu / niepowodzenia o strukturze takiej jak poniżej (C #):
I użyj w ten sposób:
Gdy są one konsekwentnie używane w odpowiedziach usług, tworzy bardzo ładny wzorzec obsługi sukcesów / niepowodzeń w aplikacji. Umożliwia to łatwiejszą obsługę błędów w wywołaniach asynchronicznych w usługach, a także w usługach.
źródło
Wolałbym Wyjątki dla wszystkich przypadków błędów, z wyjątkiem sytuacji, gdy awaria jest oczekiwanym wynikiem działania funkcji, która zwraca pierwotny typ danych, bez błędów. Np. Znalezienie indeksu podciągu w większym ciągu zwykle zwróciło -1, jeśli nie zostanie znalezione, zamiast zgłosić NotFoundException.
Zwracanie nieprawidłowych wskaźników, które mogą być wyłuskane (np. Powodując wyjątek NullPointerException w Javie) jest niedopuszczalne.
Używanie wielu różnych numerycznych kodów błędów (-1, -2) jako wartości zwracanych dla tej samej funkcji jest zwykle niewłaściwym stylem, ponieważ klienci mogą wykonać sprawdzenie „== -1” zamiast „<0”.
Należy tutaj pamiętać o ewolucji interfejsów API w czasie. Dobre API pozwala zmieniać i rozszerzać zachowanie w przypadku awarii na kilka sposobów bez przerywania pracy klientów. Np. Jeśli uchwyt błędu klienta został sprawdzony pod kątem 4 przypadków błędów i dodasz piątą wartość błędu do swojej funkcji, program obsługi klienta może tego nie przetestować i zepsuć. Jeśli zgłosisz wyjątki, zwykle ułatwi to klientom migrację do nowszej wersji biblioteki.
Inną rzeczą do rozważenia jest praca w zespole, gdzie wyznaczyć jasną linię dla wszystkich programistów, aby podjęli taką decyzję. Np. „Wyjątki dla rzeczy wysokiego poziomu, kody błędów dla rzeczy niskiego poziomu” jest bardzo subiektywne.
W każdym przypadku, gdy możliwy jest więcej niż jeden trywialny typ błędu, kod źródłowy nie powinien nigdy używać literału numerycznego do zwracania kodu błędu lub do jego obsługi (powrót -7, jeśli x == -7 ...), ale zawsze nazwana stała (zwraca NO_SUCH_FOO, jeśli x == NO_SUCH_FOO).
źródło
Jeśli pracujesz w dużym projekcie, nie możesz używać tylko wyjątków lub tylko kodów błędów. W różnych przypadkach należy zastosować różne podejścia.
Na przykład decydujesz się używać tylko wyjątków. Ale gdy zdecydujesz się użyć przetwarzania zdarzeń asynchronicznych. W takich sytuacjach używanie wyjątków do obsługi błędów jest złym pomysłem. Ale używanie kodów błędów wszędzie w aplikacji jest żmudne.
Dlatego uważam, że jednoczesne używanie zarówno wyjątków, jak i kodów błędów jest normalne.
źródło
W przypadku większości aplikacji wyjątki są lepsze. Wyjątkiem jest sytuacja, gdy oprogramowanie musi komunikować się z innymi urządzeniami. Domena, w której pracuję, to kontrole przemysłowe. Tutaj kody błędów są preferowane i oczekiwane. Więc odpowiadam, że to zależy od sytuacji.
źródło
Myślę, że zależy to również od tego, czy naprawdę potrzebujesz informacji, takich jak ślad stosu z wyniku. Jeśli tak, zdecydowanie wybierz opcję Wyjątek, która dostarcza obiektowi wiele informacji o problemie. Jeśli jednak interesuje Cię tylko wynik i nie obchodzi Cię, dlaczego ten wynik, przejdź do kodu błędu.
np. kiedy przetwarzasz plik i napotykasz IOException, klient może być zainteresowany wiedzą, skąd to się stało, otwieraniem pliku lub analizowaniem pliku itp. Więc lepiej zwróć IOException lub jego konkretną podklasę. Jednak w scenariuszu takim, jak masz metodę logowania i chcesz wiedzieć, że zakończyła się sukcesem, czy nie, albo po prostu zwracasz wartość logiczną, albo aby wyświetlić poprawny komunikat, zwracasz kod błędu. Tutaj klient nie jest zainteresowany tym, która część logiki spowodowała ten kod błędu. Po prostu wie, czy jego poświadczenie jest nieprawidłowe lub blokada konta itp.
Innym przypadkiem, o którym przychodzi mi do głowy, jest przesyłanie danych w sieci. Twoja metoda zdalna może zwracać tylko kod błędu zamiast wyjątku, aby zminimalizować transfer danych.
źródło
Moja ogólna zasada brzmi:
źródło
Kody błędów również nie działają, gdy metoda zwraca coś innego niż wartość liczbowa ...
źródło