Decyzja o niezaznaczonych wyjątkach w Scali

17

Jako programista Java zawsze byłem krytyczny wobec niesprawdzonych wyjątków. Głównie programiści używają go jako drogi do łatwości kodowania, aby później stworzyć problemy. Również programy (choć nieporządne) z zaznaczonymi wyjątkami są znacznie solidniejsze w porównaniu do niesprawdzonych odpowiedników.

Co zaskakujące, w Scali nie ma nic zwanego sprawdzonymi wyjątkami. Wszystkie Java zaznaczone i niezaznaczone są odznaczone w Scali.

Jaka jest motywacja tej decyzji? Dla mnie otwiera szeroki zakres problemów przy korzystaniu z dowolnego kodu zewnętrznego. A jeśli przypadkiem dokumentacja jest słaba, powoduje to ZABIJ.

Jatin
źródło
11
Jako programista Java zawsze krytykowałem sprawdzone wyjątki. Nieporządny kod nigdy nie jest niezawodny.
Michael Borgwardt

Odpowiedzi:

28

Sprawdzone wyjątki są w większości uważane za niepowodzenia. Zauważ, że nie zostały utworzone żadne języki po ich przyjęciu przez Javę. Zobacz http://www.artima.com/intv/handcuffs2.html , http://googletesting.blogspot.ru/2009/09/checked-exceptions-i-love-you-but-you.html , http: / /www.mindview.net/Etc/Discussions/CheckedExceptions itp.

W szczególności są nierozkładalne (z wyjątkiem powrotu do throws Exception ).

W Scali masz lepszą opcję: używanie typów algebraicznych do zwracania wartości, takich jak Option[T], Either[Exception, T]własny typ, gdy chcesz, aby użytkownik obsługiwał określone przypadki (np. Zamiast

def foo: Int // throws FileNotFoundException, IllegalStateException

ty masz

sealed trait FooResult
case class Success(value: Int) extends FooResult
case class FileNotFound(file: File) extends FooResult
case object IllegalState extends FooResult

def foo: FooResult

a teraz konsument musi obsługiwać wszystkie wyniki)

Do radzenia sobie z zewnętrznym kodem, który generuje wyjątki, masz scala.util.control.exceptionlub scala.util.Try(począwszy od Scali 2.10).

Aleksiej Romanow
źródło
4
Nigdy nie zrozumiałem, że większość ludzi nie obsługuje sprawdzonych argumentów wyjątków . Większość ludzi nie jest dobrymi programistami. Gwarantuję, że większość programistów i tak nie poradzi sobie z wynikiem błędu. W rzeczywistości try..catchwydaje się o wiele bardziej czytelny niż if. Co więcej, mogę również zagwarantować, że ci sami programiści nie będą pisać kodu, który zwraca wynik błędu - zbyt skomplikowany w Scali - nie możesz nawet powrócić z funkcji, kiedy chcesz (tak jak w Pascal)
Pijusn
5
Uważam, że komentujesz mylące i pozbawione dowodów @Pius. W Scali wybranie opcji jako typu zwrotu prawdopodobnie spowoduje dopasowanie wzorca zamiast instrukcji If . Zwracanie None zamiast Some w tym stylu jest banalne, a nie skomplikowane. Mniej dokładni programiści mogą nie pisać funkcji, które zwracają typy algebraiczne, ale to inna sprawa. Wreszcie, „nie możesz nawet wrócić z funkcji, kiedy chcesz” - po prostu nieprawda.
itsbruce
7

Sprawdzone wyjątki w Javie nie są takie złe. Oczywiście ADT może być lepszą opcją dla Scali, ale w Javie sprawdzone wyjątki mają swoje miejsce, a argument uporządkowanego kodu jest po prostu bezsensowny, bez znaczenia, bez względu na to, ile blogów go powtórzyło. Mówi w zasadzie, że z radością powinieneś ignorować trudne i możliwe do naprawy warunki, które mogą się zdarzyć w twoim systemie, ponieważ system typu śrubowego, ładny kod sprawia, że ​​twój system jest automagicznie wydajny. Takie rozumowanie również wyjaśnia, dlaczego tak wielu programistów Java dobrowolnie przenieść swój kod do plików XML (wiosna, Maven, itp tęsknię całkiem częścią).

Przyczyna braku sprawdzonych wyjątków w Scali podana przez M. Odersky poniżej http://www.scala-lang.org/old/node/8787.html jest zaskakująco inna i ma sens.

Problem ze sprawdzonymi wyjątkami najlepiej pokazuje metoda map na listach:

def map[B](f: A => B): List[B]

Jak dodać adnotację do mapy za pomocą @ rzutów? Jeśli mapa sama nie otrzyma adnotacji @throw, prawdopodobnie nie możesz przekazać jej żadnej funkcji, która ma @throw. Wprowadziłoby to uciążliwe ograniczenia i rozróżnienia dotyczące sposobów korzystania z mapy. Byłoby lepiej, gdybyśmy mogli w jakiś sposób stwierdzić, że mapa wyrzuca wszystkie wyjątki od argumentu funkcji. Istnieje kilka systemów efektów, które mogą to wyrazić, ale jak dotąd każda notacja, którą widziałem, jest zbyt ciężka.

Lukas Rytz prowadzi badania nad lekkimi systemami efektów, które można by wykorzystać do wyrażenia rodzaju mapy i innych typowych funkcji w zwięzły i precyzyjny sposób. To badania, więc obecnie nie jest jasne, w jakim stopniu odniesiemy sukces i ile z tego można włożyć do Scali. Idealnie, będziemy mogli dodać go w pewnym momencie jako opcjonalny system typów. Ale jest o wiele za wcześnie, aby dokonywać konkretnych prognoz.

Twoje zdrowie

Nie jestem pewien, ale myślę, że lambda Java 8 są również ograniczone do niesprawdzonych wyjątków.Metody w większości (wszystkich?) Nowych interfejsów funkcjonalnych w JDK 8 ( java.util.function.*) również nie deklarują niezaznaczonych wyjątków.

woky
źródło
2

Jeśli chcesz zyskać na wydajności, musisz zrezygnować ... precyzja / kontrola <- Potrzebuję na to lepszego słowa.

Scala znajduje się na szczycie, jeśli chodzi o abstrakcję. Jeśli jednym z celów Scali jest pozbycie się irytującego kodu, to oczywistym miejscem do obejrzenia jest obsługa wyjątków Javy. Jeśli chcesz napisać szybki kod w Javie, po prostu rzucaj sprawdzonymi wyjątkami, aż zostaną trafione main()i nie zostaną zaznaczone.

Nie wiem, czy rozumiem dokładnie to, o co pytasz, ale jest to moim zdaniem najbardziej oczywisty powód.

Cóż, trochę się rozejrzałem i ktoś napisał o tragedii wyjątków czekowych .

David Cowden
źródło