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


118

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

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

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

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

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

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

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

Технічні умови виключення

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

Але - це, здається, говорить про ...

Витікаюча абстракція

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

Тому...

Прийти до висновку

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


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

@deceze Як інтерфейс, можливо, визначає, що може кинути реалізація? Він може кинути всі винятки в системі типів! І що багато мов не підтримують специфікацій винятків, вони говорять про те, що вони досить
хитрі

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

1
Припустиме припущення про те, що код може обробляти виняток, коли він уникає межі інтерфейсу. Це дуже малоймовірно, враховуючи, що він не знає майже достатньо того, що насправді пішло не так. Все, що він знає, - щось пішло не так, і реалізація інтерфейсу не знала, як з цим боротися. Шанси, що він може зробити кращу роботу, погані, окрім як повідомляти про це та припиняти програму. Або ігнорувати його, якщо інтерфейс не є критичним для правильної роботи програми. Деталі реалізації, які ви не можете і не повинні кодувати в інтерфейсному договорі.
Ганс Пасант

Відповіді:


31

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

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

Це не завжди так: наприклад, погляньте на Objective-C (з рамками Foundation). Там NSError є кращим способом обробляти помилки, незважаючи на існування того, що розробник Java називав би справжніми винятками: @try, @catch, @throw, клас NSException тощо.

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

Попрацюйте з помилкою / винятком на найнижчому можливому рівні, періоді

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

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

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

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

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

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


12
+1 за заперечення "Фаворити виключень над кодами помилок". Мене вчили, що винятки - це добре і добре, якщо вони насправді є винятками, а не правилом. Викликати метод, який містить виняток, щоб визначити, чи є умова справжньою, вкрай погана практика.
Ніл

4
@JoshuaDrake: Він напевно помиляється. Винятки і gotoдуже різні. Наприклад, винятки завжди йдуть в тому ж напрямку - вниз по стеку викликів. По-друге, захист себе від несподіваних винятків - це саме та ж практика, що і для DRY. Наприклад, у C ++, якщо ви використовуєте RAII для забезпечення очищення, то це забезпечує очищення у всіх випадках, не лише виняток, але і весь нормальний потік управління. Це нескінченно надійніше. try/finallyвиконує щось дещо подібне. Якщо ви належним чином гарантуєте прибирання, не потрібно розглядати винятки як особливий випадок.
DeadMG

4
@JoshuaDrake Вибачте, але Джоел вже далеко. Винятки не такі, як goto, ви завжди хочете хоча б на один рівень вище стека викликів. А що ви робите, якщо рівень, що знаходиться вище, не може відразу впоратися з кодом помилки? Повернути ще один код помилки? Частина проблеми з помилками полягає в тому, що вони МОЖУТЬ ігноруватись, що призводить до гірших проблем, ніж викидання виключення.
Енді

25
-1 тому, що я повністю не погоджуюся з "Робота з помилкою / виключенням на найнижчому можливому рівні" - це неправильно, період. Справляйтеся з помилками / винятками на відповідному рівні. Досить часто це набагато вищий рівень, і в цьому випадку коди помилок - це величезний біль. Причина віддати перевагу виняткам над кодами помилок полягає в тому, що вони дозволяють вільно вибирати, на якому рівні працювати з ними, не впливаючи на рівні між ними.
Майкл Боргвардт

2
@Giorgio: див. Artima.com/intv/handcuffs.html - особливо сторінки 2 та 3.
Майкл Боргвардт

27

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

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

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

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

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

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


1
Це справді акуратно. Дякую за відповідь на частину про альтернативи :)
RichK

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

Нещодавно я читав книгу про СМЛ. У ньому згадуються типи варіантів, винятки (та продовження). Порада полягала в тому, щоб використовувати варіанти варіантів, коли не визначений випадок трапляється досить часто, і використовувати винятки, коли невизначений випадок трапляється дуже рідко.
Джорджіо

8

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

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

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

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


1
Я не розумію, чому код помилки може викликати протікаючу абстракцію. Якщо код помилки повертається замість нормального значення повернення, і така поведінка описана в специфікації функції / методу, то в IMO немає витоку. Або я щось переглядаю?
Джорджо

Якщо код помилки є специфічним для реалізації, тоді як API повинен бути впроваджувальним, тоді вказівка ​​та повернення коду помилки просочує небажані деталі реалізації. Типовий приклад: API журналу з файловою та базованою на базі DB реалізацією, де перший може мати помилку "повний диск", а останній - помилка "з'єднання БД, відхилене хостом".
Майкл Боргвардт

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

1
@Giorgio: Так, повідомлення про помилки, пов’язані з реалізацією, є складним у API-агностиці API. Тим не менш, ви можете робити це за винятками, оскільки (на відміну від кодів помилок) вони можуть мати кілька полів. Таким чином, ви можете використовувати тип винятку для надання загальної інформації про помилки (ResourceMissingException) та включати специфічний для реалізації код помилкиn / повідомлення як поле. Кращий з обох світів :-).
sleske

І BTW, це саме те, що робить java.lang.SQLException. Він має getSQLState(загальний) і getErrorCode(специфічний для продавця). Тепер якби у нього були належні підкласи ...
sleske

5

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

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

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

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


4

Витікаюча абстракція

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

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

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


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

@missingno: Це тому, що, як зазвичай, у Java є страшна реалізація їх, а не тому, що перевірені винятки по суті погані.
DeadMG

1
@missingno: Які проблеми можуть бути викликані перевіреними винятками?
Джорджіо

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

@missingno: Анонімні функції AFAIK на Java - це лише синтаксичний цукор для анонімних внутрішніх класів саме одним методом, тому я не впевнений, що розумію, чому перевірені винятки будуть проблемою (але я визнаю, що не знаю багато про цю тему). Так, важко передбачити, які винятки викине метод, тому ІМО може бути корисним для перевірки винятків, щоб вам не довелося здогадуватися. Звичайно, ви можете написати поганий код для обробки, але це також можна зробити з неперевіреними винятками. Однак я знаю, що дебати є досить складними, і я чесно бачу плюси і мінуси в обох сторін.
Джорджо

2

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

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

Реалізація кодів помилок є ортодоксальним способом поводження з винятком. Це як використання строки проти конструктора струн.


4
Іншими словами: реалізація кидає підкласи винятків, визначених у api.
andrew cooke

2

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

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

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

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

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

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

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


1

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

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

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

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

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

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

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

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

Коли ми ловимо виняток, то, безумовно, ми робимо припущення щодо впровадження?

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

Що робити, якщо впровадженню не потрібно викидати винятки або потрібно викидати інші винятки?

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

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


1

Витікаюча абстракція

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

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

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


1

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

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

Підведення підсумків:

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

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

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

По-перше: ви можете перевірити всі винятки - просто зробіть "Покемон обробку винятків" (треба спіймати їх усіх - тобто catch Exceptionчи навіть Throwable, або еквівалент).
sleske

1
На практиці, якщо API розроблений належним чином, він визначатиме всі винятки, з якими клієнт може впорядковуватися, - це потрібно виловлювати конкретно. Це еквіваленти кодів помилок). Будь-який інший виняток означає "внутрішню помилку", і програмі потрібно буде вимкнути або принаймні вимкнути відповідну підсистему. Ви можете зловити їх, якщо хочете (див. Вище), але вам зазвичай просто потрібно пускати їх. Саме «пухиріння» - головна перевага використання винятків. Ви все ще можете їх наздогнати далі, чи ні, залежно від потреб.
sleske

-1

Право упереджене будь-яке.

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

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


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

За винятком того, що ніхто тут не згадав про упереджене право. hugomg детально розмовляв про haskell, однак, можливо, це обробник помилок у лайні, оскільки він не залишає пояснення того, чому сталася помилка, ані будь-якого прямого методу відновлення, і зворотний виклик є одним з найбільших гріхів у дизайні управління потоком. І це питання виникло на Google.
Кенан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.