Article View: pl.comp.objects
Article #14391Re: Wyrzucenie wyjątku, czy zwrócenie null?
From: Przemek Pokrywka
Date: Tue, 28 Mar 2006 21:05
Date: Tue, 28 Mar 2006 21:05
103 lines
5956 bytes
5956 bytes
Dziękuję za ciekawą wypowiedź, choć zgadzam się z nią w (mniej więcej)
połowie
x-plorer napisał(a):
> 1. Już samo określenie wyjątek sugeruje, że chodzi o sytuację rzadko
> spotykaną. Nieznalezienie obiektu jest w opisanym przypadku równie
> uprawnione jak jego znalezienie.
Najpierw spróbuję pokazać, że branie określenia "wyjątek" dosłownie może
nieść za sobą niebezpieczeństwo zignorowania jego istoty jako
konstrukcji programistycznej.
Choć wprawdzie te dwie sytuacje są równouprawnione, to bywa, że język
traktuje je nierówno. Przy okazji może wyjść tu moje skażenie Javą i
przyzwyczajeniem do wyjątków sprawdzanych przez kompilator (AFIK rzadko
występujących w popularnych językach programowania).
Otóż w wypadku nieodnalezienia obiektu, gdy
a) zwrócony jest null, nic nie powstrzyma roztargnionego programisty
przed zignorowaniem takiej sytuacji, co najprawdopodobniej zakończy się
błędem w znacznie dalszej części programu, gdzie znalezienie go nie
będzie już takie oczywiste.
b) wyrzucony jest wyjątek sprawdzany przez kompilator, błąd kompilacji
uniemożliwi roztargnionemu programiście przejście dalej
W przypadku wyrzucenia wyjątku programista jest więc wspierany przez
kompilator w prawidłowej obsłudze wszystkich przypadków.
Owszem, zdarzają się ludzie, którzy po błędzie kompilacji szybko
dopisują pustą klauzulę catch, ale nie mam takich na myśli.
Następnie chciałbym wykazać, że równouprawnienie dwóch sytuacji nie jest
wystarczającą przesłanką, żeby nie używać wyjątków.
W aplikacjach, które często operują na plikach na każdym kroku może
wystąpić sytuacja błędu odczytu/zapisu/nieodnalezienia pliku. Pomimo, że
zarówno sytuacja odnalezienia pliku, jak i ta przeciwna są
równouprawnione, zakłada się jednak jakiś podstawowy scenariusz
działania aplikacji, w którym dobrze wykona ona zadania, do których jest
przeznaczona. Prawdziwe równouprawnienie przypadków niemal nie występuje
w praktyce. Przy takich założeniach kod, który w głównym "nurcie"
rozpatruje te pozytywne przypadki, a w klauzulach obsługi wyjątków
zajmuje się tymi negatywnymi jest moim zdaniem bardziej czytelny, niż
kod, który w równouprawnionych gałęziach instrukcji warunkowej
rozpatruje przypadek podstawowy i alternatywny.
Innymi słowy, użycie instrukcji warunkowej do odróżnienia przypadków
podstawowego i alternatywnego jest dla mnie "zbyt łaskawym"
potraktowaniem przypadku alternatywnego.
O prawdziwym równouprawnieniu dwóch przypadków możnaby mówić moim
zdaniem np. w określaniu płci osoby (i to tylko w aplikacjach, których
zasadnicze działanie jest niezależnie od tego atrybutu osoby).
> 2. Czytelność kodu. Uważam, że linia postaci:
>
> if (person == null) // nie znaleziono osoby
>
> jest bardziej czytelna niż blok chwytania wyjątku.
twierdzę, że od
Person person = find("nemo");
if (person != null)
process(person);
else
noPersonFoundCase();
czytelniejsze jest:
try {
Person person = find("nemo");
process(person);
catch (PersonNotFoundException e) {
noPersonFoundCase();
}
dlatego, że w drugim przypadku można w sposób niezakłócony prześledzić
proces wyszukiwania i przetwarzania obiektu Person z jasno oddzieloną
obsługą sytuacji wyjątkowej.
> 3. Efektywność. Porównanie z nullem to fizycznie banalne sprawdzenie.
> Rzucanie i chwytanie wyjątku jest kosztowne. Nie wytaczajmy armaty na
> wróble.
"Premature optimization is the root of all evil" jak powiedział mistrz
Knuth - jak zawsze, diabeł tkwi w szczegółach. Rezygnacja z lepszej
konstrukcji językowej na rzecz niejasnych korzyści wydajnościowych nie
jest moim zdaniem dobrą praktyką. Jeśli profiling aplikacji wykaże, że
obsługa wyjątków jest wąskim gardłem, to zgodziłbym się, że w danej
sytuacji użycie wyjątków może nie być najlepszym wyjściem. Idę jednak o
zakład, że wyjątki nie stanowią wąskiego gardła w 80% aplikacji.
> Posłużenie się wyjątkiem miałoby wg mnie sens w następującej sytuacji:
>
> W przebiegu może zajść więcej negatywnych zdarzeń, np. brak uprawnień do
> danych osoby, dane osoby uniemozliwiają przeprowadzenie dalszych obliczeń
> (np. obliczenie dni urlopu dla emeryta) itp. W takiej sytuacji można
> załatwić wszystkie możliwe wyjątki jednym blokiem przechwytywania, pod
> warunkiem, że ich sposób obsłużenia będzie identyczny niezależnie od typu
> wyjątku, np. opis wyjątku jest czytelny dla użytkownika i wystarczy
> wyświetlić go w oknie komunikatu.
Zgadzam się z takim wnioskiem - jednak opisana sytuacja to dla mnie nie
jest jedyna, w której widziałbym uzasadnienie dla użycia wyjątków.
--
Pozdrawiam,
Przemysław Pokrywka
Technical Details
Message-ID:
<e0c8eh$ur8$1@news.onet.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!mat.uni.torun.pl!news.man.torun.pl!newsfeed.pionier.net.pl!newsfeed.silweb.pl!news.onet.pl!not-for-mailReferences:
<e09c3r$lg3$1@news.onet.pl> <e09f0h$cis$1@news.task.gda.pl> <e09gjn$737$1@news.onet.pl> <e0b1re$bdc$1@news.onet.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!mat.uni.torun.pl!news.man.torun.pl!newsfeed.pionier.net.pl!newsfeed.silweb.pl!news.onet.pl!not-for-mail From: Przemek Pokrywka <adres@zastrzezony.com> Newsgroups: pl.comp.objects Subject: Re: Wyrzucenie wyjątku, czy zwrócenie null? Date: Tue, 28 Mar 2006 23:05:20 +0200 Organization: Onet.pl Lines: 103 Message-ID: <e0c8eh$ur8$1@news.onet.pl> References: <e09c3r$lg3$1@news.onet.pl> <e09f0h$cis$1@news.task.gda.pl> <e09gjn$737$1@news.onet.pl> <e0b1re$bdc$1@news.onet.pl> NNTP-Posting-Host: 041.inet.polhost.pl Mime-Version: 1.0 X-Trace: news.onet.pl 1143579921 31592 80.48.120.41 (28 Mar 2006 21:05:21 GMT) X-Complaints-To: usenet@news.onet.pl NNTP-Posting-Date: Tue, 28 Mar 2006 21:05:21 +0000 (UTC) X-Sender: 5aB4pqMdeQG1O30L902dNmlAzoKeNKcS In-Reply-To: <e0b1re$bdc$1@news.onet.pl> X-Accept-Language: pl, en-us, en User-Agent: Mozilla Thunderbird 1.0.2 (Windows/20050317) Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit