Чому варіант / можливо вважається хорошою ідеєю, а перевірені винятки - ні?


23

Деякі мови програмування, наприклад, Scala, мають поняття Optionтипів (які також називаються Maybe), які можуть містити значення чи ні.

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

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

Чи є якісь додаткові проблеми з перевіреними винятками, яких Optionнемає у типів? Або ці ідеї не такі схожі, як я вважаю, і є вагомі причини для примусового явного поводження з параметрами, а не з винятками?


Також дивіться Either e aтип даних.

4
Про перевірені винятки: як користувач безлічі відкритих джерел та внутрішніх ліній Java з розвиваючою базою коду та відсутніми / застарілими документами, я здригаюся від думки, що Java не буде застосовувати певні винятки, які явно декларуються. Це був би кошмар, коли несподівано з’являються невдалі помилки виконання, які виникають у поганих місцях. І Java7, нарешті, робить виняток обробкою майже розумним, позбавляючи від більшої частини старого безладу.
Гайда

Відповіді:


24

Оскільки Options є композиційними. Є багато корисних методів на Optionякі дозволяють вам писати код коротким, в той же час дозволяючи точний контроль потоку: map, flatMap, toList, flattenі багато іншого. Це пов’язано з тим, що Optionце особливий вид монади, деякі об’єкти, які ми дуже добре знаємо, як складати. Якщо б у вас не було цих методів і вам доводилося завжди узгоджувати відповідність Optionабо дзвонити isDefinedчасто, вони не були б такими ж корисними.

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


1
Перевірені винятки складаються більш-менш однаковими способами ... Різниця між тим try {/* bunch of complex code involving calls to 50 different methods that may throw SomeCheckedException */} catch(SomeCheckedException e) {/* operation failed, do something */}і fromMaybe someDefaultValue (something >>= otherThing >>= ...50 other functions that may return Nothing...)що саме? Окрім того, що перший розповідає про те, що пішло не так.
користувач253751

14

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

Винятки

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

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

Можливо, предмети

Можливо, об’єкти слід вибирати, коли ви зможете локально боротися з "провалом". У цьому сенсі вони є заміною зворотного коду + пропуск за посиланням api або нульовим типом.

Перевага об'єкта "Можливо" полягає в тому, що ви явно заявляєте, що щось може бути не так. У haskell об'єкт, який, можливо, не повинен мати значення, інакше програма не буде компілювати.

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

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


1
@MattFenwick дякую за відгук. Чому ви вважаєте, що приклад csv не має сенсу? ОП не дуже вимагає методів уникнення котлових плит, і я маю відчуття, що словник, такий як прикладний функтор і монади, може бути надто технічним для цього питання.
Саймон Бергот

1
Я хотів би зазначити, що з Java (не впевнений в інших мовах з перевіреними винятками) IDE дбають про додавання та обрізання кидків та оновлення частини котлів на панелі коментарів Javavac. Так що принаймні ця частина не турбує і, звичайно, не болить. Будь то біль чи користь чи щось середнє, коли робите дизайн API, це інша справа ...
hyde

5
@hyde: Тільки тому, що IDE може автоматизувати безглузді генерування котлів, це не означає, що безглуздий котлован - це не біль.
Майкл Шоу

2
@hyde: Але біль не знімається. Безглуздий котельний плит все ще є, захаращуючи код без причини. Якщо для котла є причина, що це?
Майкл Шоу

2
@MichaelShaw Якщо виняток безглуздий, видаліть його: ігноруйте ситуацію або натомість поверніть значення помилки. Якщо це помилка чи непоправна ситуація: використовуйте неперевірений виняток. Залишилося так само важливо, як, наприклад, типи параметрів, а не безглуздо котлован. Якщо він поганий API в існуючій lib, розгляньте метод / клас обгортки, використовуючи інший lib, або просто страждаєте від поганого API.
Гайда

1

оскільки Maybeви можете затримати обробку помилки, поки вам фактично не знадобиться значення (що може бути за кілька дзвінків методу)

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

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


2
Але я можу відкласти обробку перевіреного винятку, оголосивши, що мій метод кидає цей виняток.
Mad Scientist

1
@MadScientist, який піднімається лише на стек викликів, хоча, можливо, може йти в усіх напрямках
храповик виродка

5
Я думаю, ви не повинні плутати Maybeтипи з помилками обробки. Виняток використовується для повідомлення про помилку, тип опції використовується для представлення результату часткової функції. Повернення часткової функції Nothingне є помилкою.
Джорджіо

@MadScientist: Якщо виклик методу повертає індикацію "Недійсне значення", оператор одразу після його виконання може бути виконаний. На противагу цьому, якщо метод видає виняток, який не відразу потрапляє, оператор після виклику буде пропущений. Дозвіл до перевірених винятків, що стосуються стека викликів, загалом є злим (і не повинен був бути найпростішим способом боротьби з ними), оскільки абонент не може сказати, чи має стан значення, яке очікується методом, який він викликав, або чи представляє він несподіване умова, яке викликаний метод пускає бульбашку.
supercat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.