Jaki jest sens wyrzucać wyjątki (throw exception) ?

Jaki jest sens wyrzucać wyjątki (throw exception) ?
Julian_
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 4 lata
  • Postów:1703
0

skoro to samo można obsłużyć ifami?

W R nie ma czegoś takiego, we wszystkich bibliotekach studenci lecą ifami, albo jak jakiś wirutuoz się trafi to czasem try {} catch {} użyje, dlatego nie rozumiem koncepcji Javy.

edytowany 2x, ostatnio: Julian_
matt_z
  • Rejestracja:ponad 8 lat
  • Ostatnio:ponad 7 lat
  • Postów:56
3

Tak, można obejść się bez wyjątków.
Nie, IFy nie starczą.

Wyobraź sobie metodę ```
String readFromFile(filename) throws IOException

Kopiuj
Metoda zwraca Stringa - zawartość pliku.

Bez wyjątków musisz zwrócić Stringa i kod błędu. Do tego mieć gdzieś informacje co dany kod błędu oznacza (brak pliku, brak dostępu itd.). Czyli byś musiał zwrócić klasę, która ma różne elementy (String i ew. kod błędu).
Wyjątki są bardziej czytelne i bardziej eleganckie.

Coś jak z pętlą for i while. Możesz używać tylko jednej, ale czasami bardziej czytelnie jest użyć obydwu.



V-2
  • Rejestracja:około 8 lat
  • Ostatnio:11 miesięcy
  • Postów:671
0

Wyjątki są bardziej czytelne i bardziej eleganckie.

Polemizowałbym.


Nie ma najmniejszego powodu, aby w CV pisać "email" przed swoim adresem mailowym, "imię i nazwisko" przed imieniem i nazwiskiem, ani "zdjęcie mojej głowy od przedniej strony" obok ewentualnego zdjęcia. W drugiej firmie której już pracuję mam palących marihuanę programistów [...] piszą kod "leniwie", często nie wysilając się, rozwlekając ten kod, unikając np. programowania funkcyjnego (mówię tutaj o lambdach w javie).
Julian_
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 4 lata
  • Postów:1703
0

a w praktyce to co częściej można spotkać w profesjonalnych aplikacjach korpo?

V-2
Praktyka a elegancja to rozbieżne kategorie : )
SZ
  • Rejestracja:około 11 lat
  • Ostatnio:ponad 4 lata
  • Postów:616
0

Wyjątki, nie wiem jak chcesz zrobić to na ifach. Wyjątek ma tą zaletę, że przerywa aktualne przetwarzanie i wyskakuje do najbliższej sekcji try/catch.
Wyobraź sobie wywołanie 100 metod w głąb i teraz na samym dole jest błąd.....

V-2
No właśnie, wyjątek to takie goto, którym można przelecieć przez pół świata, co nie sprzyja czytelności. Na dodatek wiele nieprawidłowych stanów nie ma wcale charakteru "wyjątkowego", i stosowanie exception jako wytrychu jest kuszącym, ale nadużyciem. Choćby wszelkiego rodzaju walidacje danych. Zdrowiej jest w takich przypadkach użyć czegoś innego niż wyjątku - choćby właśnie obiektu reprezentującego błąd.
1

Wyjątki, nie wiem jak chcesz zrobić to na ifach.

Normalnie, dać Maybe albo Either, techniczne to nawet haskell ma try catcha dla "nieczystego" kodu ale w "czystym" kodzie nie ma sensu rzucania wyjątków.

V-2
Do myślenia powinna też dać taka alternatywa, jak konwencja obsługi błędów w RxJavie (czym można oczywiście opakować "oldskulową" sygnalizację błędów opartą o wyjątkach)
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Wyjątek może wylecieć bardzo wysoko. Obstawienie tego ifami czy za pomocą Either sprawdza się tylko dla czegoś takiego jak checked exceptions, bo te zwykle obsługuje bardzo blisko. Ale jak nagle stanie sie coś faktycznie niespodziewanego to zwykle chcemy wyskoczyć bardzo wysoko, a przepychanie Either czy jakiegoś errorcode przez 100 poziomów to chory pomysł.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
V-2
W przypadku błędów krytycznych jest to zrozumiałe, ale ile stanowią one procent wszystkich sytuacji świadczących o nieprawidłowym stanie aplikacji? A jeśli NORMĄ jest obsługa wszelkich nieprawidlowych sytuacji o sto poziomów od ich występowania, to dla mnie sugeruje że przy designie coś poszło nie tak. Nie ma to jak przekopywać się przez stack trace na pół kilometra ;)
nie100sowny
  • Rejestracja:około 9 lat
  • Ostatnio:około 10 godzin
  • Lokalizacja:Kraków
  • Postów:402
0

Dokładnie. Co do wyjątków stosuję takie zasady:

  1. Gdy piszę korpo apkę (np. w Spring), rzucam sobie RuntimeExceptiony (np. Guava preconditions), checked najszybciej jak się da zamieniam na IllegalState. Następnie wykorzystuję jedno miejsce (ControllerAdvice / Filter), żeby chwycić te wyjątki i zalogować poprawnie ze StackTrace. Mam obsługę błędów pewną i w jednym miejscu, a mój kod produkcyjny jest prostszy.

  2. Gdy piszę mniejszą apkę to na poziomie głównej klasy łapię wszystkie wyjątki.

  3. Nigdy nie prowadzę logiki biznesowej (np. Błędy HTTP, walidację itp.) wyjątkami, ponieważ są one wolne. JVM traktuje je jako rzadkie przypadki.

Może jest ktoś mądrzejszy i robi inaczej chętnie się dowiem.


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
Koziołek
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:9 dni
  • Lokalizacja:Stacktrace
  • Postów:6822
1

Od początku. W Javie mamy wyjątki weryfikowalne (checked) ponieważ taki był pomysł na język - mamy mechanizm chroniący przed błędami, które można przewidzieć.

Kolejna rzecz, to używanie wyjątków. Przez lata założenie, było takie, że wyjątek jest propagowany w górę, a na pewnym poziomie mamy jakiś mechanizm przechwytywania i obsługi wyjątków. Jakieś ExceptionHandler czy inne adnotacje ze springa. I to się sprawdzało do momentu, aż nie odkryliśmy, że takie zachowanie powoduje, że aplikacja bywa niestabilna. Dosypano do tego trochę koncepcji funkcyjnych i stwierdzono, że mechanizm wyjątków weryfikowalnych nie jest najlepszy.

Kolejnym etapem było wprowadzenie Either i Try, ale tu rozbiliśmy się o problem co mamy zwrócić gdy jednak mamy wyjątek. Tu wchodzą elementy związane z systemem typów i komponowaniem różnych elementów.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
nie100sowny
Rozwiniesz "niestabilna"?
Julian_
czyli używać czy nie?
Koziołek
@nie100sowny: obsługa wyjątków jest bardzo kosztowna i wpływa na wydajność. Poza tym niektóre rodzaje wyjątków w środowisku serwerowym propagują się dość wysoko i potrafią spowodować wstrzymanie aplikacji przez kontener.
nie100sowny
@Koziołek: W własnym poście zaznaczyłem problem z wydajnością. Słowo niestabilne jest nieodpowiednie, brzmi jakby używanie wyjątków powodowało błędy niczym concurrency :). @Julian_ Tak używaj pochodnych RuntimeException do obsługi błędów i chwytaj je w jednym miejscu w aplikacji. Napisałem wyżej.
CM
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 6 lat
  • Lokalizacja:Warszawa
  • Postów:118
0
Julian_ napisał(a):

W R nie ma czegoś takiego

A stop() to niby czym jest?

edytowany 1x, ostatnio: Crude Monte Carlo
Julian_
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 4 lata
  • Postów:1703
0
Crude Monte Carlo napisał(a):
Julian_ napisał(a):

W R nie ma czegoś takiego

A stop() to niby czym jest?

to jest jak System.exit(0) z komunikatem.

CM
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 6 lat
  • Lokalizacja:Warszawa
  • Postów:118
0

Może inaczej. Co zrobi poniższy kod?

Kopiuj
E <- simpleError("ERROR 1")

do_sth_internal <- function(){
  
  print("internal 1")
  
  if(TRUE) stop(E)
  
  print("internal 2")
  
}

do_sth_external <- function(){
  
  print("external 1")
  
  do_sth_internal()
  
  print("external 2")
  
}

tryCatch(
  do_sth_external(),
  error = function(E) "EDIT @insectoman: a teraz?",
  finally = print("Ultimate error handling script")
)
edytowany 2x, ostatnio: Crude Monte Carlo
insectoman
na pewno się nie skompiluje...
CM
@insectoman: nie chciało mi się obsługiwać wyjątku. Skrypt się nie wykonywał, bo rzucałem wyjątek. Wniosek w R można rzucać wyjątki.
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4709
1

Ogólnie sprawa wygląda tak:
na pewno wyjątki są lepsze od zwracania jakiś dziwnych wartośći typu -1 , null czy cokolwiek.

Ale jednak CheckedException w Javie się nie sprawdziły:

  • są tak męczące w obsłudze, że programiści permanentie robią skróty typu
    catch (Exception e) {}

  • albo robią rethrow i kod konczy się tym , że prawie każda metoda ma "throws Exception" (tak, są tacy magicy),

  • w 95% przypadków obsługa optymalna wygląda tak
    catch (SiakisException e) {throw new RuntimeException(e)}

Czyli generalnie męczący boilerplate. (ale idea była ładna)

Dodatkowo wyjątki psują tak zwane referential transparency - czyli taką własnośc kodu, że wywołanie funkcji możesz zastapic przez wartość funkcji - liczbę.
Ta własność znakomicie ułatwia testowanie ( i nie potrzeba korzystać z mocków - nawet jak testujesz IO).

Dlatego jednak w miejsce Checked Exception lepiej użyć Try lub Either.
Nie tylko nie łamią referential transparency, ale dodatkowo dzięki monadycznym map i flatMap łatwo je można propagować.

Inna sprawa do RuntimeException - czyli te sytuacje kiedy wyrypał się system nie działa baza danych itp - czyli naprawdę wyjątkowe wyjatki.
Te są fajne i warto ich używać, a że nie trzeba deklarować to też nie brudzą w kodzie.
To są też wyjątki, których generalnie nie testujemy bo odpowiadają właśnie za sytuacje, które w zasadzie nie powinny mieć miejsca.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 2x, ostatnio: jarekr000000
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:5 miesięcy
  • Postów:2787
0

@jarekr000000: a co sądzisz o błędach walidacyjnych? Np użytkownik chce coś zrobić ale złego JSona wysyła na serwer - rzucać jakiś ValidationException? W sumie tutaj nie jest to sytuacja wyjątkowa, możemy się spodziewać że często użytkownik poda np id czegoś czego nie ma w bazie etc.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 9 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4709
0

Jak mi uzytkownik wysyła złego JSona to odpowiadam mu np. 400 Bad Request - tu nie ma żadnego wyjątku w sensie javy.


jeden i pół terabajta powinno wystarczyć każdemu
PI
  • Rejestracja:ponad 9 lat
  • Ostatnio:5 miesięcy
  • Postów:2787
0
jarekr000000 napisał(a):

Jak mi uzytkownik wysyła złego JSona to odpowiadam mu np. 400 Bad Request - tu nie ma żadnego wyjątku w sensie javy.

@jarekr000000 jak najbardziej, status HTTP będzie o tym mówił. Ale jakiś response też powinien być. Według mnie JSon z jakimś komunikatem, że "popełniłeś błąd" + do tego status 400

DI
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:103
1

Jakieś artykuły / literatura na temat obsługi wyjątków? Coś też o Either? Poczytałbym o tym.

Burdzi0
Przydałoby się. Może jakiś Devoxx?

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.