Pracuję jako wykonawca projektujący korporacyjną aplikację Java dla mojego klienta w roli lidera technicznego. Z aplikacji będą korzystać użytkownicy końcowi, a zespół wsparcia będzie obsługiwał aplikację, gdy wyjdziemy.
Inni techniczni potencjalni klienci, z którymi pracuję, mają wrażenie, że obsługa wyjątków spowoduje, że kod będzie brudny. System powinien zgłaszać sprawdzone wyjątki tylko z warstwy usługi, a reszta kodu powinna generować wyjątki czasu wykonywania ze wszystkich innych warstw, aby nie trzeba było obsługiwać niezaznaczonych wyjątków.
Jaka jest potrzeba rzucenia niesprawdzonego wyjątku w aplikacji biznesowej?
Z moich wcześniejszych doświadczeń na temat wyjątków czasu wykonywania:
1) Niesprawdzone wyjątki powodują, że kod jest nieprzewidywalny, ponieważ nie pojawiają się nawet w Javadoc.
2) Zgłaszanie niesprawdzonych wyjątków w aplikacji biznesowej nie ma sensu, ponieważ kiedy je rzucisz i trafi prosto w twarz użytkowników, jak wyjaśnisz to użytkownikowi? Widziałem dość aplikacji internetowej, która pokazuje, 500 -Internal Error. Contact Administrator
że nic nie znaczy dla użytkownika końcowego lub zespołu wsparcia zarządzającego aplikacją.
3) Zgłaszanie wyjątków środowiska wykonawczego zmusza użytkowników klasy zgłaszających wyjątek do przejścia przez kod źródłowy w celu debugowania i sprawdzenia, dlaczego wyjątek został zgłoszony. Można tego uniknąć tylko wtedy, gdy Javadoc wyjątku środowiska wykonawczego jest doskonale udokumentowany, co moim zdaniem nigdy nie jest przypadkiem.
źródło
@throws
tagiem, co jest dobrą praktyką.@throws
znacznika Javadoc, aby udokumentować każdy niesprawdzony wyjątek, który może zgłosić metoda, ale nie używaj słowa kluczowego throws, aby uwzględnić niesprawdzone wyjątki w deklaracji metody.Odpowiedzi:
Sprawdzone wyjątki są nieudanym przykładem projektu językowego. Zmuszają cię do posiadania bardzo nieszczelnych abstrakcji i brudnego kodu. Należy ich unikać w jak największym stopniu.
Co do twoich punktów:
1) Sprawdzone wyjątki powodują, że kod jest brudny i nie mniej nieprzewidywalny, ponieważ pojawiają się wszędzie .
2) W jaki sposób poprawiony wyjątek jest pokazywany użytkownikowi? Jedyna rzeczywista różnica między sprawdzonymi i niezaznaczonymi wyjątkami jest techniczna i wpływa tylko na kod źródłowy.
3) Czy słyszałeś kiedyś o śladach stosu? Mówią dokładnie, gdzie został zgłoszony wyjątek, bez względu na to, czy jest zaznaczony, czy niezaznaczony. W rzeczywistości sprawdzone wyjątki są zwykle gorsze przy debugowaniu, ponieważ często są zawijane, co prowadzi do dłuższych i brzydszych śladów na stosie, lub nawet całkowicie tracone, ponieważ zawijanie zostało wykonane nieprawidłowo.
Istnieją dwa rodzaje wyjątków: te, które występują „normalnie” i zwykle są obsługiwane bardzo blisko miejsca ich wystąpienia, oraz te, które są naprawdę wyjątkowe i mogą być obsługiwane ogólnie w bardzo wysokiej warstwie (po prostu przerwij bieżącą akcję i zaloguj ją / pokaż błąd).
Sprawdzone wyjątki stanowiły próbę umieszczenia tego rozróżnienia w składni języka w momencie zdefiniowania wyjątków. Problemy z tym są
źródło
SQLException extends Exception
oznacza, że wybranie rzutu,SQLException
ponieważ błąd ma związek z dostępem do bazy danych automatycznie oznacza, że wyjątek jest sprawdzany. I możesz udokumentować niezaznaczone wyjątki w komentarzach Javadoc. Działa dobrze dla wszystkich innych języków.Moim zdaniem, rodzaj zgłaszanego wyjątku zależy od tego, co robi twój kod.
Zgłaszam sprawdzone wyjątki, gdy spodziewam się, że mogą się zdarzać dość często (na przykład użytkownicy wprowadzają podejrzane dane) i oczekuję, że kod wywołujący zajmie się sytuacją.
Zgłaszam wyjątki od niesprawdzonych / uruchomieniowych wyjątków (nie tak często, jak sprawdzane), gdy mam rzadką sytuację, w której nie oczekuję obsługi kodu wywołującego. Przykładem może być jakiś dziwny błąd związany z pamięcią, którego nigdy się nie spodziewam. Niezaznaczone są rodzaje błędów, które mogą sprowadzić aplikację.
Przed użytkownikiem nie powinien pojawiać się żaden wyjątek bez pewnego poziomu wsparcia. Nawet jeśli jest to tylko „proszę wyciąć i wkleić ten zrzut błędu do wiadomości e-mail”. Nic nie jest bardziej irytujące dla użytkownika niż informacja o błędzie, ale nie podano mu żadnych szczegółów ani działań, które można podjąć, aby go naprawić.
Domyślam się, że filozofia, o której wspominasz, pochodzi z jednego z dwóch źródeł:
źródło
Jeśli nie chcesz odznaczonych wyjątków czasu wykonywania, dlaczego używasz Java? Istnieje możliwość zastosowania wyjątków czasu wykonywania prawie wszędzie - w szczególności NullPointerException, ArithmeticException, ArrayIndexOutOfBounds itp.
A kiedy raz przeczytasz pliki dziennika jakiegoś systemu J2EE, na przykład instalacji SAP NetWeaver, zobaczysz, że takie wyjątki zdarzają się dosłownie cały czas.
źródło
Jest kilka zasad postępowania z wyjątkami, o których należy pamiętać. Ale najpierw musisz pamiętać, że wyjątki są częścią interfejsu ujawnionego przez kod; udokumentuj je . Jest to szczególnie ważne, gdy interfejs jest publiczny, ale jest to bardzo dobry pomysł również w przypadku prywatnych interfejsów.
Wyjątki powinny być obsługiwane tylko w punkcie, w którym kod może zrobić z nimi coś sensownego. Najgorszą opcją obsługi jest nic nie robić na ich temat, co należy zrobić tylko wtedy, gdy jest to dokładnie właściwa opcja. (Kiedy mam taką sytuację w swoim kodzie, dołączam komentarz do tego efektu, aby nie martwić się o puste ciało).
Drugą najgorszą opcją jest zgłoszenie niepowiązanego wyjątku bez dołączenia oryginału jako przyczyny. Problem polega na tym, że informacje zawarte w oryginalnym wyjątku, które umożliwiłyby zdiagnozowanie problemu, zostały utracone; tworzysz coś, z czym nikt nie może nic zrobić (poza narzekaniem, że „to nie działa” i wszyscy wiemy, jak nienawidzimy tych zgłoszeń błędów).
Znacznie lepiej jest rejestrować wyjątek. To pozwala komuś dowiedzieć się, na czym polega problem i go naprawić, ale należy rejestrować wyjątek tylko w punkcie, w którym zostałby utracony lub zgłoszony przez połączenie zewnętrzne. Nie dzieje się tak dlatego, że częstsze rejestrowanie jest poważnym problemem jako takim, ale dlatego, że nadmierne rejestrowanie oznacza, że dziennik zajmuje więcej miejsca i nie zawiera więcej informacji. Po zarejestrowaniu wyjątku możesz z czystym sumieniem zgłosić klientowi / klientowi précis (o ile podasz również czas wygenerowania - lub inny identyfikator korelacji) w tym raporcie, aby można było dopasować krótką wersję w razie potrzeby ze szczegółami).
Najlepszą opcją jest oczywiście całkowite obsłużenie wyjątku, zajmując się sytuacją błędu w całości. Jeśli możesz to zrobić, zrób to! Może to nawet oznaczać, że można uniknąć konieczności rejestrowania wyjątku.
Jednym ze sposobów obsługi wyjątku jest zgłoszenie innego wyjątku, który zapewnia opis problemu na wyższym poziomie (np. „
failed to initialize
” Zamiast „index out of bounds
”). Jest to dobry wzorzec, o ile nie stracisz informacji o przyczynie wyjątku; użyj szczegółowego wyjątku, aby zainicjować wyjątekcause
wyższego poziomu lub zapisz szczegóły (jak omówiono powyżej). Rejestrowanie jest najbardziej odpowiednie, gdy masz zamiar przekroczyć granicę międzyprocesową, na przykład wywołanie IPC, ponieważ nie ma gwarancji, że klasa wyjątków niskiego poziomu będzie w ogóle obecna na drugim końcu połączenia. Zachowanie się jako dołączonej przyczyny jest najbardziej odpowiednie podczas przekraczania wewnętrznej granicy.Kolejny wzorzec, który widzisz, to catch-and-release:
Jest to anty-wzorzec, chyba że masz ograniczenia typu z innych
catch
klauzul, co oznacza, że nie możesz po prostu pozwolić, by wyjątek przeszedł sam. To po prostu brzydka funkcja Java.Nie ma prawdziwej różnicy między sprawdzonymi wyjątkami a niesprawdzonymi, oprócz faktu, że musisz zadeklarować sprawdzone wyjątki, które przekraczają granice metod. Nadal dobrym pomysłem jest dokumentowanie niesprawdzonych wyjątków (z
@throws
komentarzem javadoc), jeśli wiesz, że są one celowo wyrzucane przez Twój kod. Nie celowo wrzucajjava.lang.Error
ani jego podklas (chyba że piszesz implementację JVM).Opinia: Nieoczekiwany przypadek błędu zawsze oznacza błąd w kodzie. Sprawdzone wyjątki są sposobem na zarządzanie tym zagrożeniem, a tam gdzie programiści celowo wykorzystują niesprawdzone wyjątki jako sposób na uniknięcie kłopotów z obsługą przypadków błędów, narastają spory dług techniczny, który będziesz musiał oczyścić przez pewien czas jeśli chcesz solidny kod. Obsługa niechlujnych błędów jest nieprofesjonalna (a spojrzenie na obsługę błędów jest dobrym sposobem na określenie, jak dobry jest naprawdę programista).
źródło
Myślę, że powinieneś rzucić TYLKO sprawdzony wyjątek, gdy aplikacja może odzyskać. Użytkownicy twojej biblioteki muszą więc wychwycić te wyjątki i zrobić wszystko, co trzeba, aby je odzyskać. Cokolwiek innego powinno być odznaczone.
Jako przykład
Jeśli aplikacja ładuje dane z pliku lub bazy danych. Następnie,..
osoba dzwoniąca zawsze może złapać zaznaczony MissingDataFileException, a następnie spróbować załadować dane z bazy danych.
źródło