Dzisiaj krótki wpis o trzech i pół sposobach na to jak wyrzucać wyjątki, gdy już go się raz złapie i coś z nim zrobi lub nie. Wyjątki są w dotnet i nic tego nie zmieni. Część na nas z nich korzysta, a część robi to źle.
No to siup z kodem, polecam zacząć czytanie od linijki 64. Reszta to infrastruktura która umożliwia uruchomienie kodu. Można przekopiować do siebie i samodzielnie poklikać.
Mamy trzy przykłady na to jak złapać, a następnie rzucić ponownie wyjątkiem.
Raz – throw
Skupiamy się na linijkach 66-76. W tym przypadku wyrzucony zostanie dokładnie ten sam wyjątek, który został złapany, nic nie zostanie zmienione. Tak naprawdę ten sam, totalnie i całkowicie. Można porównywać referencje i takie tam.
Dwa – throw e
Skupiamy się na linijkach 78-88. W tym przypadku wyrzucony zostanie znowu ten sam wyjątek, ale z jedną drobną zmianę. Zmieniony zostanie miejsce pochodnia wyjątku. O ile wcześniej źródło wyjątku pochodziło z metody MethodThatThrows, w tym przypadku źródło zostanie zmienione na linię z throw w obsłudze wyjątku. Stracony zostanie poprzedni stack trace.
Trzy – throw new
Skupiamy się na linijkach 90-100. Tutaj rzeź. Wszelkie informacje i powiązania z oryginalnym wyjątkiem znikają. Tworzony jest zupełnie nowy obiekt wyjątku, a wszelka historia ginie. Wraz z opuszczeniem bloku {}
Pół
W przykładzie powyżej można się uratować i podczas tworzenia nowego wyjątku, podać tekst oraz oryginalny wyjątek, który schowa się we właściwości InnerException.
Koniec
Co mogę powiedzieć na koniec. Zastanówcie się co chcecie zrobić i jak wasz kod zostanie zinterpretowany nie przez maszynę, ale przez innego programistę.
A gdzie łapić? Tam gdzie może dziać się źle, czy to wszystkie w jednym miejscu?
Ło panie. Temat łapania i obsługi wyjątków to coś grubszego niż jeden komentarz.
Na szybko to zależy. Na dłużej, jeśli to nic krytycznego to złap blisko i uratuj aplikacje, jeśli to coś poważnego, wyświetl błąd i zrób restart aplikacji.
Coś się chyba pochrzaniły numery linijek. W lini 64 mam ‘}’ 🙂
Aha, coś mi się musiało źle spojrzeć, dzięki. Poprawione.
Spotkałem się kiedyś z radą, by unikać samodzielnego rzucania wyjątków, a obsługiwać tylko to co samo zostało wyrzucone.Mając jakąś metodę która dostaje parametry i ma zwrócić jakiś obiekt, powinienem w przypadku złych parametrów rzucić jakimś wyjątkiem i mieć pewność że jeżeli metoda zwróci obiekt to jest on na pewno dobry, czy zwrócić null a wyjątek ewentualnie obsłużyć w tej metodzie bez większego rozgłosu?
Ja staram się nie korzystać z wyjątków. Gdy dostajesz złe parametry, to możesz zwrócić obiekt który nic nie wnosi do systemu, ale powoduje że aplikacja nadal działa, patrz null object pattern. Dla mnie wyjątek to sprawa ostateczna. Gdy już naprawdę nie wiem co zrobić i mogę się jedynie położyć i powoli czołgać na cmentarz, wtedy rzucam wyjątkiem. Tak samo nulle – to także omijam, znowu null object pattern robi robotę.
Pisałem o tym wzorcu wcześniej: http://jaroslawstadnicki.pl/2016/08/10/null-object-mi-roznicy-nie-robi/
Jakby coś pisz śmiało.
Dzięki wielkie 🙂
OK, to konkretnie, mam metodę, która tworzy dokument. Załóżmy, że dokument ma tylko numer i datę. Numer nadaje się z jakiegoś ciągu, a datę dostaję w parametrze.
Teraz, w przypadku otrzymania nulla (załóżmy głupio, że data przekazywana jest jako object) i zastosowania null object pattern, jeśli dobrze rozumiem zasadę tego wzorca, tworzę dokument z datą DateTime.Now. Hmm.
To oczywiście przykład, ale faktem jest, że raczej rzucam wyjątkami w takich sytuacjach, a jest ich mnóstwo. Poza tym, dlaczego od razu kaplica? Można złapać wyjątek, albo inaczej wszystkie wyjątki gdzieś na starcie, wyświetlić “Wystąpił błąd” i w kolejnych zakładkach info do skopiowania dla programistów. Aplikacja dalej działa, tylko nie działa akcja, która się wywaliła. A może można ją wywołać, podając tym razem datę (dla bardziej spostrzegawczych użytkowników)?
Ciężko się ustrzec przed głupimi rzeczami. Ale wartość zwracana w null object nie musi zawsze być w 100% poprawną wartością. Np. w tym wypadku nie musi to być DateTime.Now lecz np. DateTime.Min, gdzie wartość jest poprawna (bo nie jest null) ale np. nie przechodzi przez cześć walidacji, logiki, biznesu, bo jest datą w przeszłości.
Możemy się przerzucać przykładami i ich sposobami rozwiązywania, null object nie jest lekiem na całe zło, jest jednym z wielu dostępnych rozwiązań.
Faktycznie wszystko zależy od okoliczności, a dyskusja czysto akademicka. Nie ciągnijmy tematu 🙂