Чи доцільніше реєструвати винятки в загальному чи базовому класі виключень?


15

Я переробляю досить великий веб-додаток. Одне з найважливіших питань - непослідовність поводження з помилками, і я намагаюся придумати розумну стратегію. Я створив спеціальний обробник помилок через set_error_handler, який по суті перетворює помилки PHP у ErrorExceptions та спеціальний базовий клас виключень, який безпосередньо успадковується від Exception .

У виробництві я використовую загальний загальний виняток через set_exception_handler , і я збираюся додати журнал виключень в суміш * . Моя дилема полягає в тому, де робити фактичну реєстрацію в базовому класі винятків або в уловці.

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

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

і одна причина для входу в базовий клас виключень:

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

Чи є якась прийнятна практика щодо реєстрації винятків?

* Спочатку ведення журналу передбачає запис у текстовий файл спочатку, і це може перерости до надсилання електронної пошти для певних типів винятків.


Деякі пояснення, спонукувані @ unholysampler в відповідь :

Я зіткнувся з кодовою базою слоїв 2 * 10 ^ 6, з великою кількістю сторонніх речей, над якими я не маю ніякого контролю, а в деяких кодах я маю контроль над винятками перед датами у PHP. І є також недавній недавній код, ми відновлюємося від тривалого періоду напруженого тиску, коли нам практично довелося перестати думати і просто зламали.

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

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

Відповіді:


11

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

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

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

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

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


Я додав роз'яснення до питання, підказаного вашою відповіддю. З того, що я зібрав, з практичної сторони питання, яке ви пропонуєте увійти в лову?
янніс

1
@YannisRizos: Так, ви повинні реалізувати загальну інформацію як свій перший крок. Те, що я сказав про привід-all, було більше для того, щоб ви не використовували його як нормальну частину вашого потоку коду. Реалізація необробленого обробника винятків важлива, оскільки дозволяє отримувати багато інформації щоразу, коли ваш код робить щось погане.
unholysampler

Чи немає фреймів для ведення журналів, які могли б зручно обробляти концепцію "Ось купа речей, які повинні потрапляти в журнал, якщо вона не буде замінена"? Кожен шар, який бачить виняток, може замінити дані попереднього, за винятком того випадку, якщо новий виняток буде скинуто в процесі стека, розмотуючи останній звіт журналу, не буде замінено і таким чином буде записано. Чи жодна структура не підтримує таку схему?
supercat

3

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

Нашим рішенням було запропонувати механізм, який використовував конфігурацію виконання, щоб увімкнути тип винятку разом із дешевим стеком при спробі діагностувати ці проблеми.


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