Почему Option / Может считаться хорошей идеей, а проверенные исключения - нет?

23

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

Из того, что я читал о них, они считаются широко лучшим способом решения этой проблемы null, потому что они явно вынуждают программиста рассматривать случаи, когда не может быть значения, а не просто взорваться во время выполнения.

Проверенные исключения в Java, с другой стороны, кажутся плохой идеей, и Java кажется единственным широко используемым языком, который их реализует. Но идея, стоящая за ними, кажется, чем-то похожа на Optionтип, чтобы явно заставить программиста иметь дело с тем фактом, что может быть выдано исключение.

Есть ли дополнительные проблемы с проверенными исключениями, Optionкоторых нет у типов? Или эти идеи не так похожи, как я думаю, и есть веские причины для принудительной явной обработки опций, а не исключений?

Сумасшедший ученый
источник
Также см. Either e aТип данных.
4
О проверенных исключениях: как пользователь множества библиотек с открытым исходным кодом и внутренних библиотек Java с развивающейся кодовой базой и отсутствующими / устаревшими документами, я содрогнулся от мысли, что Java не будет предписывать определенные исключения для явного объявления. Это был бы кошмар необработанных ошибок времени выполнения, неожиданно появляющихся в плохих местах. И Java7, наконец, делает обработку исключений почти вменяемой, избавляясь от большей части старого беспорядка try-catch.
Гайд

Ответы:

24

Потому что Optionскомпонованы. Есть много полезных методов на Optionкоторые позволяют вам писать код кратким, в то же время позволяя точный контроль потока: map, flatMap, toList, flattenи многое другое. Это связано с тем, что Optionэто особый вид монады, некоторые объекты, которые мы очень хорошо знаем, как составлять. Если бы у вас не было этих методов, и вам приходилось постоянно выполнять сопоставление с образцом Optionили isDefinedчасто вызывать их, они были бы не такими полезными.

Вместо этого, хотя проверенные исключения действительно добавляют некоторую безопасность, вы не можете ничего с ними сделать, кроме как перехватывать их или позволять им пузыриться в стеке (с добавленным шаблоном в объявлении типа).

Andrea
источник
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...)что именно? Кроме того, что первый дает вам больше деталей о том, что пошло не так.
user253751
14

Несмотря на то, что исключения и объекты Maybe не связаны с однотипными проблемами.

Исключения

Исключения действительно блестят, когда вам приходится иметь дело с исключительной ситуацией (которая в некоторых случаях является ошибкой). Например, вы анализируете CSV и хотите защитить себя от строк с неправильным форматированием. Местом, где вы обнаружите, что что-то не так, могут быть вызовы некоторых функций вдали от итерации строки. Если вы выбросите исключение на самом глубоком уровне (где вы узнаете о проблеме форматирования), вы можете перехватить его в цикле, записать ошибку и перейти к следующей строке. Вам не нужно ничего менять в остальной части кода.

Проверенное исключение добавляет много боли, потому что все промежуточные функции должны объявлять тип throwable. Эта функция побеждает первоначальные цели, поэтому они не популярны в наши дни.

Возможно объекты

Возможно, объекты следует выбирать, когда вы можете локально справиться с «провалом». В этом смысле они являются заменой кода возврата + передача по ссылочному API или обнуляемому типу.

Преимущество объекта Maybe заключается в том, что вы явно заявляете, что что-то может быть не так. В haskell не имеющий значения объект должен иметь значение, иначе программа не будет компилироваться.

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

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

Саймон Бергот
источник
1
@MattFenwick спасибо за отзыв. Почему вы думаете, что пример csv не имеет смысла? ОП на самом деле не запрашивает шаблонные методы избежания, и у меня есть ощущение, что словарный запас, такой как аппликативный функтор и монады, может быть слишком техническим для этого вопроса.
Саймон Бергот
1
Я хотел бы отметить, что с Java (не уверен в других языках с проверенными исключениями) IDE позаботятся о добавлении и сокращении бросков и обновлении стандартной части комментариев javadoc. Так что, по крайней мере, эта часть не беспокоит и, конечно, не причиняет боль. Будь то боль, благо или что-то среднее между разработкой API, это другой вопрос ...
Хайд,
5
@hyde: То, что IDE может автоматизировать бессмысленную генерацию шаблонов, не означает, что бессмысленный шаблон не является проблемой.
Майкл Шоу,
2
@hyde: но боль не снимается. Бессмысленный шаблон все еще там, беспорядочно кодируя без причины. Если есть причина для шаблона, то что это?
Майкл Шоу,
2
@MichaelShaw Если исключение бессмысленно, удалите его: игнорируйте ситуацию или верните значение ошибки. Если это ошибка или неисправимая ситуация: используйте непроверенное исключение. То, что остается, так же важно, как, например, типы параметров, а не бессмысленный шаблон. Если это плохой API в существующей библиотеке, рассмотрите метод / класс-оболочку, использующий другую библиотеку или просто страдающий от плохого API.
Гайд
1

потому что Maybeвы можете отложить обработку ошибки до тех пор, пока вам действительно не понадобится значение (которое может быть вызвано несколькими вызовами методов)

в то время как проверенное исключение должно быть обработано в месте вызова

Единственным преимуществом исключений является то, что может быть передано больше информации о том, почему это не удалось (если кто-то не разработал MaybeErrorс бросаемым полем, когда это ошибка)

чокнутый урод
источник
2
Но я могу отложить обработку проверенного исключения, заявив, что мой метод выдает это исключение.
Безумный ученый,
1
@MadScientist, который только поднимает стек вызовов, в то время как Может идти во всех направлениях
трещотка урод
5
Я думаю, что вы не должны путать Maybeтипы с обработкой ошибок. Исключение используется для сообщения об ошибке, тип параметра используется для представления результата частичной функции. Частичное возвращение функции Nothingне является ошибкой.
Джорджио
@MadScientist: если вызов метода возвращает указание «Недопустимое значение», оператор сразу после его выполнения может выполняться. Напротив, если метод генерирует исключение, которое не сразу перехватывается, оператор, следующий за вызовом, будет пропущен. Разрешение проверенных исключений просачиваться вверх по стеку вызовов, как правило, является злом (и не должно было быть «самым простым» способом борьбы с ними), так как вызывающая сторона не может сказать, имеет ли условие значение, ожидаемое вызываемым им методом, или представляет ли это непредвиденное состояние, которое вызывает вызываемый метод.
суперкат