Sprawdzone wyjątki Javy zyskały złą prasę przez lata. Znamiennym znakiem jest to, że jest to dosłownie jedyny język na świecie, który je ma (nawet inne języki JVM, takie jak Groovy i Scala). Wybitne biblioteki Java, takie jak Spring i Hibernate, również ich nie używają.
Osobiście znalazłem dla nich jedno zastosowanie ( w logice biznesowej między warstwami), ale poza tym jestem wyjątkowym sprawdzonym wyjątkiem.
Czy są inne zastosowania, o których nie wiem?
java
exceptions
errors
Brad Cupit
źródło
źródło
Odpowiedzi:
Przede wszystkim, jak każdy inny paradygmat programowania, musisz zrobić to dobrze, aby działał dobrze.
Dla mnie zaletą sprawdzonych wyjątków jest to, że autorzy biblioteki wykonawczej Java JUŻ zdecydowali dla mnie, jakie typowe problemy można racjonalnie oczekiwać w punkcie wywoływania (w przeciwieństwie do najwyższego poziomu catch-print- die block) i jak najwcześniej zastanowić się, jak poradzić sobie z tymi problemami.
Lubię sprawdzone wyjątki, ponieważ zwiększają one niezawodność mojego kodu, zmuszając mnie do jak najwcześniejszego zastanowienia się nad odzyskiwaniem błędów.
Aby być bardziej precyzyjne, aby mi to sprawia, że mój kod bardziej wydajny, ponieważ zmusza mnie do rozważenia dziwne przypadki narożne bardzo wcześnie w procesie, w przeciwieństwie do powiedzenie „Ups, mój kod nie poradzić, jeśli plik nie istnieje jeszcze” na podstawie błąd w produkcji, który następnie trzeba przerobić kod, aby go obsłużyć. Dodanie obsługi błędów do istniejącego kodu może być trywialnym zadaniem - a zatem kosztownym - podczas przeprowadzania konserwacji, a nie tylko od samego początku.
Może się okazać, że brakuje pliku jest śmiertelną rzeczą i powinno spowodować, że program przestanie działać w płomieniach, ale potem ty podjąć tę decyzję z
To także pokazuje bardzo ważny efekt uboczny. Jeśli wstawisz wyjątek, możesz dodać wyjaśnienie, które znajduje się w pliku śledzenia ! Jest to bardzo potężne, ponieważ możesz dodać informacje np. O nazwie brakującego pliku, parametrach przekazanych do tej metody lub innych informacjach diagnostycznych, a informacje te są obecne bezpośrednio w śladzie stosu, który często jest jedną rzeczą dostać się, gdy program się zawiesił.
Ludzie mogą powiedzieć „możemy po prostu uruchomić to w debuggerze w celu odtworzenia”, ale odkryłem, że bardzo często błędy produkcyjne nie mogą być później odtworzone i nie możemy uruchamiać debugerów w produkcji, z wyjątkiem bardzo paskudnych przypadków, w których w grę wchodzi Twoja praca.
Im więcej informacji w stosie śledzenia, tym lepiej. Sprawdzone wyjątki pomagają mi zdobyć te informacje tam wcześnie.
EDYCJA: Dotyczy to również projektantów bibliotek. Jedna biblioteka, z której korzystam na co dzień, zawiera wiele sprawdzonych wyjątków, które można by zaprojektować o wiele lepiej, dzięki czemu korzystanie z niej jest mniej uciążliwe.
źródło
Masz dwie dobre odpowiedzi, które wyjaśniają, jakie sprawdzone wyjątki stały się w praktyce. (+1 do obu.) Ale warto byłoby również zbadać, do czego były przeznaczone w teorii, ponieważ intencja jest naprawdę opłacalna.
Zaznaczone wyjątki mają na celu zwiększenie bezpieczeństwa języka. Rozważ prostą metodę, taką jak mnożenie liczb całkowitych. Możesz myśleć, że typem wyniku tej metody byłaby liczba całkowita, ale, ściśle mówiąc, wynikiem jest albo liczba całkowita, albo wyjątek przepełnienia. Biorąc pod uwagę wynik całkowity sam w sobie, ponieważ typ zwracany przez metodę nie wyraża pełnego zakresu funkcji.
Patrząc w tym świetle, nie jest prawdą stwierdzenie, że sprawdzone wyjątki nie trafiły do innych języków. Po prostu nie przyjęli formy używanej przez Javę. W aplikacjach Haskell często stosuje się algebraiczne typy danych, aby rozróżnić pomyślne i nieudane zakończenie funkcji. Chociaż nie jest to sam w sobie wyjątek, intencja jest bardzo podobna do sprawdzonego wyjątku; jest to interfejs API zaprojektowany, aby zmusić konsumenta API do obsługi zarówno sukcesu w przypadku niepowodzenia, np .:
To informuje programistę, że funkcja ma dwa dodatkowe możliwe wyniki oprócz sukcesu.
źródło
IMO, sprawdzone wyjątki są wadliwą implementacją czegoś, co mogłoby być całkiem przyzwoitym pomysłem (w zupełnie innych okolicznościach - ale tak naprawdę nie jest nawet dobrym pomysłem w obecnych okolicznościach).
Dobrym pomysłem jest to, że dobrze byłoby, gdyby kompilator sprawdził, czy wszystkie wyjątki, które program może wyrzucić, zostaną wychwycone. Wadliwa implementacja polega na tym, że aby to zrobić, Java zmusza cię do radzenia sobie z wyjątkiem bezpośrednio w dowolnej klasie wywołującej wszystko, co zadeklarowano, aby zgłosić wyjątek sprawdzony. Jednym z najbardziej podstawowych pomysłów (i zalet) obsługi wyjątków jest to, że w przypadku błędu pozwala pośrednim warstwom kodu, które nie mają nic wspólnego z konkretnym błędem, całkowicie zignorować jego istnienie. Sprawdzone wyjątki (zaimplementowane w Javie) nie pozwalają na to, a zatem niszczą główną (podstawową?) Zaletę obsługi wyjątków na początek.
Teoretycznie mogliby sprawić, by sprawdzone wyjątki były przydatne, wymuszając je tylko na poziomie całego programu - tzn. Podczas „budowania” programu buduj drzewo wszystkich ścieżek sterowania w programie. Różne węzły w drzewie będą opatrzone adnotacjami z 1) wyjątkami, które mogą wygenerować, i 2) wyjątkami, które mogą wychwycić. Aby upewnić się, że program był poprawny, chodzisz po drzewie, sprawdzając, czy każdy wyjątek zgłoszony na dowolnym poziomie drzewa został przechwycony na wyższym poziomie w drzewie.
Powodem, dla którego tego nie zrobili (i tak sądzę), jest to, że byłoby to niezwykle trudne - w rzeczywistości wątpię, aby ktokolwiek napisał system kompilacji, który mógłby to zrobić dla czegoś innego niż niezwykle proste (graniczy z „zabawką” „) języki / systemy. W przypadku Javy rzeczy takie jak dynamiczne ładowanie klas czynią to jeszcze trudniejszym niż w wielu innych przypadkach. Co gorsza (w przeciwieństwie do C) Java nie jest (przynajmniej normalnie) statycznie kompilowana / powiązana z plikiem wykonywalnym. Oznacza to, że nic w systemie nie ma tak naprawdę globalnej świadomości, aby nawet próbować wykonać takie egzekwowanie, dopóki użytkownik końcowy nie zacznie faktycznie ładować programu, aby go uruchomić.
Wykonanie egzekucji w tym momencie jest niepraktyczne z kilku powodów. Przede wszystkim, nawet w najlepszym przypadku wydłużyłoby czas uruchamiania, które są już jedną z największych, najczęstszych skarg na Javę. Po drugie, aby zrobić wiele dobrego, naprawdę musisz wykryć problem wystarczająco wcześnie, aby programista mógł go naprawić. Gdy użytkownik ładuje program, jest już za późno, aby zrobić wiele dobrego - jedyne, co możesz zrobić, to zignorować problem lub w ogóle odmówić załadowania / uruchomienia programu, ponieważ istnieje ryzyko, że może istnieć wyjątek to nie zostało złapane.
W tej chwili sprawdzone wyjątki są gorsze niż bezużyteczne, ale alternatywne projekty sprawdzonych wyjątków są jeszcze gorsze. Chociaż podstawowy pomysł na sprawdzone wyjątki wydaje się dobry, to naprawdę nie jest zbyt dobry i okazuje się, że jest szczególnie nieodpowiedni dla Javy. W przypadku czegoś takiego jak C ++, który zwykle jest kompilowany / łączony w kompletny plik wykonywalny z niczym innym, jak odbiciem / dynamicznym ładowaniem klas, miałbyś trochę większą szansę (choć, szczerze mówiąc, nawet wtedy egzekwując je poprawnie bez tego samego bałaganu, jaki oni obecnie przyczyna w Javie prawdopodobnie nadal wykraczałaby poza obecny stan wiedzy).
źródło
UnexpectedException
typ pochodzący zRuntimeException
. Zauważ, że „rzuty” i „nie oczekują” nie są sprzeczne; jeślifoo
rzucaBozException
i sprawdzabar
, to nie znaczy, że oczekujebar
rzutuBozException
.Są naprawdę dobre dla irytujących programistów i zachęcania do połykania wyjątków. Połowa punktów wyjątków polega na tym, że masz rozsądny domyślny sposób obsługi błędów i nie musisz myśleć o jawnym propagowaniu warunków błędów, z którymi nie możesz sobie poradzić. (Rozsądnym domyślnym jest fakt, że jeśli nigdy nie poradzisz sobie z błędem nigdzie w swoim kodzie, skutecznie zapewniłeś, że nie może się to zdarzyć, i masz rozsądne wyjście i ślad stosu, jeśli się mylisz.) Sprawdzone wyjątki pokonane to. Czują, że muszą jawnie propagować błędy w C.
źródło
throws FileNotFoundException
. Hard fix:catch (FileNotFoundException e) { throw RuntimeException(e); }
Myślę, że można śmiało powiedzieć, że sprawdzone wyjątki były trochę nieudanym eksperymentem. To, co popełnili błąd, to to, że zerwali warstwy:
Ładne rozdzielenie zainteresowanych zostało zerwane, ponieważ teraz wiedza o błędach, które mogły być ograniczone do A i C, teraz musi zostać rozrzucona na B.
Jest miła dyskusja sprawdzonych wyjątków na Wikipedia.
A Bruce Eckel również ma fajny artykuł na ten temat. Oto cytat:
Uważam, że w przypadku C ++, jeśli wszystkie metody mają
throws
klauzulę specyfikacji, możesz mieć jakieś fajne optymalizacje. Nie sądzę jednak, żeby Java mogła mieć te zalety, ponieważRuntimeExceptions
nie są sprawdzane. W każdym razie nowoczesny JIT powinien być w stanie zoptymalizować kod.Jedną z fajnych cech AspectJ jest zmiękczanie wyjątków: możesz zamienić sprawdzone wyjątki w niesprawdzone wyjątki, szczególnie w celu zwiększenia warstw.
Być może to ironia losu, że Java przeszła przez te wszystkie kłopoty, gdy mogła
null
zamiast tego sprawdzić , co mogło być o wiele bardziej wartościowe .źródło
Kocham wyjątki.
Ciągle jednak jestem oszołomiony ich niewłaściwym użyciem.
Nie używaj ich do obsługi przepływu. Nie chcesz kodu, który próbuje coś zrobić i używa wyjątku jako wyzwalacza do zrobienia czegoś innego, ponieważ Wyjątki to obiekty, które trzeba utworzyć i użyć pamięci itp. Tylko dlatego, że nie mogłeś mieć kłopotów z napisaniem czegoś rodzaj sprawdzania if () przed wykonaniem połączenia. To jest po prostu leniwe i nadaje chwalebnemu wyjątkowi złe imię.
Nie połykaj ich. Zawsze. Pod żadnym pozorem. Jako absolutne minimum należy umieścić coś w pliku dziennika, aby wskazać, że wystąpił wyjątek. Próba śledzenia drogi przez kod, który połyka wyjątki, jest koszmarem. Ponownie, przeklnijcie połykaczy wyjątków za sprowadzenie potężnego wyjątku na kompromitację!
Traktuj wyjątki w czapce OO. Twórz własne obiekty wyjątków z sensownymi hierarchiami. Nakładaj na siebie logikę biznesową i wyjątki. Kiedyś odkrywałem, że gdybym zaczął na nowym obszarze systemu, potrzebowałbym podklasy wyjątków w ciągu pół godziny od kodowania, więc teraz zaczynam od pisania klas wyjątków.
Jeśli piszesz „ramowe” bity kodu, upewnij się, że wszystkie początkowe interfejsy są napisane, aby w razie potrzeby tworzyć własne wyjątki ... i upewnij się, że kodery mają jakiś przykładowy kod w miejscu, co należy zrobić, gdy ich kod zgłasza wyjątek IOException, ale interfejs, do którego piszą, chce zgłosić wyjątek „ReportingApplicationException”.
Po zastanowieniu się, jak sprawić, by Wyjątki działały dla Ciebie, nigdy nie będziesz oglądać się za siebie.
źródło
initCause
lub zainicjuj wyjątek z wyjątkiem, który go spowodował. Przykład: Masz narzędzie we / wy, którego potrzebujesz tylko w przypadku niepowodzenia zapisu. Istnieje jednak wiele powodów, dla których zapis może się nie powieść (nie można uzyskać dostępu, błąd zapisu itp.). Zrzuć niestandardowy wyjątek z tego powodu, aby oryginalny problem nie został połknięty.Sprawdzone wyjątki są również w ADA.
(Uwaga, ten post zawiera silne przekonania, z którymi możesz się spotkać.)
Programiści ich nie lubią i narzekają lub piszą kod połykania wyjątków.
Istnieją sprawdzone wyjątki, ponieważ rzeczy mogą nie tylko nie działać, możesz przeprowadzić analizę trybu / efektów awarii i ustalić to z góry.
Odczyty plików mogą się nie powieść. Wywołania RPC mogą zakończyć się niepowodzeniem. Sieć IO może zawieść. Dane mogą być źle sformatowane podczas analizowania.
„Szczęśliwa ścieżka” dla kodu jest łatwa.
Znałem faceta z uniwersytetu, który potrafiłby napisać świetny kod „happy path”. Żaden z przypadków na krawędzi nigdy nie zadziałał. Obecnie robi Python dla firmy open source. Powiedział Nuff.
Jeśli nie chcesz obsługiwać sprawdzonych wyjątków, naprawdę mówisz
Tak więc sprawdzone wyjątki nie będą spodobały się programistom, ponieważ oznacza to więcej pracy.
Oczywiście inni ludzie mogliby chcieć, aby ta praca została wykonana.
Być może chcieli właściwej odpowiedzi, nawet jeśli serwer plików ulegnie awarii / pamięć USB umrze.
Dziwne jest przekonanie w społeczności programistów, że powinieneś używać języka programowania, który ułatwia ci życie i sprawia ci przyjemność, gdy twoja praca polega na pisaniu oprogramowania. Twoim zadaniem jest rozwiązanie czyjegoś problemu, nie dopuszczenie do zautomatyzowanej jazzowej improwizacji.
Jeśli jesteś programistą amatorem (nie programujesz dla pieniędzy), możesz programować w C # lub innym języku bez sprawdzonych wyjątków. Heck, wytnij środkowego mężczyznę i program w Logo. Za pomocą żółwia możesz rysować ładne wzory na podłodze.
źródło
Sprawdzone wyjątki powinny zachęcać ludzi do radzenia sobie z błędami w pobliżu źródła. Im dalej od źródła, tym więcej funkcji zakończyło się w trakcie działania i tym bardziej prawdopodobne jest, że system przejdzie w niespójny stan. Ponadto jest bardziej prawdopodobne, że przypadkowo złapiesz niewłaściwy wyjątek.
Niestety ludzie lubili ignorować wyjątki lub dodawać coraz wyższe specyfikacje rzutów. Oba nie mają sensu zachęcać sprawdzone wyjątki. Są jak transformacja kodu proceduralnego, aby korzystać z wielu funkcji Gettera i Settera, co rzekomo czyni go OO.
Zasadniczo sprawdzone wyjątki próbują wykazać pewien stopień poprawności w kodzie. Jest to prawie taki sam pomysł jak pisanie statyczne, ponieważ próbuje udowodnić, że pewne rzeczy są poprawne, zanim nawet uruchomi się kod. Problem polega na tym, że cały ten dodatkowy dowód wymaga wysiłku i czy wysiłek jest opłacalny?
źródło