[ Pobierz całość w formacie PDF ]

jącym wiedzę, która pozwoli zinterpretować sytuację i podjąć rozsądne działania.
Wyjątki można także wykorzystać do porządkowania zawiłej logiki na pewnym
odcinku kodu. Ilustruje to przykład  Przepisać kod z użyciem try-finally w pod-
rozdziale 17.3. Ogólnie rzecz biorąc, mechanizm wyjątku polega na tym, że
procedura używa polecenia throw (wyrzuć), aby go zgłosić, i przekazuje jed-
nocześnie obiekt wyjątku. Kod w innej procedurze, wyżej w hierarchii wy-
wołań, używa bloku try-catch (próbuj-przechwyć), aby wyjątek przechwycić.
Implementacje mechanizmu wyjątków w najpopularniejszych językach nie są
jednolite. W tabeli 8.1 zaprezentowane zostało zestawienie podstawowych róż-
nic między trzema z nich.
Programy, które używają
Jest coś, co łączy wyjątki z dziedziczeniem: oba te mechanizmy, odpowiednio
wyjątków jako jednego
stosowane, pozwalają zmniejszyć złożoność, jednak lekkomyślne ich traktowa-
z mechanizmów zwykłego
przetwarzania, sprawiają nie szybko prowadzi do powstania kodu, który jest niemal zupełnie niezro-
takie same problemy
zumiały. Na kolejnych stronach zebrane zostały wskazówki zwracające uwagę
z czytelnością oraz
na korzyści płynące ze stosowania wyjątków oraz problemy, które mogą wystą-
przy modyfikacji
i rozbudowie
pić przy nadużywaniu tego mechanizmu.
jak tradycyjny
kod spaghetti.
Używaj wyjątków do powiadamiania innych części programu o błędach, które
 Andy Hunt
i Dave Thomas nie powinny być ignorowane. Największą zaletą wyjątków jest dawana przez
nie możliwość sygnalizowania błędów w sposób niepozwalający na ich zigno-
rowanie (Meyers 1996). W przypadku innych mechanizmów obsługi błędów
zawsze należy liczyć się z ryzykiem propagacji błędu w programie bez jego
wykrycia. Wyjątki eliminują to zagrożenie.
Zgłaszaj wyjątek tylko w sytuacjach naprawdę wyjątkowych. Wyjątki powinny
być zarezerwowane dla sytuacji faktycznie nietypowych, innymi słowy dla takich,
do których nie można dostosować kodu innymi metodami. Stosuje się je podob-
nie jak asercje  nie dla zdarzeń rzadkich, ale tych, które nigdy nie powinny
wystąpić.
8.4. Wyjątki 235
Tabela 8.1. Wyjątki w trzech popularnych językach
Cecha C++ Java Visual Basic
Blok try-catch tak tak tak
Blok try-catch-finally nie tak tak
Dane wyjątku obiekt Exception obiekt Exception obiekt Exception
lub obiekt klasy lub obiekt klasy lub obiekt klasy
pochodnej; wskaznik pochodnej pochodnej
do obiektu; odwołanie
do obiektu; typ taki
jak string lub int
Skutek nieprzechwycenia wywołanie procedury przerwanie wątku przerwanie programu
wyjątku std::unexpected(), wykonania,
standardowo jeżeli wyjątek
wywołującej jest  wyjątkiem
procedurę kontrolowanym ;
std::terminate(), która brak skutków, jeżeli
standardowo jest to  wyjątek czasu
wywołuje abort() wykonania
Zgłaszane wyjątki muszą nie tak nie
być definiowane
w interfejsie klasy
Przechwytywane wyjątki nie tak nie
muszą być definiowane
w interfejsie klasy
Używając wyjątków, warto pamiętać o tym, że jest to trudny kompromis między
wprowadzeniem mechanizmu dającego ogromne możliwości a zwiększeniem
stopnia komplikacji kodu. Osłabiają one hermetyzację, bo wymagają od kodu
wywołującego procedurę, aby znał wyjątki, które może zgłosić kod wywoły-
wany. Zwiększa to złożoność, a więc zaprzecza temu, co w rozdziale 5.,  Projek-
towanie , określone zostało jako Główny Imperatyw Techniczny Oprogramo-
wania: Zarządzanie Złożonością.
Nie używaj wyjątków jako metody odkładania rozwiązania problemu na póz-
niej. Jeżeli obsługę błędu można zapewnić lokalnie, należy to zrobić. Użycie
throw nie jest alternatywą, w przypadku gdy problem można rozwiązać na
miejscu.
Unikaj zgłaszania wyjątków w konstruktorach i destruktorach, jeżeli nie zostaną
przechwycone w tym samym miejscu. Gdy konstruktory i destruktory mogą
zgłaszać wyjątki, reguły przetwarzania komplikują się bardzo szybko. Przykła-
dem może być fakt, że w języku C++ destruktor nie zostanie wywołany przed
ukończeniem budowania obiektu. W efekcie zgłoszenie wyjątku w konstrukto-
rze powoduje pominięcie destruktora. To może z kolei prowadzić do sytuacji,
w której pewne zasoby nie zostają zwolnione (Meyers 1996, Stroustrup 2010).
Podobne problemy pojawiają się przy zgłaszaniu wyjątków w destruktorach.
Adwokat tego czy innego języka mógłby stwierdzić, że zasady tego rodzaju są
 trywialnie proste i pamiętanie o nich nie jest żadnym problemem, jednak
programista jest tylko człowiekiem i każda reguła zostaje wcześniej czy pózniej
236 Rozdział 8. Programowanie defensywne
zapomniana (czy też przeoczona). Lepszą praktyką jest proste unikanie wprowa-
dzania dodatkowej złożoności, będącej konsekwencją takiego kodu, i powstrzy-
mywanie się od zgłaszania wyjątków poza  zwykłymi procedurami.
Patrz też: Więcej
Zgłaszaj wyjątki na właściwym poziomie abstrakcji. Procedura, tak jak i klasa,
o utrzymywaniu
powinna reprezentować poprzez swój interfejs spójną abstrakcję. Podobnie jak
spójności abstrakcji
interfejsu w punkcie wykorzystywane typy danych, zgłaszane wyjątki są częścią jej interfejsu.
 Dobra abstrakcja
w podrozdziale 6.2.
Gdy podejmujesz decyzję o przekazaniu wyjątku procedurze wywołującej,
upewnij się, że poziom jego abstrakcji odpowiada abstrakcji interfejsu proce-
dury. Oto przykład tego, czego nie należy robić:
Klasa, która zgłasza wyjątek o niewłaściwym poziomie abstrakcji (Java)
class Employee { // pracownik
...
public TaxId GetTaxId() throws EOFException { // wyj tek EOF
Deklaracja wyjątku
...
na złym poziomie
}
abstrakcji.
...
}
Kod GetTaxId() przekazuje niskopoziomowy wyjątek EOFException do kodu wy-
wołującego. Procedura nie przejmuje za niego odpowiedzialności i ujawnia szcze-
góły swojej implementacji, przekazując niskopoziomowy obiekt tego wyjątku.
Prowadzi to do ścisłego powiązania kodu klienta procedury nie z klasą Emplo
yee, ale z kodem na niższym poziomie, tym, który zgłasza wyjątek EOFExcep
tion. Hermetyzacja zostaje złamana i funkcjonalność pojęciowa kodu maleje.
Procedura GetTaxId() powinna przekazywać wyjątek spójny z interfejsem klasy, [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • markom.htw.pl