Рекомендуйте схему / підхід до викриття / толерантності / відновлення після системних помилок, обробку винятків (наприклад, у Java, C ++, Perl, PHP)


13

Чи можете ви порекомендувати схему / підхід до розкриття / допуску / відновлення після системних помилок, обробку винятків (Java, C ++, Perl, PHP)?

Про деякі помилки потрібно повідомити.

Деякі помилки можна обробляти внутрішньо (шляхом повторного спроби або є несуттєвими (можуть ігноруватися).

Як ви структуруєте код для їх лову?

Але всі помилки потрібно реєструвати.

Які найкращі практики існують?

А для їх моделювання, щоб мати змогу повністю протестувати компоненти, які впливають на них?

Загальне питання, що не стосується мови програмування, застосовне до декількох сучасних мов програмування, але було б вітальним прикладом ілюстрації зразків, підходів та філософій на Java, C ++, PHP та Perl.

(Також запитують у stackoverflow: /programming/7432596/recommend-a-design-pattern-approach-to-exposed-tolerating-recovering-from-system, але я подумав, що це потрібно запитати і програмістам, тому що Я думаю, що питання і відповіді програмістів охоплюють більш широкі проблеми програмного забезпечення / програмування, тоді як stackoverflow більше стосується технічної реалізації IMHO).


2
Мені ваше запитання здається занадто загальним і відкритим, щоб ефективно відповідати. Спробуйте обмежити це лише деякими конкретнішими випадками, а також конкретними типами / середовищами (наприклад, GUI-додаток / сервер / ...).
Péter Török


@ Péter Török, мікера дає хорошу відповідь, імовірно, прийме їх.
therobyouknow

Відповіді:


16

Невдача - це чудовий підхід до дизайну, і, можливо, це можна вважати зразком: http://en.wikipedia.org/wiki/Fail-fast

Я також знайшов корисні ряд принципів:

  • Розгляньте винятки як частину інтерфейсу для кожної функції / модулів - тобто документуйте їх та, де це доречно / якщо ваша мова підтримує її, тоді використовуйте перевірені винятки.
  • Ніколи не помиляйте провал - якщо він не вдався, не намагайтеся продовжувати деяку спробу "припустити", як діяти далі. Наприклад, спеціальна обробка для нульових випадків для мене часто викликає запах коду: якщо ваш метод потребує ненульового значення, він повинен негайно кидати виняток, якщо він стикається з нулем (або NullPointerException, або в ідеалі більш описовим IllegalArgumentException).
  • Пишіть одиничні тести як для виняткових випадків, так і для звичайних - іноді такі тести можуть бути складно налаштувати, але це варто, коли ви хочете бути впевненими, що ваша система є надійною для збоїв.
  • Журнал у точці, де помилка була впіймана та оброблена (якщо припустити, що помилка була достатньо вираженою для реєстрації). Причина цього полягає в тому, що це означає, що ви зрозуміли причину і підходили до виправлення помилки, тому ви можете зробити повідомлення журналу значимим .....
  • Використовуйте винятки лише для справді несподіваних умов / збоїв. Якщо ваша функція "виходить з ладу" таким чином, який насправді очікується (наприклад, опитування, щоб побачити, чи є більше вхідних даних, а знаходження немає), вона повинна повернути нормальну відповідь ("немає вводу"), а не викидати виняток
  • Збій витончено (заслуга Стівена Лоу!) - очистіть перед припиненням, якщо це взагалі можливо, як правило, розкручуючи зміни, відкочуючи транзакції або звільняючи ресурси в "нарешті" заяві або еквіваленті. В ідеалі очищення має відбуватися на тому самому рівні, на якому ресурси були використані задля ясності та логічної послідовності.
  • Якщо вам доведеться вийти з ладу, відмовтеся голосно - виняток, який жодна частина вашого коду не змогла обробити (тобто просочена до верхнього рівня, не потрапляючи + обробляючись), повинна спричинити негайну, гучну і видиму несправність, яка спрямовує вашу увагу на неї. Зазвичай я зупиняю програму або завдання і пишу повний звіт про винятки в System.out.

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

+1 @mikera для чітких питань про те, що слід врахувати. Ймовірно прийнята відповідь, я залишу відкритим на трохи довше, щоб інші могли зробити свій внесок.
therobyouknow

+1 @Steve A. Lowe - для дизайну, орієнтованого на користувачів. наприклад, як збереження файлів, не залишаючи тимчасових файлів. Дивіться моє запитання про "гігієну даних" як пов'язану тему в моєму списку питань.
therobyouknow

5

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

  1. Чи можна щось корисне зробити з цим винятком (крім журналу)? Якщо відповідь "так", напишіть код обходу, і якщо вирішення може спричинити винятки, перейдіть до пункту 2:
  2. Оберніть виняток навколо виключення під час виконання, киньте його, перейдіть до 3.
  3. У класі вищого рівня, де була ініційована можлива транзакція з базою даних / процесом, виберіть виняток, відкату транзакції та повторне скидання винятку.
  4. Для класу верхнього рівня (який може бути тим, де була ініційована транзакція), введіть виняток, використовуючи структуру реєстрації, наприклад slf4j (поєднану, наприклад, з log4j ) або log4net . Якщо можливо, виключення надішліть електронною поштою до списку розповсюдження, який складається з розробників програми.
  5. Якщо є графічний інтерфейс, відобразіть повідомлення про помилку, яке найбільш зручно вказує, що спричинило проблему; не показуйте виняток / стек-трек, користувачеві це не важливо і не потрібно знати, що це NullPointerException.

Я також повинен додати крок 0 , де я навмисно кидаю те, що я називаю винятком "бізнес" (новий виняток, який я створюю, розширюючи клас "Виняток"), коли якесь складне лікування неможливо виконати через помилки даних, АЛЕ Як відомо, вони трапляються, оскільки вони були визначені як випадки виключення під час аналізу.

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

Крім того, кроки, які я перерахував, можуть бути різними, якщо те, що ви пишете, є API / Framework . Там викидання продуманих винятків є обов'язковим, щоб допомогти розробникам зрозуміти свої помилки.

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


+1 @Jalayn для log4j згадую як підхід, це те, що я використовую, тому це підсилює його, щоб знати, що це ще хтось.
therobyouknow

0

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

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

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