викид з програми виконання Java


12

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

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

Що потрібно коли-небудь кидати безперебійним винятком у бізнес-додатку?

З мого досвіду про винятки з виконання:

1) Неперевірені винятки роблять код непередбачуваним, оскільки вони не відображаються навіть у Javadoc.

2) Кидати неперевірені винятки у бізнес-додатку є безглуздим, оскільки, коли ви кидаєте його, і він іде прямо на обличчя Користувачів, як ви поясните це користувачеві? Я бачив достатньо веб-додатків, які показують, 500 -Internal Error. Contact Administratorщо не означає нічого для кінцевого користувача або для команди підтримки, яка керує програмою.

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


Чи можете ви пояснити, що таке рівень обслуговування? Найбільш віддалений шар від користувача чи найближчий до користувача?
Маной Р

Чому це питання не підходить до SO?
Bjarke Freund-Hansen

@Manoj R: Ні. Рівень або рівень обслуговування - це те, де виконуються бізнес-правила та логіка, відокремлені як від деталей технології DB, так і від презентації клієнта.
Майкл Боргвардт

6
Неперевірені винятки [...] не відображаються навіть у Javadoc. => вони з’являться, якщо ви документуєте їх @throwsтегом, що, до речі, є хорошою практикою.
assylias

4
@SureshKoya Ефективна Java, пункт 62: Документуйте всі винятки, викинуті кожним методом. Витяг. Використовуйте @throwsтег Javadoc для документування кожного неперевіреного винятку, який може перекинути метод, але не використовуйте ключове слово кидок, щоб включити неперевірені винятки в декларацію методу.
assylias

Відповіді:


13

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

Щодо ваших балів:

1) Перевірені винятки роблять код брудним і не менш непередбачуваним, оскільки вони з’являються скрізь .

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

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

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

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

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

1. Ну а у випадку неперевіреного винятку, ви навіть не знатимете, чи може дзвінок призвести до перевірки. 2. Коли ви сказали "Це абсолютно ортогонально смисловому значенню винятку, але прив'язування його до ієрархії класів змушує вас змішати два", я вважаю, що ви мали на увазі виклик ієрархії замість ієрархії класів.
випадкова речовинаOfLivingThing

2
@Suresh Koya: Ні, я мав на увазі ієрархію класів, перевіряється той факт, що декларація SQLException extends Exceptionозначає, що вибір кинути, SQLExceptionоскільки помилка пов'язана з доступом до БД, означає, що виключення перевіряється. І ви можете задокументувати неперевірені винятки в коментарях Javadoc просто чудово. Добре працює на всіх інших мовах.
Майкл Боргвардт

1
@MichaelBorgwardt "Перевірені винятки - це невдалий вираз у мовному дизайні", це ваша особиста думка, якщо ні, я хотів би прочитати докладніше про це. Будь-яке справжнє посилання було б чудово допомогти
Vipin

2
@Vipin: Це моя особиста думка, але така, якою поділяються багато інших людей, наприклад, Брюс Еккель : mindview.net/Etc/Discussions/CheckedExceptions - і той факт, що жодна інша мова не прийняла перевірених винятків за 20 років з часу запровадження Java. для себе ...
Майкл Боргвардт

2

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

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

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

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

Я думаю, що філософія, яку ви згадуєте, походить з одного з двох джерел:

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

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

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

Крім того, навіть якщо виняток із виконання програми буде кинуто, я віддаю перевагу конвенції, на яку вказував @assylias.
випадкова речовинаOfLivingThing

1

Якщо ви не хочете неперевірених винятків під час виконання, тоді чому ви використовуєте Java? Існує можливість виключень з виконання часу майже скрізь - зокрема, винятки NullPointerException, ArithmeticException, ArrayIndexOutOfBounds та ін.

Коли ви прочитаєте файли журналів якоїсь системи J2EE, наприклад, установки SAP NetWeaver, ви побачите, що такі винятки відбуваються буквально весь час.


З специфікації мови Java: "Класи виключень під час виконання (RuntimeException та його підкласи) звільнені від перевірки часу компіляції, оскільки, на думку дизайнерів мови програмування Java, оголошення таких винятків не допомогло б істотно встановити правильність програм. Багато операцій і конструкцій мови програмування Java можуть спричинити винятки під час виконання програми ".
randomin substanceOfLivingThing

1
Виняток із виконання, про який ви говорите, - це ті, які виникають із Java, оскільки система виконання Java не має поняття, чому ви намагаєтесь робити конкретний виклик. Напр .: NullPointerException виникає, якщо ви викликаєте метод null. У такому випадку система виконання Java не має правильного слова для програмістів, які були дурними, і блякнула абонента за допомогою NullPointerException. Сумна частина абонента продала вам продукт Netweaver, і ви як користувач стаєте жертвою поганого програмування. Випробувачі в рівній мірі винні, оскільки вони не зробили всіх граничних тестів.
випадкова речовинаOfLivingThing

1

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

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

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

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

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

Один із способів поводження з винятком - це скинути ще один виняток, який забезпечує опис проблеми вищого рівня (наприклад, " failed to initialize" замість " index out of bounds"). Це гарна модель, доки ви не втратите інформацію про причину винятку; використовувати докладний виняток, щоб ініціалізувати виняток causeвищого рівня або записати деталі (як обговорено вище). Ведення журналу є найбільш доцільним, коли ви збираєтеся перейти межу міжпроцесою, наприклад, виклик IPC, оскільки немає гарантії, що клас винятку низького рівня взагалі буде присутній на іншому кінці з'єднання. Тримання як прикріпленої причини є найбільш доцільним при перетині внутрішньої межі.

Ще один шаблон, який ви бачите, - це прихоплення та випуск:

try {
    // ...
} catch (FooException e) {
    throw e;
}

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

Немає реальної різниці між перевіреними винятками та неперевіреними, крім того, що ви повинні оголосити перевірені винятки, які перетинають межі методу. Це все-таки хороша ідея документувати вивірені винятки (з @throwsкоментарем javadoc), якщо ви знаєте, що їх навмисно кидають ваш код. Навмисно не кидайте java.lang.Errorта його підкласи (якщо ви не пишете реалізацію JVM).

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


0

Я думаю, ви повинні ТІЛЬКИ кинути перевірений виняток, коли програма може відновитись. Отже, користувачі вашої бібліотеки повинні виловлювати ці винятки та робити все, що потрібно для відновлення. Все інше повинно бути відміченим.

Як приклад,

Якщо ваш додаток завантажує дані або з файлу, або з бази даних. Потім,..

try {
  File data = new File(...);
  // parse file here
} catch (Exception ex) {
  throw new MissingDataFileException("data file not found");
}

абонент може завжди зловити перевірену MissingDataFileException, а потім спробувати завантажити дані з бази даних.

try {
  Connection con = DriverManager.getConnection( host, username, password );
  // query data here
} catch (Exception ex) {
  throw new RuntimeException("better call Saul!");
}

1
Саул загинув в автокатастрофі 3 роки тому. Збій! ;-)
стипендіати Дональ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.