Грунтовність винятків


9

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

  • BadRequestException
  • AuthenticationFailureException
  • ProductNotFoundException

Кожен із них побудований на основі коду помилки, повернутого з API.

Після переваг винятків це здається ідіоматичним для Java. Однак думка моїх друзів не зовсім рідкість.

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


Сторінка, на яку ви пов’язали, - це, мабуть, найкраща остаточна відповідь, яку ми можемо отримати. Ви насправді запитуєте про думку. Я можу відповісти, яким є мій досвід та думка, але це не об'єктивна відповідь.
марстато

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

Я абсолютно згоден. У мене теж є класи класів винятків, зернисті. Крім того, ви можете визначити abstractта узагальнити класи винятків методами getter, а потім змусити деталізовані розширити загальні. Напр AuthenticationFaliureException extends ClientErrorException. Таким чином, кожен користувач може вибрати, яким чином він хотів би поводитися з винятками. Це, очевидно, більше працює. Однак при написанні програми (замість бібліотеки) IMHO інша ситуація. У такому випадку я б не робив винятки більш детальними, ніж вони вам потрібні, для простоти.
марстато

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

Відповіді:


15

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

Зазвичай це компроміс. Його можна певною мірою пом'якшити, використовуючи успадкування (загальний базовий клас винятку для тих, хто телефонує, хто хоче загалом ловити та записати все, і вивести винятки з цього базового класу для тих, хто телефонує, хто потребує різних реакцій), але навіть це може призвести до багато зайвих складностей, якщо ви не будете обережні і дотримуєтесь принципу YAGNI. Тож головне питання має бути тут:

  • Ви дійсно очікуєте, що абонент вашого коду реагуватиме по-різному, з різним потоком контролю, на ці різні помилки?

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

  • якийсь додаток, де ви або команда має всю свою кодову базу під вашим контролем?

  • або якийсь компонент для багаторазового використання для сторонніх осіб, де ви не знаєте всіх потенційних абонентів?

  • тривале запущене серверне додаток, коли різні види помилок не повинні негайно зламати всю систему і можуть вимагати різного виду усунення помилок?

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

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


3
"Ви дійсно очікуєте, що абонент вашого коду реагуватиме по-різному, з різним потоком контролю, на ці різні помилки?" це чудове запитання. Дякую, я пам’ятаю це.

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

1

Відповідь залежить від того, про який рівень повідомлень про помилки ми говоримо.

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

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

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

Однак вам не доведеться зупинятися на цьому. Поширена помилка може виникнути в одному з ваших компонентів, і ви, можливо, захочете повідомити, що у вашому компоненті виникла проблема . Тож не тільки те, що пішло не так, а й куди. Тоді було б доречно зафіксувати перший виняток у MyComponentException. Це дасть вам найкраще з обох світів.

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


Це справедливо. Отже, ви пропонуєте не вигадувати новий виняток, коли хороший вже існує?

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