Хто повинен читати Exception.Message, якщо він є?


27

Створюючи винятки, чи слід писати повідомлення, які повинен розуміти користувач або розробник? Хто насправді повинен бути читачем повідомлень про виключення?

Я вважаю, що повідомлення про винятки зовсім не корисні, і мені завжди важко їх писати. Згідно з умовами, тип винятку вже повинен нам повідомити, чому щось не працювало, а власні властивості можуть додавати ще більше інформації, як імена файлів, індекси, ключі тощо, тож чому повторювати це у самому повідомленні? Автогенероване повідомлення також може робити, і все, що воно повинно містити, - це назва винятку зі списком додаткових властивостей. Це було б так само корисно, як і рукописний текст.

Хіба не було б краще взагалі не писати повідомлення, але натомість мати спеціальних рендерів для виключень, які піклуються про створення значущих повідомлень, можливо, на різних мовах, а не на жорсткому кодуванні їх у коді?


Мене запитали, чи не відповідає жодне з цих питань на моє запитання:

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

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

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

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


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

2
@ThomasOwens Я читав їх обох, але вони не звертаються до певного приймача повідомлення про виключення. Вони взагалі говорять про користувачів, але хто він? Чи користувач програмного забезпечення, який тепер має уявлення про програмування, або розробники, які повинні аналізувати, що пішло не так? Я ніколи не знаю, до кого звертатись, коли пишуть повідомлення.
t3chb0t

2
Я думаю, що хороша відповідь тут може стосуватися будь-якого або обох цих питань, але вони далеко не дублікати.
Гонки легкості з Монікою

1
Чому на землі це було закрито як дублікат? Навіть якщо це був дублікат того іншого питання (якого це не так), на це явно є краща відповідь, він повинен бути другим, який позначений як дублікат.
Бен Аронсон

2
@MichaelT Я все ще не дуже бачу там, що перетинається, якщо ви не припускаєте, що повідомлення про виключення призначене для користувачів
Бен Ааронсон

Відповіді:


46

Ці повідомлення призначені для інших розробників

Очікується, що ці повідомлення прочитають розробники, щоб допомогти їм налагодити додаток. Це може мати дві форми:

  • Активна налагодження. Ви насправді працюєте налагоджувачем під час написання коду та намагаєтесь з’ясувати, що відбувається. У цьому контексті корисний виняток допоможе вам зрозуміти, що відбувається не так, або, врешті-решт, запропонувати рішення (хоча це необов’язково).

  • Пасивна налагодження. Код працює у виробництві та виходить з ладу. Виняток записується в журнал, але ви отримуєте лише повідомлення та слід стека. У цьому контексті корисне повідомлення про виключення допоможе швидко локалізувати помилку.

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

Наприклад, IOSecurityExceptionтип виключення, викинутого під час запису файлу, не є явним щодо проблеми: це тому, що у нас немає дозволів на доступ до файлу? А може, ми можемо це прочитати, але не написати? А може, файл не існує, і ми не маємо дозволів на створення файлів там? Або, можливо, він заблокований (сподіваємось, тип винятку в цьому випадку буде іншим, але на практиці типи іноді можуть бути виразними). Чи, можливо, безпека доступу до коду заважає нам робити будь-які операції вводу / виводу?

Замість цього:

IOSecurityException: файл знайдено, але в дозволі на читання його вмісту було відмовлено.

набагато чіткіше. Тут ми одразу знаємо, що дозволи в каталозі встановлені правильно (інакше ми не зможемо знати, що файл існує), але дозволи на рівні файлів є проблематичними.

Це також означає, що якщо ви не можете надати будь-яку додаткову інформацію, яка вже не є типом винятку, ви можете залишити повідомлення порожнім. DivisionByZeroExceptionє хорошим прикладом, коли повідомлення є зайвим. З іншого боку, те, що більшість мов дозволяють викинути виняток, не вказуючи його повідомлення, робиться з іншої причини: або тому, що повідомлення за замовчуванням вже доступне, або тому, що воно буде створене пізніше, якщо потрібно (і створення цього повідомлення вкладається в тип винятку, що має ідеальний сенс, "OOPly", кажучи).

Зауважте, що з технічних (найчастіше виконання) причин деякі повідомлення виявляються набагато дурнішими, ніж повинні бути. .NET NullReferenceException:

Посилання на об'єкт не встановлено для примірника об'єкта.

є прекрасним прикладом повідомлення, яке не є корисним. Корисним повідомленням буде:

Посилання на об'єкт productне встановлено для примірника об'єкта, коли його викликають product.Price.

Ці повідомлення не для кінцевих користувачів!

Кінцеві користувачі не бачать повідомлень про виключення. Ніколи. Хоча деякі розробники в кінцевому підсумку показують ці повідомлення користувачам, це призводить до поганого досвіду роботи та розладу. Такі повідомлення, як:

Посилання на об'єкт не встановлено для примірника об'єкта.

не означають абсолютно нічого для кінцевого споживача, і його слід уникати будь-якою ціною.

Найгірший сценарій - це глобальна спроба / ловити, яка кидає виняток для користувача та закриває додаток. Додаток, який піклується про своїх користувачів:

  • В першу чергу обробляє винятки. Більшість з них можна обробляти, не турбуючи користувача. Мережа не працює? Чому б не почекати кілька секунд і спробувати ще раз?

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

  • Запрошує користувача виконати дію у формі, яка не є помилкою. Немає достатнього дозволу для доступу до файлу? Чому б не попросити користувача надати адміністративні дозволи або вибрати інший файл?

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

    У своєму запитанні ви запропонували виключити два повідомлення: технічне для розробників та одне для кінцевих користувачів. Хоча це є дійсною пропозицією в деяких незначних випадках, більшість винятків створюються на рівні, коли неможливо скласти змістовне повідомлення для користувачів. Візьміть DivisionByZeroExceptionі уявіть, що ми не могли запобігти винятку і не можемо впоратися самі. Коли відбудеться поділ, чи знає фреймворк (оскільки це фреймворк, а не діловий код, який кидає виняток), що буде корисним повідомленням для користувача? Абсолютно не:

    Відбувся поділ на нуль. [ДОБРЕ]

    Натомість можна дозволити це викинути виняток, а потім схопити його на більш високому рівні, де ми знали контекст бізнесу та могли б діяти відповідно для того, щоб реально допомогти кінцевому користувачеві, таким чином показавши щось на кшталт:

    Поле D13 не може мати значення, ідентичне значенню в полі Е6, оскільки віднімання цих значень використовується як дільник. [ДОБРЕ]

    або можливо:

    Значення, повідомлені службою ATP, не відповідають місцевим даним. Це може бути викликано тим, що локальні дані не синхронізовані. Хочете синхронізувати інформацію про доставку та повторити спробу? [Так ні]

Ці повідомлення не призначені для розбору

Не очікується, що повідомлення про виключення будуть також розібрані або використані програмно. Якщо ви вважаєте, що абоненту може знадобитися додаткова інформація, включіть її у виняток поруч із повідомленням. Це важливо, оскільки повідомлення може бути змінено без попереднього повідомлення. Тип є частиною інтерфейсу, але повідомлення це не так: ніколи не покладайтеся на нього для обробки виключень.

Уявіть повідомлення про виключення:

Час підключення до перерви кешування вичерпано після очікування 500 мс. Або збільшити час очікування або перевірити моніторинг продуктивності, щоб виявити падіння продуктивності сервера. Середній час очікування кешування-сервера становив 6 мс. за останній місяць, 4 мс. за останній тиждень і 377 мс. за останню годину

Ви хочете отримати значення "500", "6", "4" та "377". Подумайте трохи про підхід, який ви будете використовувати для розбору, і лише потім продовжуйте читати.

У вас є ідея? Чудово.

Тепер оригінальний розробник виявив помилку помилки:

Connecting to the caching sever timed out after waiting [...]

має бути:

                            ↓
Connecting to the caching server timed out after waiting [...]

Більше того, розробник вважає, що місяць / тиждень / одна година не є особливо актуальним, тому він також вносить додаткові зміни:

Середній час очікування кешування-сервера становив 6 мс. за останній місяць, 5 мс. за останні 24 години та 377 мс. за останню годину

Що відбувається з вашим розбором?

Замість розбору ви можете використовувати властивості виключень (які можуть містити все, що хто хоче, як тільки дані можуть бути серіалізовані):

{
    message: "Connecting to the caching [...]",
    properties: {
        "timeout": 500,
        "statistics": [
            { "timespan": 1, "unit": "month", "average-timeout": 6 },
            { "timespan": 7, "unit": "day", "average-timeout": 4 },
            { "timespan": 1, "unit": "hour", "average-timeout": 377 },
        ]
    }
}

Наскільки просто зараз використовувати ці дані?

Іноді (наприклад, у .NET) повідомлення навіть можна перекласти на мову користувача (IMHO, переклад цих повідомлень абсолютно неправильний, оскільки, як очікується, будь-який розробник зможе читати англійською мовою). Розбір таких повідомлень близький до неможливого.


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

1
@Neil: це трохи занадто теоретично. На практиці користь від приховування журналів від користувача переважає складність онлайн-журналу. Не рахуючи зручного для користувача аспекту. Уявіть, що ви встановлюєте Visual Studio на новій Windows VM. Раптом установка не вдається. Ви б хотіли просто перейти до журналів та самостійно діагностувати проблему (за допомогою Stack Exchange та блогів) або почекати, поки Microsoft вирішить проблему та опублікує виправлення?
Арсеній Муренко

4
Я думаю, що всі знають, що повідомлення "посилання на об'єкт ..." не є корисним. Хоча відповідне питання - який машинний код ви хотіли б створити джиттера, який видає потрібне повідомлення? Якщо ви зробите цю вправу, ви швидко виявите, що повідомлення неможливо легко генерувати без величезних витрат на ефективність, накладених на всі не виключні випадки . Користь від того, щоб зробити недбалу роботу розробника дуже легшою, не виплачується хітом продуктивності для кінцевого користувача.
Ерік Ліпперт

7
Щодо винятків із безпеки: чим менше інформації у винятку, тим краще. Мій улюблений анекдот полягає в тому, що в попередній бета-версії .NET 1.0 ви могли отримати повідомлення про виключення типу "Ви не маєте дозволу визначати ім'я файлу C: \ foo.txt". Чудово, дякую за детальне повідомлення про виключення!
Ерік Ліпперт

2
Я не згоден ніколи не показувати кінцевому користувачеві детальне повідомлення про помилку. Зі мною траплялося багато разів, коли я отримую криптовалютне повідомлення про помилку, яке заважає мені запустити свою гру / програмне забезпечення, але коли я переглядаю Google, я з’ясовую, що існує легкий спосіб вирішення. Без цього повідомлення про помилку не було б способу знайти вирішення. Можливо, краще просто заховати деталі під кнопкою «більше деталей»?
BlueRaja - Danny Pflughoeft

2

Відповідь на це повністю залежить від винятку.

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

Однак більшу частину часу користувач не може виправити невиконаний виняток. Більшість із них передбачає внесення змін до коду. У цих випадках споживачем повідомлення явно є розробник.

Випадок спійманих винятків є складнішим, оскільки у вас є можливість правильно обробити виняток і кинути більш дружній. Одна написана мовою сценаріїв кинула винятки, повідомлення яких було дуже чітко призначено для розробника. Однак, як стек розкручується, я додав сліди стека стежок, що читаються користувачем, всередині мови сценаріїв. Мої користувачі дуже рідко могли переробляти повідомлення, але вони могли подивитися на стек стека у своєму сценарії та зрозуміти, що траплялось у 95% часу. Для решти 5%, коли вони мені зателефонували, ми мали не лише слід стека, але і готове для розробника повідомлення, яке допоможе мені зрозуміти, що не так.

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


1
"Якщо виняток викликаний помилкою файлової системи під час відкриття файлу, можливо, має сенс надіслати це повідомлення кінцевому користувачеві": але коли ви кинете помилку файлової системи, ви не знаєте контексту: це може бути дія користувача або щось зовсім не пов’язане між собою (наприклад, ваша програма робить резервну копію певної конфігурації, без того, щоб користувач навіть цього не помічав). Це означає, що у вас буде блок спробувати / ловити, який показує повідомлення про помилку , що сильно відрізняється від прямого показу повідомлення про виключення .
Арсеній Муренко

@MainMa Ви, можливо, не знаєте контексту прямо, але є багато підказок. Наприклад, якщо вони відкривають файл, і виняток - "IOError: дозвіл відхилено", є обґрунтований шанс, що користувач може скласти 2 і 2 разом і розібратися у відповідному файлі. Мій улюблений редактор робить це - він просто виводить текст виключення у діалоговому вікні, без пуху. З іншого боку, якщо я завантажував свою заявку і отримував "дозвіл відмовлений" під час завантаження купу зображень, набагато менш розумно припускати, що користувач може щось зробити з інформацією.
Корт Аммон - Відновіть Моніку

Аргументуючи свою думку, я ніколи не бачив жодної цінності показу користувачеві NullReferenceException, крім того, що сам акт відображення цього повідомлення показує, що у вашому програмному забезпеченні не було поняття, як відновити! Це повідомлення про виключення ніколи не корисне кінцевому користувачеві.
Корт Аммон - Відновіть Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.