Чи повинна моя бібліотека завдань з асинхрії тихо ковтати винятки?


10

Щойно я дізнався, що .NET 4.5 внесла зміни в обробку винятків всередині Task. А саме вони тихо пригнічуються.

Офіційне мотивування того, чому це було зроблено, виглядає як "ми хотіли бути більш доброзичливими до недосвідчених розробників":

У .NET 4.5 Завдання мають значно більшу популярність, ніж у .NET 4, оскільки вони використовуються в мовах C # та Visual Basic як частина нових функцій асинхронізації, підтримуваних мовами. Це фактично переносить Завдання з домену досвідчених розробників у сферу кожного. Як результат, це також призводить до нового набору компромісів щодо того, наскільки суворо слід дотримуватися обробку виключень.

( джерело )

Я навчився вірити, що багато рішень у .NET приймалися людьми, які дійсно знають, що роблять, і зазвичай є дуже вагома причина для того, що вони вирішують. Але цей рятується від мене.

Якщо я розробляв власну бібліотеку завдань з асинхронією, то яка перевага при ковтанні винятків, які розробники Framework бачили, що я не бачу?


4
+1. Хороше запитання, враховуючи той факт, що не поширюючи винятки, з якими ви не можете впоратися, є поганою практикою навіть убік асинхронного контексту. Також аргумент щодо недосвідчених розробників досить кульгавий, IMHO. Що для новачків буде більш незручним, ніж фрагмент коду, який не тільки не працює, але й не припускає жодних винятків?
Арсеній Муренко

@MainMa Точно мої думки, але я раніше помилявся (коли виявилося, що вони насправді мають дуже гарну, але не очевидну причину), тому я подумав, що запитаю.
Роман Старков

2
Нічого собі, я радий, що ви опублікували це лише тому, що це перше, що я чув про це; і це, безумовно, порушує POLA . Ви маєте рацію, що ті хлопці справді знають, що вони роблять, тому мені щиро цікаво, які міркування можуть стояти за цим ... Задумуйтесь, чи є у них більш технічна причина, заснована на впровадженні Async та як розповсюджуватимуться винятки як дно передано до розробки ..
Джиммі Хоффа

Відповіді:


2

Для чого це варто, документ, з яким ви зв'язали, наводить приклад як обґрунтування:

Task op1 = FooAsync(); 
Task op2 = BarAsync(); 
await op1; 
await op2;

У цьому коді розробник запускає дві асинхронні операції, які будуть виконуватися паралельно, а потім асинхронно чекає кожного, використовуючи нову функцію мови очікування ... [C] розглядає, що буде, якщо вини і op1, і op2. Очікування op1 поширюватиме виняток op1, і тому op2 ніколи не чекатиме. Як результат, виняток op2 не буде дотримано, і процес врешті-решт завершиться збоєм.

Щоб полегшити розробникам написання асинхронного коду на основі завдань, .NET 4.5 змінює поведінку винятків за замовчуванням для непомічених винятків. Хоча незабезпечені винятки все ще спричинятимуть підвищення події UnobservaTaskException (якщо це не буде, то це буде переломною зміною), процес за замовчуванням не завершиться. Швидше за все, виняток закінчиться поїданням після події, незалежно від того, чи дотримується обробник події.

Я в цьому не переконаний. Він виключає можливість однозначної, але важко відстежувати помилку (таємничий збій програми, який може статися черездовго після фактичної помилки), але замінює її можливістю абсолютно безшумної помилки - яка згодом може стати настільки ж важкою для відстеження проблеми у вашій програмі. Мені це здається сумнівним вибором.

Поведінка налаштована - але, звичайно, 99% розробників просто збираються використовувати поведінку за замовчуванням, ніколи не замислюючись над цим питанням. Тож те, що вони обрали за замовчуванням, - велика справа.


Але ви робите отримати нормальне виняток для op1, НЕ так? Якщо це залишатиметься без обробки, це призведе до збиття процесу, правда?
Тімві

1
@Timwi, наскільки я розумію, ні op1виняток, ні op2виняток не принесуть програму. Перевага полягає в тому, що у вас є можливість спостерігати за обома. Але якщо ви цього не зробите, вони будуть проковтнуті. Я можу помилитися.

Я дуже здивований, що вони вважають таким важливим, щоб ви могли «спостерігати» за обома. Якщо ви хочете "спостерігати" за ними, ви їх ловите та повідомляєте про їх виникнення через результат завдання! ... Погодьтесь із вашими міркуваннями, +1
Роман Старков

2

TL; DR - Ні , ви не повинні просто ігнорувати винятки тихо.


Давайте розглянемо припущення.

  • Ваша сліпа віра

Я навчився вірити, що багато рішень у .NET приймалися людьми, які дійсно знають, що роблять, і зазвичай є дуже вагома причина для того, що вони вирішують. Але цей рятується від мене.

У MS є кілька справді геніальних людей на персоналі, без сумніву. У них також є ряд керівників та керівників, які ... незрозумілі, і які послідовно приймають погані рішення. Як би ми не хотіли вірити казці вченого технічно кмітливого, що керує розробкою продукту, реальність набагато похмуріша.

Моя думка, якщо ваш інстинкт говорить вам, що щось може бути не так, то є хороший шанс (і минулий прецедент), що він неправильний.

  • Що це технічне питання

Як поводитися з винятками в цьому випадку - це рішення людських факторів, а не технічне рішення. Виключення - помилка. Повідомлення про помилку, навіть якщо вона неформатована, надає важливу інформацію кінцевому користувачеві. А саме, щось пішло не так.

Розглянемо цю гіпотетичну розмову між кінцевим користувачем та розробником.

Користувач: Додаток зламано.
Dev: Що зламано?
Користувач: Не знаю, натискаю на кнопку, і нічого не відбувається.
Dev: Що ти означає, що нічим не буває?
Користувач: Подивіться, я клацаю, чекаю, і я чекаю, і я чекаю, і нічого ... це, очевидно, зламано.

Наш бідний, на щастя гіпотетичний розробник, тепер повинен з'ясувати, що пішло не так у ланцюзі подій. Де це було?
Повідомлення обробника події -> Повсякденне обробляння події -> Метод, ініційований обробником -> початок асинхронного виклику -> 7 шарів мережі OSI -> фізична передача -> резервне копіювання 7 шарів мережі OSI -> послуга отримання -> метод, викликаний службою -> ... -> повернути відповідь, надісланий службою -> .... -> отримання асинхроніму -> обробка відповіді на асинхрон -> ...

І зауважте, що я описав кілька потенційних помилок.


Звертаючись до деяких основних припущень, я думаю, стає зрозумілішим, чому тихо придушення винятків є поганою ідеєю. Виняток та пов’язане з ним повідомлення про помилку є ключовим показником для користувачів, що щось пішло не так. Навіть якщо повідомлення не має сенсу для кінцевого користувача, вбудована інформація може бути корисною для розробника для розуміння того, що пішло не так. Якщо їм пощастить, повідомлення навіть призведе до рішення.

Я думаю, що проблема тут полягає в тому, що неправильно оброблений виняток призведе до збою вашої програми. Пригнічуючи винятки, програма не вийде з ладу. Існує певна обґрунтованість цього, хоча з точки зору асинхронізації - дозволити програмі продовжувати працювати під час отримання даних. Не так вже й багато логічного розширення, якщо говорити про те, що якщо ви можете продовжувати працювати, очікуючи на результати, то невдача у пошуку також не повинна руйнувати додаток - виклик async неявно оголошується як недостатньо важливий для завершення роботи програми.

Отже, це рішення, але це вирішення неправильної проблеми. Не потрібно багато зусиль, щоб забезпечити обгортку для обробки винятків, щоб програма могла продовжувати працювати. Виняток - це вилучення, повідомлення про помилку, викинуте на екран або ввійшли в систему, і програмі дозволяється продовжувати працювати. Придушення винятку означає, що ігнорування помилок буде А-ОК, і тестування гарантує, що винятки ніколи не потраплять у поле.

Тож моя кінцева оцінка полягає в тому, що це наполовину спроба вирішити проблему, створену шляхом підштовхування людей до асинхронної моделі, коли вони не були готові перекласти своє мислення на цей підхід.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.