Ці повідомлення призначені для інших розробників
Очікується, що ці повідомлення прочитають розробники, щоб допомогти їм налагодити додаток. Це може мати дві форми:
Активна налагодження. Ви насправді працюєте налагоджувачем під час написання коду та намагаєтесь з’ясувати, що відбувається. У цьому контексті корисний виняток допоможе вам зрозуміти, що відбувається не так, або, врешті-решт, запропонувати рішення (хоча це необов’язково).
Пасивна налагодження. Код працює у виробництві та виходить з ладу. Виняток записується в журнал, але ви отримуєте лише повідомлення та слід стека. У цьому контексті корисне повідомлення про виключення допоможе швидко локалізувати помилку.
Оскільки ці повідомлення часто реєструються, це також означає, що ви не повинні містити там конфіденційну інформацію (наприклад, приватні ключі або паролі, навіть якщо це може бути корисно для налагодження програми).
Наприклад, 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, переклад цих повідомлень абсолютно неправильний, оскільки, як очікується, будь-який розробник зможе читати англійською мовою). Розбір таких повідомлень близький до неможливого.