Лучше возвращать None или выдавать исключение при выборе URL?

У меня есть вспомогательный метод Scala, который в настоящее время пытается получить URL-адрес и возвращает параметр [String] с HTML-страницей этой веб-страницы.

Если есть какие-то исключения (неверный URL-адрес, тайм-ауты чтения и т.д.), или если возникают какие-либо проблемы, он возвращает None. Вопрос в том, было бы лучше просто выбросить исключение, чтобы вызывающий код мог регистрировать исключение или предпочтительнее возвращать None в этом случае?

Ответ 1

Создание исключений является дорогостоящим, поскольку трассировка стека должна быть заполнена. Бросание и отлавливание исключений также дороже обычного возвращения. Учитывая это, вы можете задать себе следующие вопросы:

  • Вы хотите принудительно обработать ошибку вызывающим? Если это так, не бросайте исключение, так как Scala не имеет механизма проверки-исключения, который заставляет вызывающего чтобы поймать их.

  • В случае ошибки вы хотите включить сведения о том, почему это не удалось? Если нет, вы можете просто вернуть Option[A], где A - ваш тип возврата, и тогда у вас будет либо Some(validContent), либо None, без каких-либо дополнительных объяснений. Если да, вы можете вернуть что-то вроде Either[E, A] или Scalaz Validation[E, A]. Все эти параметры заставляют вызывающего пользователя каким-то образом развернуть результат, будучи свободным для обработки ошибки E по своему усмотрению. Теперь что должно E быть?

  • Вы хотите предоставить трассировку стека в случае сбоя? Если это так, вы можете вернуть Either[Exception, A] или Validation[Exception, A]. Если вы действительно идете с исключением, вы захотите использовать Try[A], двумя возможными случаями которого являются Failure(exc: Throwable) и Success(value: A). Обратите внимание, что вы, конечно, возьмете затраты на создание броска. Если нет, вы можете просто вернуться Either[String, A] (и быть особенно осторожным, чтобы помнить, означает ли Right успех или сбой здесь - Left обычно используется для ошибок, а Right для "правильного" значения - Validation возможно яснее). Если вы хотите по желанию вернуть трассировку стека, вы можете использовать Lift Box[A], который может быть Full(validContents), Empty без дополнительных объяснений (очень похоже на Option[A] до здесь) или указать Failure который может хранить строку ошибки и/или бросать (и многое другое).

  • Возможно, вам нужно предоставить несколько указаний относительно того, почему это не удалось? Затем верните Either[Seq[String], A]. Если вы часто это делаете, возможно, вам захочется использовать Scalaz и Validation[NonEmptyList[String], A] вместо этого, что дает некоторые другие приятные лакомства. Посмотрите его для получения дополнительной информации об этом или посмотрите эти примеры использования.

Ответ 2

Я думаю, что в этом случае, если важно регистрировать исключения, то всеми способами отбрасывать исключения (и, возможно, просто возвращать String вместо опции). В противном случае вы можете просто вернуть None. Одно предупреждение - могут быть исключения по другим причинам, которые вы не предвидите, и в этом случае может быть опасно сделать код для всех кодов.

Одна вещь, которую вы могли бы сделать, это нечто вроде системы Lift Box. A Box по существу является опцией, но с добавлением пары функций: A Full похож на Some, a Empty похож на None, но Lift делает шаг дальше и имеет Failure, который похож на Empty, но с указанием причины/сообщения.

Ответ 3

Общее правило: "если вы можете обработать исключение, обработайте его". Поэтому не хватает контекста, чтобы догадаться. Вы можете использовать пару методов tryFetchUrl/fetchUrl.