Сучасний спосіб виконання обробки помилок ...

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

Спробуйте винятки щодо кодів помилок

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

Але - мені це здається суперечливим ...

Кодування до інтерфейсів, а не реалізацій

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

Якщо тільки - інтерфейс ...

Специфікації винятку

Деякі мови дозволяють розробникам стверджувати, що певні методи викидають певні винятки (наприклад, Java використовує ключове слово throws ). З точки зору виклику коду це виглядає добре - ми чітко знаємо, які винятки нам можуть знадобитися улов.

Але - це, здається, пропонує ...

Витік абстракції

Чому інтерфейс повинен вказати, які винятки можна викинути? Що робити, якщо для реалізації не потрібно викидати виняток, або потрібно викинути інші винятки? На рівні інтерфейсу не існує способу дізнатися, які винятки, які можуть бути потрібні для реалізації.

Тому...

Щоб зробити висновок

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

112
Негабаритне припущення полягає в тому, що код може обробляти винятком, коли він виходить за межу інтерфейсу. Це малоймовірно, з огляду на те, що він майже не знає про те, що насправді пішло не так. Все, що відомо, полягає в тому, що щось пішло не так, і реалізація інтерфейсу не знала, як з нею справлятися. Шкода, що вона може зробити кращу роботу, є поганою, за винятком повідомлень про неї та припинення програми. Або ігнорувати його, якщо інтерфейс не є критичним для правильної роботи програми. Деталь реалізації, яку ви не можете і не повинні кодувати в контракті на інтерфейс.
додано Автор Vinayaka Thompson, джерело
Я не отримую ваш аргумент про витоку абстракцій. Визначення того, яке виключення певний метод може викинути, є частиною специфікації інтерфейсу . Так само, як тип поверненого значення є частиною специфікації інтерфейсу. Винятки просто не "виходять з лівого боку" функції, але вони все ще є частиною інтерфейсу.
додано Автор Ben, джерело
Я згоден, що може бути складно керувати всіма різними винятками, які метод може кинути, якщо він сам використовує інші методи і не охоплює їх виключення всередині. Сказавши це, це не суперечність.
додано Автор Ben, джерело
@deceze Як інтерфейс, можливо, визначає те, що може здійснити реалізація? Це може викинути всі винятки в системі типу! І те, що багато мов не підтримують специфікації виключень, говорять про те, що вони досить хитрині
додано Автор Bob Jarvis, джерело

11 Відповіді

Перш за все, я б не погодився з цим твердженням:

Виправте винятки щодо кодів помилок

Це не завжди так: наприклад, подивіться наobjective-c(за основу Фонду). Там NSError - це найкращий спосіб обробляти помилки, незважаючи на те, що розробник Java називає справжніми виключеннями: @ try, @catch, @ throw, class NSException і т. Д.

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

Усуньте помилку/виняток на найнижчому рівні, період

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

Наскільки виключення, викинутий методом, повинні бути частиною його декларації, я вважаю, що вони повинні: вони є частиною контракту , визначеного цим інтерфейсом: цей метод робить A або збігається з B або C.

Наприклад, якщо клас є xml Parser, частина його дизайну повинна бути ознакою того, що наданий файл xml просто неправильний. У Java, як правило, це робиться, оголосивши винятки, які ви очікуєте, і додати їх до частини throws частини декларації методу. З іншого боку, якщо один з алгоритмів синтаксичного аналізу не виконувався, немає причин переносити таке виняток вище, ніж невикористаний.

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

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

Останнє: деякі мови, наприклад, Ейфель, мають інші механізми обробки помилок і просто не включають можливості кидати. Там "виняток" сорту автоматично піднімається, коли неможливо виконати пост умову для процедури.

29
додано
@JoshuaDrake: Але ви знаєте, де він почне виконуватись - відповідний catch найвищого рівня. І це може йти тільки одним способом - на відміну від goto , який може стрибати як завгодно.
додано Автор Andy Irving, джерело
@JoshuaDrake: Він безумовно помиляється. Винятки та goto дуже різні. Наприклад, винятки завжди йдуть в тому ж напрямку - вниз до стеку викликів. А по-друге, захист від винятків з несподіванки - це точно така ж практика, як DRY - наприклад, в C ++, якщо ви використовуєте RAII для забезпечення очищення, то це забезпечує очищення в всім випадках, а не тільки виключення, а також весь нормальний контроль потоку. Це нескінченно надійніше. try/finally виконує щось дещо подібне. Коли ви правильно гарантуєте очищення, вам не потрібно розглядати винятки як особливий випадок.
додано Автор Andy Irving, джерело
+1 для заперечення "Виключення за кодами помилок". Я був вчив, що винятки добре і добре, якщо вони фактично є винятками, а не правилом. Виклик методу, який видає виняток для визначення того, чи є умова істинною, є надзвичайно поганою практикою.
додано Автор Justin Poliey, джерело
-1, тому що я абсолютно не погоджуюсь з "Справи з помилкою/виключенням на найнижчому рівні" - це неправильно, період. Усунути помилки/винятки на рівні відповідного . Нерідко це набагато більш високий рівень, і в цьому випадку коди помилок є величезним болем. Причиною винятку щодо кодів помилок є те, що вони дозволяють вільно вибирати, на якому рівні займатися ними, не впливаючи на рівні між ними.
додано Автор kyck-ling, джерело
@ Джорджіо: дивіться artima.com/intv/handcuffs.html - особливо сторінку 2 та 3.
додано Автор kyck-ling, джерело
@ Джорджо: як правило, обробка виключень на вищому рівні є дуже загальною і, насправді, не хвилює того, що це за винятком. Перевірене винятком Java є теоретичним рішенням ніші, але на практиці вони просто призводять до забруднення API. Існує причина, що їх ніхто не прийняв, навіть інші мови JVM.
додано Автор kyck-ling, джерело
@ Майкл Боргвардт: Дякую за посилання. Я розумію вашу ідею обробки виключень на відповідному рівні, але знову ж таки, як дізнатися, які винятки ловити, якщо я не знаю, який виняток можна кинути? Або ви маєте на увазі, що потрібно обробляти документовані винятки з викликом у виклику абонента, і мати загальний обробник зловмисника на більш високому рівні в стовпці дзвінків для будь-яких додаткових винятків, які можуть вийти з виклику?
додано Автор Giorgio, джерело
@ Майкл Боргвардт: Які проблеми викликані перевіреними винятками?
додано Автор Giorgio, джерело
@ Майкл Боргвардт: це можливо, якщо ви можете оголосити про винятки, викинуті за допомогою кожного методу. Це можливо тільки в Java: C + +, C#, Scala не надають цей об'єкт, тому важко знати, які винятки трапляються, якщо ви навіть не знаєте, які винятки викинуті, і вам слід подивитися на реалізацію, щоб знати це .
додано Автор Giorgio, джерело
@DeadMG: "Але ви знаєте, де він почне виконуватись - відповідний вилов на найвищому рівні". Що робити, якщо відсутній відповідний вилов, тому що виключення викидається з класу, який ви не знаєте (оскільки ви не повинні знати всі деталі реалізації коду, який ви телефонуєте)?
додано Автор Giorgio, джерело
@JoshuaDrake Вибачте, але Джоел дуже далеко. Винятки не збігаються з переходом, ви завжди виконуєте принаймні один рівень до стек викликів. І що ви робите, якщо наведений вище рівень не може негайно впоратися з кодом помилки? Повернутися ще один код помилки? Частина проблеми з помилкою полягає в тому, що вони можуть бути проігноровані, що призводить до гірших проблем, ніж викидання винятку.
додано Автор Andy, джерело
@ Джорджо: Взагалі кажучи, якщо ви не знаєте, що виняток може бути кинутий, ви не повинні ловити його. Винятки призначаються для використання, коли щось справді виняткове та може спричинити проблеми в потоці. Деякі винятки можуть бути відновлені, але їх основне призначення відрізняється від коду помилки. Користувач ніколи не повинен їх бачити, проте розробник повинен їх бачити досить часто, оскільки вони вказують на запобігання помилка. Захоплення, безумовно, не призначене як те, на що завжди можна довіряти працювати.
додано Автор Magus, джерело
@DeadMG З статті msdn, пов'язаної в моєму коментарі Не механізований механізм виключення ОС (OS) не завжди може призвести до запуску необробленої обробки виключень CLR. , так що я б сказав, що ви тільки думаєте, що знаєте. Ви стверджували, що він спустився у стек, Енді каже, що він піднімається вгору, так що це таке?
додано Автор Joshua Drake, джерело
@DeadMG У C# принаймні, що тримається тільки при ловлі їх. Виключення виключень змушують ваш код вийти з цього пункту та йти де-небудь ще. Якщо ви викинете невикористане виключення, ви негайно піднімете стек і не знаєте, де код знову розпочнеться. Обробка необгрунтованого винятку в CLR . Але також слід зауважити, що я опублікував статтю лише на користь того, щоб кинути виклик у припущенні, що виключення виключення з кодів виправлення помилок були єдиним способом йти, а не погодитися з Джоелем.
додано Автор Joshua Drake, джерело
Перегляньте Джоел за винятками ще раз, щоб заперечувати припущення.
додано Автор Joshua Drake, джерело

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

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

func x = do
    a <- operationThatMightFail 10
    b <- operationThatMightFail 20
    c <- operationThatMightFail 30
    return (a + b + c)

operationThatMightfail - це функція, яка повертає значення, загорнуте в Можливо. Він працює як нульовий покажчик, але позначення do гарантує, що ціла річ оцінюється як нуль, якщо не вдається виконати будь-який з a, b або c. (і компілятор захищає вас від створення випадкової NullPointerException)

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

Загальний LISP робить це, і робить це можливим, маючи синтаксичну підтримку (неявні аргументи) і наявність вбудованих функцій, які слідують за цим протоколом.

27
додано
До речі, виключення є однією з найбільш функціональних частин сучасних імперативних мов. Винятки утворюють монаду. Винятки використовуються для відповідності паттеру. Винятки допомагають імітувати аплікаційний стиль, не навчившись навчитися, що таке Можливо .
додано Автор Rorick, джерело
Нещодавно я читав книгу про SML. Тут згадані типи опцій, винятки (і продовження). Порада полягала в тому, щоб використовувати типи опцій, коли часто трапляється невизначена справа, і використовувати винятки, коли невизначений випадок відбувається дуже рідко.
додано Автор Giorgio, джерело
Це дійсно акуратно. Дякую, що відповіли на частину про альтернативи :)
додано Автор Bob Jarvis, джерело

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

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

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

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

8
додано
@Giorgio: Так, повідомлення про помилки, пов'язані з виконанням, є складними з асоціацією API. Тим не менше, ви можете зробити це за винятком, оскільки (на відміну від кодів помилок) вони можуть мати кілька полів. Таким чином, ви можете скористатися типом винятку для надання загальної інформації про помилку (ResourceMissingException) і включити спеціальний код, пов'язаний з виконанням, як поле. Кращий обох світів :-).
додано Автор Julien Hoarau, джерело
І, до речі, це саме те, що робить java.lang.SQLException. Вона має getSQLState (загальний) та getErrorCode (специфічний для постачальників). Тепер, якщо б у нього були тільки підкласи ...
додано Автор Julien Hoarau, джерело
Якщо код помилки є специфічним для реалізації, тоді як API, як передбачається, є реалізацією-агностик, то при заданні та поверненні коду помилки витікає небажана деталізація виконання. Типовий приклад: API для журналів з файловою і базовою реалізацією на базі DB, де перша може мати помилку "повне завантаження диска", а друга - помилка "Від'єднання БД від хоста".
додано Автор kyck-ling, джерело
@sleske: Також об'єкт, який повернено як результат, може містити декілька полів, які ви можете запитати за коди помилок.
додано Автор Giorgio, джерело
Я розумію, що ви маєте на увазі. Якщо ви хочете повідомити про конкретні помилки для реалізації, то API не може бути агностиком для реалізації (не з кодами помилок, ані з винятками). Я думаю, єдиним рішенням буде визначити реалізацію-агностичний код помилки, такого як "ресурс недоступний", або вирішити, що API не є агностичним.
додано Автор Giorgio, джерело
Я не розумію, чому код помилки може спричинити витік абстракції. Якщо код помилки повертається замість нормальної поверненої величини, і така поведінка описується в специфікації функції/методу, то в IMO немає витоків. Чи я щось оглядаю?
додано Автор Giorgio, джерело

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

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

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

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

5
додано

Витоку абстракції

     

Чому інтерфейс повинен вказати, які винятки можуть бути   бути кинутий? Що робити, якщо для реалізації не потрібно кидати   виняток, або потрібно викинути інші винятки? Там ніякий шлях, у   рівень інтерфейсу, щоб дізнатись, які винятки можуть знадобитися здійсненню   кинути.

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

Коди помилок не підходять. Вони страшенні. Ви повинні вручну пам'ятати, щоб перевіряти та розповсюджувати їх, кожного разу, для кожного дзвінка. Це перш за все порушує СУХИ, і масово підриває код обробки помилок. Це повторення є набагато більшою проблемою, ніж будь-яка особа, яка зіткнулася з винятками. Ви ніколи не можете мовчки ігнорувати виняток, але люди можуть і мовчки ігнорують коди повернення - напевно, погано.

4
додано
@missingno: Це тому, що, як звичайно, Java страшна реалізація їх, а не тому, що перевірені винятки є за своєю суттю поганими.
додано Автор Andy Irving, джерело
@missingno: Анонімні функції AFAIK в Java - це просто синтаксичний цукор для анонімних внутрішніх класів з точно одним методом, тому я не впевнений, що розумію, чому перевірені винятки стануть проблемою (але я визнаю, що не знаю багато про цю тему). Так, важко передбачити, які винятки метод буде кидати, тому IMO може бути корисно перевірити винятки, так що вам не доведеться вгадати. Звичайно, ви можете писати поганий код для обробки їх, але це також можна зробити з невикористаними винятками. Однак я знаю, що дебати є досить складними і, чесно кажучи, я бачу плюси та мінуси на обох сторонах.
додано Автор Giorgio, джерело
@missingno: Які проблеми можуть бути викликані перевіреними винятками?
додано Автор Giorgio, джерело
@ Джорджо: Важко передбачити будь-яке виключення, яке метод може кинути, оскільки це має враховувати інші підкласи та код, який ще не написано. На практиці люди в кінцевому підсумку з потворними шляхами, які викидають інформацію, як повторне використання класу системних винятків для всього, або часто доводиться ловити і повторно викидати внутрішні винятки. Я також чув, що перевірені винятки були великою перешкодою, коли вони намагалися додати анонімні функції до мови.
додано Автор hugomg, джерело
Коди помилок можуть бути простішими у використанні, якщо у вас є хороші форми синтаксичного цукру або допоміжних методів, і в деяких мовах ви можете створити гарантію компілятора та системи типу, що ви ніколи не забудете впоратися з кодом помилки. Що стосується частини інтерфейсу інтерфейсу, я думаю, він думав про горезвісну скупчення перевірених винятків Java. Хоча на перший погляд здавалося б ідеально підходящою ідеєю, на практиці вони викликають багато болісних проблем.
додано Автор hugomg, джерело
@Giorgio: перевірені винятки не взаємодіють з загальною системою, що ускладнює визначення багатьох видів корисних функцій вищого порядку. james-iry.blogspot.com. br/2012/02/& hellip;
додано Автор hugomg, джерело

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

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

Вищезгадане спостереження можна поширювати на будь-який злегка пов'язаний інтерфейс (як зазначалося); Я думаю, що це насправді є нормою, що після повного завантаження 3-6 кадрів стеків, незгоджений виняток, ймовірно, опиниться в розділі коду, який:

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

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

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

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

2
додано

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

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

Впровадження кодів помилок є ортодоксальним способом обробки винятку. Це схоже на використання рядка чи конструктора рядків.

2
додано
Іншими словами: реалізації викинути підкласи винятків, визначених в api.
додано Автор keif, джерело

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

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

Підсумовуючи:

  • Я вважаю, що виключення дозволяють використовувати більш чистий код та більш агресивний підхід до тестування та налагодження, оскільки невидані винятки набагато більш помітні та їх важко ігнорувати, ніж коди помилок. (Невдало буде).
  • З іншого боку, невиявлені помилки винятків, які не були виявлені під час тестування, можуть з'являтися у виробничому середовищі у формі аварії. За певних обставин така поведінка є неприйнятною, і в цьому випадку я думаю, що використання кодів помилок є більш надійним підходом.
1
додано
По-перше: Ви можете перевірити всі винятки - просто виконайте "Обробка виключень із Pokemon" (треба зловити їх усім, тобто catch Exception або навіть Throwable або еквівалентне).
додано Автор Julien Hoarau, джерело
На практиці, якщо API правильно розроблений, він буде вказати всі винятки, які клієнт може обробляти значущим чином - їх потрібно спеціально спіймати. Це еквіваленти кодів помилок). Будь-яке інше виключення означає "внутрішня помилка", і програма повинна бути вимкнена або принаймні вимкнути відповідну підсистему. Ви можете зловити їх, якщо хочете (див. Вище), але ви, як правило, просто повинні дозволити їм пузирувати. Це "перемішування" - це головна перевага використання винятків. Ви можете все-таки зловити їх далі, чи ні, залежно від потреб.
додано Автор Julien Hoarau, джерело
Я не погоджуюсь. Так, невичерпні винятки можуть призвести до аварійного завершення роботи програми, але це також може бути помилковим кодом помилок. Якщо ви правильно використовуєте виключення, єдиними незграбними будуть фатальні (наприклад, OutOfMemory), і для них збій відразу є найкращим, що ви можете зробити.
додано Автор Julien Hoarau, джерело
Код помилки є частиною договору між абонентом m1 та callee m2: можливі коди помилок визначаються тільки в інтерфейсі m2. За винятками (якщо ви не використовуєте Java і не оголошувати всі виключені винятки в підписях методів), ви маєте неявний контракт між caller m1 і всіма способами, які можна викликати м2, рекурсивно. Звичайно, це помилка не перевіряти повернений код помилки, але це завжди можливо зробити. З іншого боку, не завжди можливо перевірити всі винятки, викинуті методом, якщо ви не знаєте, як воно реалізується.
додано Автор Giorgio, джерело

Виправте винятки щодо кодів помилок

  • Обидва повинні співіснувати.

  • Повертайте код помилки, коли ви очікуєте певну поведінку.

  • Повернення винятку, коли ви не передбачали якусь поведінку.

  • Коди помилок, як правило, пов'язані з одним повідомленням, коли тип виключення залишається, але повідомлення може змінюватися

  • Виняток має слід стека, коли код помилки не є. Я не використовую коди помилок для налагодження зламаної системи.

Кодування інтерфейсів, а не реалізацій

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

Коли ми змиримося з винятком, то ми приймаємо припущення про   реалізація?

Це цілком залежить від вас. Ви можете спробувати і спіймати винятковий тип винятку, а потім спіймати більш загальний Exception . Чому не дозволяйте виключенням розповсюджувати стек, а потім керувати ним? Крім того, ви можете подивитися на аспект програмування, де обробка винятків стає "plugging" аспект.

Що робити, якщо для реалізації не потрібно викидати виняток, або   потрібно викинути інші винятки?

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

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

1
додано

Витоку абстракції

     

Чому інтерфейс повинен вказати, які винятки можуть бути   бути кинутий? Що робити, якщо для реалізації не потрібно кидати   виняток, або потрібно викинути інші винятки? Там ніякий шлях, у   рівень інтерфейсу, щоб дізнатись, які винятки можуть знадобитися здійсненню   кинути.

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

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

1
додано

Правий упереджений.

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

Недостатньо? Код із правильною обробкою помилок виглядає огидно (вірно з усіх механізмів).

1
додано
це, здається, не пропонує нічого суттєвого щодо пунктів, зроблених та пояснених у попередніх 10 відповідях. Чому натискати на два роки питання з такими подібними речовинами
додано Автор gnat, джерело
За винятком ніхто тут не згадав правильний упереджений теж. Hugomg наблизився до розмови про Haskell, однак, можливо, це обробник помилок, оскільки він не залишає жодних пояснень причин виникнення помилки, а також будь-який прямий спосіб їх відновлення, а call-backs - одне з найбільших гріхів у дизайні потоку керування. І це питання підійшло на Google.
додано Автор Keynan, джерело