W jaki sposób uczysz programistów obsługi wyjątków? Wszystkie inne rzeczy są nauczane w łatwy sposób - Struktury danych, ASP.NET, WinForms, WPF, WCF - nazywasz to, wszystko można łatwo nauczyć.
W przypadku obsługi wyjątków nauczenie ich próbowania w końcu to tylko składniowa natura obsługi wyjątków.
Czego jednak należy nauczyć - Jaką część kodu umieszczasz w bloku try ? Co robisz w bloku catch ?
Pozwól, że zilustruję to przykładem.
Pracujesz nad projektem Windows Forms Project (małe narzędzie) i zaprojektowałeś go tak, jak poniżej, z 3 różnymi projektami.
- UILayer
- BusinessLayer
- DataLayer
Jeśli w DataLayer pojawi się wyjątek (powiedzmy, że ładowanie XDocument zgłasza wyjątek) (UILayer wywołuje BusinessLayer, który z kolei wywołuje DataLayer), czy po prostu wykonaj następujące czynności
//In DataLayer
try {
XDocument xd_XmlDocument = XDocument.Load("systems.xml");
}
catch(Exception ex)
{
throw ex;
}
który jest ponownie wyrzucany w BusinessLayer, a który jest przechwytywany w UILayer, gdzie zapisuję go do pliku dziennika?
Czy tak postępujesz w przypadku obsługi wyjątków?
Odpowiedzi:
Aby objaśnić obsługę wyjątków, wyjaśnij kryjącą się za tym koncepcję: Kod, w którym często występuje błąd, nie wie, jak poprawnie obsługiwać ten błąd. Kod, który wie, jak poprawnie go obsługiwać, może być funkcją, która go wywołała, lub może znajdować się wyżej w stosie wywołań.
Gdy piszesz procedurę wywołującą procedurę, która może zgłosić wyjątek, jeśli wiesz, jak poprawnie obsługiwać ten błąd, umieść wywołanie w bloku try i umieść kod obsługi błędów w bloku catch. Jeśli nie, zostaw to w spokoju i pozwól, aby coś nad tobą w stosie wywołań obsługiło błąd.
Powiedzenie „catch ex, throw ex” nie jest dobrym sposobem na obsługę wyjątków, ponieważ tak naprawdę nic nie obsługuje. Ponadto, w zależności od tego, jak działa model wyjątku w Twoim języku, może to być rzeczywiście szkodliwe, jeśli usunie informacje śledzenia stosu, które można było wykorzystać do debugowania problemu. Po prostu pozwól wyjątkowi propagować stos wywołań, aż natrafi na procedurę, która wie, jak go obsłużyć.
źródło
Podobnie jak większość rzeczy, wyjątki i obsługa wyjątków będą prawdopodobnie wydawać się rozwiązaniem w poszukiwaniu problemu dla nowych programistów, dopóki nie dowiesz się, dlaczego pozornie prostsze rozwiązanie (kody powrotu w stylu C i errno) działają tak źle. Zacznę od motywowania problemu i umieszczenia go w odpowiednim kontekście. Pokaż, jak można obsługiwać błędy przy użyciu kodów powrotu lub zmiennych globalnych / statycznych. Następnie podaj przykłady, dlaczego nie działa dobrze. Wtedy i tylko wtedy wprowadź wyjątki i wyjaśnij, że są one formą sygnalizacji pozapasmowej i że o to chodzi to, że domyślnym zachowaniem, jeśli zignorujesz wyjątek, jest przekazanie złotówki stosowi wywołań komuś, kto może zajmij się tym.
Konkluzja: Pokazanie, w jaki sposób obsługa błędów została wykonana w C, pozwoli uczniom zrozumieć, na czym naprawdę polegają wyjątki i dlaczego wychwytywanie wyjątków, z którymi tak naprawdę nie można sobie poradzić, to po prostu symulacja sposobu, w jaki działano w czasach ciemnych.
źródło
Zacznę od Wytycznych projektowych dla wyjątków krótkie i obejmują DO, DO NIE i UNIKAJ. Podaje również powody.
W twoim przypadku sekcją odkrywczą byłyby wyjątki pakowania
I spodziewałbym się, że będzie napisane w ten sposób. Zauważ, że wyłapuje określony wyjątek i próbuje dodać informacje, aby propagować bardziej znaczący komunikat. Należy również pamiętać, że wewnętrzny wyjątek jest nadal utrzymywany do celów logowania
AKTUALIZACJA Kanini pyta, czy słusznie jest mieć ten blok wyjątków w warstwie danych, czy też sprawdzenie pliku powinno być dostępne dla warstwy biznesowej.
Na początek chciałbym zauważyć, że uzasadnienie owijania wyjątków jest takie
Więc jeśli uważasz, że wyższa warstwa powinna w ogóle wiedzieć o pliku, wtedy twoja warstwa danych powinna wyglądać tak
No Try No Catch.
Osobiście uważam, że jeśli twoja warstwa danych nie jest w stanie zrobić czegoś pożytecznego, np. Użyj domyślnego pliku system.xml, który jest zasobem asemblera, nic nie robiąc lub owijając wyjątek jest dobrym wyborem, ponieważ twoje logowanie powie ci, która metoda i jaki plik był problemem. (
throw ex
w tym przypadku lub preferowanethrow
też, ale nie dodaje żadnej wartości). Oznacza to, że po zidentyfikowaniu będziesz w stanie szybko rozwiązać problem.Jako przykład ten konkretny przykład ma również następujący problem polegający na tym, że XDocument.Load może wyrzucić cztery wykonania
Nie możemy bezpiecznie zagwarantować, że następujący kod nie zostanie zgłoszony i wyjątek FileNotFoundException, po prostu dlatego, że może on istnieć, gdy sprawdzamy istnienie, i znikać, gdy ładujemy. Udostępnienie tego warstwie biznesowej nie pomogłoby.
SecurityException jest jeszcze gorszy, ponieważ między innymi powodami wyrzucenia, jeśli inny proces przechwytuje wyłączną blokadę pliku, nie dostaniesz błędu, dopóki nie spróbujesz otworzyć go do odczytu, ponieważ nie ma metody File.CanIOpenThis (). A jeśli taka metoda istniała, nadal masz ten sam problem, co w przypadku File.Exists
źródło
Zróbmy rolę. (to nie jest żart)
Powinieneś zrobić warsztat, w którym odegrasz łańcuch połączeń. Każda osoba jest przedmiotem. Będziesz potrzebować nowicjuszy, a niektórzy ludzie, którzy rozumieją „grę”, pomogą.
Użyj naprawdę prostego problemu, takiego jak plik IO. gui-> model-> plik_io
Osoba będąca czytnikiem plików musi powiedzieć następnej ....
Najpierw zrób to z kodami powrotu. (użyć karteczek samoprzylepnych?)
jeśli interakcje są po prostu „tym, co mówi kod”, już wkrótce można uświadomić ludziom, że wyjątki są wyjątkowe.
w przypadku kodów powrotu przekaż karteczkę samoprzylepną.
wyjątki, podnieście ręce w powietrze i powiedzcie, na czym polega problem.
następnie poproś, aby wykonali polecenie „złap x, wyrzuć x” i zobacz, jak dużo gorzej diagnoza jest taka, jaką otrzymuje GUI „model miał wyjątek”.
Myślę, że to zadziała, by szkolić ludzi, których masz, ponieważ ludzie dość dobrze rozumieją interakcje z innymi ludźmi.
źródło
Wyobrażam sobie, że rozumiem wyjątki, które musisz najpierw zrozumieć na przykład relacje dziecko-rodzic w klasach. Jeśli zrozumiesz, że dziecko może dziedziczyć funkcje od rodzica, może być w stanie na poziomie podstawowym zrozumieć, że jeśli dziecko ma problem, nie może go obsłużyć, przekaże ten problem (wyjątek) swojemu rodzicowi i pozwoli rodzicowi z tym.
Staje się to powiązaniem łańcuchowym, dopóki nie skończysz w miejscu, w którym coś wie, jak poradzić sobie z wyjątkiem.
I do tego stopnia, że w końcu jest to trywialna część ... kiedy pojawia się problem, coś musi sobie z tym poradzić, aby program nie zakończył się fatalnie, po obsłużeniu tego wyjątku jest blok na końcu, który zawsze będzie wykonywany niezależnie od try catch .
Dobrym przykładem może być sieć:
lub w wyjątkowym przypadku:
źródło
Daj aplikację nowicjuszowi, który ma bardzo dobrą obsługę wyjątków. Rzuć gdzieś wyjątek i pozwól mu debugować go za pomocą Logów. Śledząc propagację wyjątku, powinni móc go debugować. Wykonaj to ćwiczenie 3 lub 4 razy. Teraz po prostu usuń całą obsługę wyjątków z kodu i pozwól im spróbować śledzić ten sam wyjątek.
Wierzę, że uznanie dla kodu obsługi wyjątków zostanie natychmiast docenione.
źródło
IMO, powinieneś pomyśleć, że obsługa wyjątków i instrukcje kontroli przepływu są w zasadzie takie same. Używasz ich do kontrolowania przepływu swoich programów w zależności od tego, w jakim są obecnie stanie. Różnica polega na tym, że obsługa wyjątków reaguje tylko w przypadku wystąpienia błędu (lub wyjątku).
źródło
Prawdopodobnie nie pomogłoby to nowemu programistowi, ale odkryłem, że rozumiałem pojęcie wyjątków znacznie lepiej, kiedy zacząłem używać monad w programowaniu funkcjonalnym. Monada zmusza cię do rozważenia każdego „kanału”, przez który dane mogą wpływać do lub z programu, ponieważ wszystko to zapewnia wygodną abstrakcję, aby „ukryć” część tego przepływu danych.
Pomysł, że funkcja może mieć różne typy danych wyjściowych, a wyjątek jest jak typ powrotu o wyższym priorytecie z funkcji, jest dość zgrabny.
Pamiętaj, że rozumiem, że nie tak działają wyjątki w większości języków (szczegóły implementacji), ale w abstrakcyjnym sensie tak się dzieje.
źródło
Udawaj, że małpa używa klawiatury
Kiedyś mówiłem moim chłopakom, kiedy piszą kod, aby udawać, że małpa będzie siedziała przy keyboardzie i będzie korzystać z tej aplikacji.
To nauczyło ich przewidywania wszelkiego rodzaju rzeczy:
Myślę, że to był obraz słowny, gdy małpa tylko wali w klawisze i robi, co chce, zamiast ładnie podążać. To zadziałało dla mnie.
źródło