Чому «журнал і кидок» вважається антивізером? [зачинено]


85

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

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


Спробуйте знайти відповідь на softwareengineering.stackexchange.com
chharvey

Відповіді:


121

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

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

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


для подальших деталей див. коментарі до відповіді Джеффа
Ману

8
Причиною реєстрації та повторного видалення виключення є звуження причини та реєстрація конкретного повідомлення.
Mike Argyriou

11
Відповідь: може бути корисна інформація про налагодження, доступна в поточній точці стека, яка не буде доступна в іншій точці трасування стека
rtconner

Вилов та повторний викид іноді корисний, якщо новий виняток є більш корисним із більшою інформацією або більш конкретним.
borjab

Щоб витратити на те, що прокоментував @rtconner: в асинхронному коді може бути, що уловлювач не має контексту, доступного для метателя.
Нір Альфасі,

53

Log-and-throw є хорошим шаблоном, якщо суб'єкт, який ловить і повертає виняток, має підстави вважати, що він містить інформацію, яка не буде реєструватися далі в стеці викликів - принаймні, не найбільш бажаним способом. Це може статися з кількох причин:

  1. Виняток може бути перехоплений та відновлений на межі рівня додатку та може містити привілейовану інформацію. Погано було б для рівня бази даних дозволити виняток, наприклад, "Спроба додати повторюваний ключ" fnord "у поле" users "", щоб досягти зовнішнього рівня програми (що, в свою чергу, може піддати його користувачеві), але це може бути корисним для внутрішніх частин бази даних викинути такий виняток та інтерфейсу програми, щоб його вловити, надійно зареєструвати та відновити дещо менш описовий виняток.
  2. Виняток може становити той, який зовнішній шар, мабуть, очікував би обробляти без реєстрації, але внутрішній шар може знати щось, чого зовнішній шар не знає, що може припустити, що ведення журналу може бути корисним. Як грубий приклад, середній рівень програми може бути запрограмований на спробу підключення до одного сервера, а якщо це не працює, спробуйте інший. Затоплення журналу програми повідомленнями про "збій з'єднання", коли сервер не працює для обслуговування, може бути не корисним, тим більше, що - з точки зору програми, все працювало нормально. Може бути корисно переслати інформацію про збій з'єднання на ресурс реєстрації, пов'язаний із серверами, який потім зможе відфільтрувати журнали, щоб створити звіт про те, коли сервер піднімався і опускався, на відміну від журналу кожної спроби з'єднання .

4
№1 справді є розумним випадком загального користування, однак УП чітко запитував "переробити його (звичайно, зберігши оригінальний слід стека)", тому №1 не є правильною відповіддю.
Джеффрі Чжен

@GeoffreyZheng: Це залежатиме від того, чи надійне реєстрація вихідного трасування стека буде вважатися "збереженням".
суперкіт

2
Щодо №1: викриття вмісту винятків (наприклад, відображення e.getMessage()/ стек-трасування в інтерфейсі користувача, а також надсилання його як відповідь REST) ​​слід розглядати як саму вразливість, оскільки виняток виконання може містити будь-яку конфіденційну інформацію. Щодо №2: ви можете повторно кинути виняток, додавши всю інформацію, яку хочете знати клієнту (+ першопричина), не потрібно нічого реєструвати.
Микита Босік

@NikitaBosik: Незалежно від того, чи слід винятки виставляти на стороні клієнта, додатки, які роблять це, є достатньо поширеними, щоб принцип "глибокої безпеки" передбачав, що повідомлення про винятки слід очищати від конфіденційної інформації. Крім того, якщо зовнішній рівень не очікує відкинути певний тип винятку, не реєструючи його, а також не пересилаючи інформацію зовнішньому об'єкту, який може бути зацікавлений, додавання середнього рівня інформації, яку зовнішній шар збирається ігнорувати, не допоможе нічого.
supercat

20

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

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

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


1
Я погоджуюсь, що у вас повинен бути один обробник вищого рівня, який робить це за вас. Але на мою думку, обробник вищого рівня ПОВИНЕН бути "вписати і кинути". Отже, суперечка навколо, В ЯКІЙ ТОЧКІ "вписати і кинути", а не вологіше чи взагалі цього не робити?!?
Ману

@Manu, я думаю, справа в тому, що якщо це єдиний обробник (централізований), це нормально. Якщо ви дублюєте код, це не добре. Я не думаю, що в цьому є щось більше, ніж це!
Jeff Foster

5
@Manu - до чого звертається обробник верхнього рівня в такому випадку? Мені здається, що якщо є що-небудь доступне для цього, то це насправді не є обробником найвищого рівня. І ви точно не хочете переробляти виняток до самого середовища виконання. Це призведе до зупинки більшості програм.
aroth

1
@aroth: Я бачу, що ви говорите або "журнал і обробка" (якщо ви є обробником найвищого рівня), або "не реєструйте і не кидайте (або обробляйте інакше)", якщо ні. Дякую, що вказали на це.
Manu

9

Журнал і кидок ІМО є явним порушенням Принципу найменшого сюрпризу.

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


А як щодо журналів без помилок?
Су Чжан,

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