Właśnie dowiedziałem się, że .NET 4.5 wprowadził zmianę w sposobie obsługi wyjątków wewnątrz Task
. Mianowicie są cicho tłumione.
Oficjalne uzasadnienie, dlaczego tak się stało, brzmi: „chcieliśmy być bardziej przyjaźni dla niedoświadczonych programistów”:
W .NET 4.5 zadania mają znacznie większe znaczenie niż w .NET 4, ponieważ są one wprowadzone w językach C # i Visual Basic jako część nowych funkcji asynchronicznych obsługiwanych przez te języki. To w efekcie przenosi Zadania z domeny doświadczonych programistów do królestwa wszystkich. W rezultacie prowadzi to także do nowego zestawu kompromisów dotyczących tego, jak surowo obchodzić się z obsługą wyjątków.
( źródło )
Nauczyłem się ufać, że wiele decyzji w .NET było podejmowanych przez ludzi, którzy naprawdę wiedzą, co robią, i zwykle istnieje bardzo dobry powód, dla którego decydują. Ale ten mi ucieka.
Gdybym projektował własną bibliotekę zadań asynchronicznych, jaka jest zaleta przełykania wyjątków, których twórcy Framework zauważyli, że ich nie widzę?
Odpowiedzi:
Jeśli chodzi o to, co warto, w dokumencie, do którego się odnosisz, podano przykładowe uzasadnienie:
Nie przekonuje mnie to. Eliminuje możliwość jednoznacznego, ale trudnego do wyśledzenia błędu (tajemnicza awaria programu, która może wystąpić długo po rzeczywistym błędzie), ale zastępuje go możliwością całkowicie cichego błędu - który może stać się równie trudnym do wyśledzenia problemem później w twoim programie. To wydaje mi się wątpliwym wyborem.
Zachowanie jest konfigurowalne - ale oczywiście 99% programistów po prostu zastosuje zachowanie domyślne, nigdy nie myśląc o tym problemie. To, co wybrali jako domyślne, to wielka sprawa.
źródło
op1
, prawda? Jeśli że jeden szczątki nieobsługiwany, to będzie obniżyć proces, prawda?op1
wyjątek, aniop2
wyjątek nie sprowadziłby programu. Zaletą jest to, że masz okazję obserwować oba. Ale jeśli tego nie zrobisz, oboje zostaną połknięci. Mogę się jednak mylić.TL; DR - Nie , nie powinieneś po prostu cicho ignorować wyjątki.
Spójrzmy na założenia.
Bez wątpienia stwardnienie rozsiane ma naprawdę świetnych ludzi. Mają też wielu menedżerów i menedżerów, którzy są ... nieświadomi i konsekwentnie podejmują złe decyzje. O ile chcielibyśmy wierzyć w bajkę technicznie wytrawnego naukowca kierującego rozwojem produktu, rzeczywistość jest o wiele bardziej ponura.
Chodzi mi o to, że jeśli twój instynkt mówi ci, że coś może być nie tak, istnieje duża szansa (i wcześniejszy precedens), że jest to coś złego.
Sposób postępowania w przypadku wyjątków w tym przypadku jest decyzją dotyczącą czynników ludzkich, a nie decyzją techniczną. Luźno wyjątek jest błędem. Prezentacja błędu, nawet jeśli jest źle sformatowana, zapewnia użytkownikowi krytyczne informacje. Mianowicie, coś poszło nie tak.
Rozważ tę hipotetyczną rozmowę między użytkownikiem końcowym a deweloperem.
Nasz biedny, na szczęście hipotetyczny Deweloper musi teraz dowiedzieć się, co poszło nie tak w łańcuchu wydarzeń. Gdzie to było?
Powiadomienie modułu obsługi zdarzenia -> Procedura obsługi zdarzenia -> Metoda wywołana przez moduł obsługi -> początek asynchronicznego wywołania -> 7 warstw sieci OSI -> fizyczna transmisja -> wykonaj kopię zapasową 7 warstw sieci OSI -> usługa odbioru -> metoda wywołana przez usługę -> ... -> odpowiedź zwrotna wysłana przez usługę -> .... -> potwierdzenie asynch -> przetwarzanie odpowiedzi asynch -> ...
I pamiętaj, że opisałem kilka potencjalnych ścieżek błędów.
Po uwzględnieniu niektórych podstawowych założeń wydaje mi się, że staje się bardziej jasne, dlaczego ciche tłumienie wyjątków jest złym pomysłem. Wyjątek i powiązany komunikat o błędzie jest kluczowym wskaźnikiem dla użytkowników, że coś poszło nie tak. Nawet jeśli wiadomość nie ma znaczenia dla użytkownika końcowego, osadzone informacje mogą być przydatne dla programisty w zrozumieniu, co poszło nie tak. Jeśli będą mieli szczęście, wiadomość doprowadzi nawet do rozwiązania.
Myślę, że część problemu polega na tym, że niepoprawnie obsłużony wyjątek spowoduje awarię aplikacji. Pomijając wyjątki, aplikacja nie ulegnie awarii. Jest w tym jednak pewna ważność, ponieważ asynchronizacja polega na umożliwieniu aplikacji działania podczas pobierania danych. Logiczne rozszerzenie nie mówi, że jeśli możesz nadal działać podczas oczekiwania na wyniki, to niepowodzenie pobierania nie powinno również spowodować awarii aplikacji - wywołanie asynchroniczne jest domyślnie deklarowane jako niewystarczająco ważne, aby zakończyć aplikację.
Jest to rozwiązanie, ale rozwiązuje zły problem. Zapewnienie opakowania obsługi wyjątków nie wymaga tak dużego wysiłku, aby aplikacja mogła pozostać uruchomiona. Wychwycono wyjątek, komunikat o błędzie zostanie wyświetlony na ekranie lub zalogowany, a aplikacja będzie mogła nadal działać. Pominięcie wyjątku oznacza, że ignorowanie błędów będzie A-OK, a dzięki testom upewnisz się, że wyjątki i tak nigdy nie uciekną w pole.
Ostatecznie oceniam, że jest to niedopracowana próba rozwiązania problemu stworzonego przez popchnięcie ludzi do modelu asynchronicznego, gdy nie byli gotowi na zmianę sposobu myślenia.
źródło