Czy bloki catch powinny być używane do zapisywania logiki, tj. Obsługi kontroli przepływu itp.? A może po prostu rzucać wyjątki? Czy wpływa to na wydajność lub łatwość konserwacji kodu?
Jakie są skutki uboczne (jeśli występują) logiki pisania w bloku catch?
EDYTOWAĆ:
Widziałem klasę Java SDK, w której zapisali logikę w bloku catch. Na przykład (fragment kodu pobrany z java.lang.Integer
klasy):
try {
result = Integer.valueOf(nm.substring(index), radix);
result = negative ? new Integer(-result.intValue()) : result;
} catch (NumberFormatException e) {
String constant = negative ? new String("-" + nm.substring(index))
: nm.substring(index);
result = Integer.valueOf(constant, radix);
}
EDYCJA 2 :
Przechodziłem samouczek, w którym liczą to jako zaletę pisania logiki wyjątkowych przypadków w wyjątkach:
Wyjątki pozwalają napisać główny przepływ kodu i poradzić sobie z wyjątkowymi przypadkami gdzie indziej.
Jakieś konkretne wskazówki, kiedy pisać logikę w bloku catch, a kiedy nie?
java
programming-practices
exceptions
HashimR
źródło
źródło
Odpowiedzi:
Przytoczony przez ciebie przykład wynika z kiepskiego projektu API (nie ma czystego sposobu na sprawdzenie, czy String jest prawidłową liczbą całkowitą, z wyjątkiem próby jego przeanalizowania i wyłapania wyjątku).
Na poziomie technicznym rzut i try / catch to konstrukcje sterowania przepływem, które pozwalają przeskoczyć stos wywołań, nic więcej i nic mniej. Przeskakiwanie stosu wywołań niejawnie łączy kod, który nie jest blisko siebie w źródle, co jest niekorzystne z uwagi na łatwość konserwacji . Dlatego należy go używać tylko wtedy, gdy trzeba to zrobić, a alternatywy są jeszcze gorsze. Powszechnie akceptowane przypadek gdzie alternatywy są gorsze jest obsługa błędów (specjalne kody powrotne, które muszą być sprawdzone i mijały się każdy poziom stosu wywołań ręcznie).
Jeśli masz przypadek, w którym alternatywy są gorsze (i naprawdę dokładnie rozważyłeś je wszystkie), powiedziałbym, że użycie rzutowania i próbowania / łapania dla kontroli przepływu jest w porządku. Dogmat nie jest dobrym substytutem osądu.
źródło
Jest to coś, co zwykle zależy od języka i paradygmatu.
Większość mojej pracy jest wykonywana w Javie (a czasem w C ++). Często stosuje się wyjątki tylko w wyjątkowych warunkach. Istnieją pewne pytania dotyczące przepełnienia stosu dotyczące narzutu wydajności wyjątków w Javie , i jak widać, nie jest to wcale nieistotne. Istnieją również inne obawy, takie jak czytelność i łatwość konserwacji kodu. Przy prawidłowym użyciu wyjątki mogą przekazywać obsługę błędów odpowiednim komponentom.
Jednak w Pythonie panuje idea, że łatwiej jest prosić o wybaczenie niż pozwolenie. W społeczności Python jest to znane jako EAFP , co kontrastuje z podejściem „patrz przed skokiem” ( LBYL ) w językach w stylu C.
źródło
To nie jest najlepszy sposób myślenia o blokach try / catch. Sposób myślenia o blokach try / catch jest następujący: nastąpiła awaria, gdzie jest najlepsze miejsce, aby poradzić sobie z TYM konkretnym niepowodzeniem. To może być następny wiersz kodu, może być dwadzieścia poziomów w górę łańcucha połączeń. Gdziekolwiek to jest, tam właśnie powinno być.
To, co robi blok catch, zależy od błędu i tego, co możesz z tym zrobić. Czasami można go po prostu zignorować (brak usunięcia pliku scratch bez nieistotnych danych), czasem zostanie użyty do ustawienia wartości zwracanej funkcji na true lub false (metoda analizy java), czasem wyjdziesz z programu . Wszystko zależy od błędu.
Ważną częścią do zrozumienia jest: catch block == Wiem, jak sobie z tym poradzić.
źródło
Bloków połowowych należy używać wyłącznie do obsługi wyjątków, nic więcej i nigdy do kontroli przepływu. W każdej sytuacji, w której chcesz zastosować wyjątki do zarządzania przepływem, lepiej byłoby sprawdzić warunki wstępne.
Obsługa przepływu z wyjątkami jest powolna i semantycznie niepoprawna.
źródło
Po pierwsze, zapomnij o idei, że „wyjątki należy stosować w wyjątkowych warunkach”. Przestań też martwić się o wydajność, dopóki nie będziesz mieć kodu, który działa nieakceptowalnie, i nie będziesz mierzył, gdzie leży problem.
Kod jest najłatwiejszy do zrozumienia, gdy działania następują w prostej sekwencji, bez warunków warunkowych. Wyjątki poprawiają łatwość konserwacji poprzez usunięcie sprawdzania błędów z normalnego przepływu. Nie ma znaczenia, czy wykonanie przebiega normalnie przez 99,9% czasu, czy 50% czasu, czy 20% czasu.
Zgłaszaj wyjątek, gdy funkcja nie może zwrócić wartości, procedura nie może zakończyć oczekiwanej akcji lub gdy konstruktor nie jest w stanie wytworzyć użytecznego obiektu. Pozwala to programistom założyć, że funkcja zawsze zwraca przydatny wynik, procedura zawsze kończy żądaną akcję, a skonstruowany obiekt jest zawsze w użytecznym stanie.
Największym problemem, jaki widzę z kodem obsługi wyjątków, jest to, że programiści piszą bloki try / catch, kiedy nie powinni. Na przykład w większości aplikacji internetowych, jeśli żądanie bazy danych zgłasza wyjątek, nic nie można zrobić w kontrolerze. Wystarczy jedna ogólna klauzula połowowa na najwyższym poziomie. Następnie kod kontrolera może błogo zignorować możliwość awarii dysku lub baza danych jest w trybie offline lub cokolwiek innego.
źródło
Bloki catch nie powinny być używane do pisania logiki kodu. Powinny być używane tylko do obsługi błędów. Przykładem jest (1) oczyszczenie wszystkich przydzielonych zasobów, (2) wydrukowanie przydatnego komunikatu i (3) wyjście z gracją.
To prawda, że wyjątki mogą być nadużywane i powodować niepożądane
goto
skutki. Ale to nie czyni ich bezużytecznymi. Przy właściwym użyciu mogą poprawić wiele aspektów twojego kodu.źródło