В моем коде scala (библиотеках, а также приложениях) я в настоящее время использую смесь Option и Try, когда любой из них кажется более подходящим.
Я склонен реализовывать методы "doSomething", которые могут быть успешными с возвращаемым значением или с ошибкой с помощью Try. То есть они могут содержать код, который бросать, или, когда я обнаруживаю ошибки «вручную», я искусственно создаю Throwable и возвращаю Failure. Следовательно, возвращаемое значение этих методов — это Try[ReturnType].
Теперь я прочитал, что создание исключений несколько неоптимально, потому что оно создает трассировку стека (и, следовательно, медленно), что мне даже не нужно. Я также видел примеры, использующие подкласс ControlThrowable, которые не создают трассировку стека, однако у них также нет сообщения, и Try, конечно же, не поймает его.
Теперь мой конкретный вопрос будет заключаться в том, должен ли я вообще предпочитать EitherTry, когда я хочу выполнять обработку ошибок во время выполнения / возвращаемые значения метода, и использовать Try только в ситуациях, когда мне действительно нужно что-то поймать (например, сторонний код)?
Таким образом, мне не пришлось бы создавать неуклюжие Throwable, а вместо этого использовать только, например. строки в Left для ошибок.
Итак, в основном:
Option: ежедневное использование чего-то, что просто имеет значение или нетTry: перехватывать исключения внутри методов, но не использовать их как возвращаемое значениеEither: универсальное возвращаемое значение, содержащее ошибку (строку) или значение успехаБудет ли эта концепция работать хорошо, или есть более жизнеспособный/общий подход?
в Scala также есть черта NoStackTrace
На самом деле это не ответ, но я считаю, что два соответствующих варианта — это Try и Either[Throwable, ?], и решение в значительной степени зависит от культуры: выберите Either, если вы используете кошек и библиотеки, связанные с кошками, рассмотрите Try в противном случае и будьте последовательны, конвертируя при необходимости как можно раньше.
Что бы вы ни делали, держитесь подальше от ControlThrowable. Это предназначено только для внутреннего использования, когда разработчикам языка нужно возиться с потоком управления способами, которые в противном случае были бы невозможны.
Не существует такой вещи, как одно кольцо, чтобы править всеми. Используйте Try (или свой собственный ADT продукта), где вы хотите вернуть типы продуктов, и используйте Either, если вам нужен возврат типа суммы.
Что ж, основное отличие будет заключаться в том, что часть ошибки в Try — это всегдаThrowable, но в Either это может быть что угодно, и, как я уже сказал, создание Throwable — это то, чего я хотел бы избежать. Или, другими словами: должен я все еще создаю Throwable для передачи описаний ошибок в возвращаемом значении, в то время как того же можно добиться с помощью Either[String,_] + верно?
@Travis Brown: Какая польза от использования Either[Throwable, ?] вместо Try?
@user826955 user826955 1) Вы работаете с библиотеками, которые используют Either (например, circe), проще взаимодействовать с не-Throwable представлениями об ошибках, меньше волшебства, связанного с перехватом исключений, и т. д.
@TravisBrown Почему вы хотите вернуть либо [Throwable, ?], если ваша ошибка не была сгенерирована из-за перехваченного Throwable и достаточно строки, описывающей ошибку, или, например, класса case с метаданными о контексте ошибки? Он говорит о создании исключения для представления ошибки.
Остаток: Scala Throwable — это псевдоним java.lang.Throwable. Я всегда стараюсь избегать нативных java-приложений.





Как заявил Трэвис Браун в комментариях, не существует условности настоящий, и это в значительной степени культурная вещь. Согласованность — это самое важное, чтобы ваш код оставался читабельным. Я видел кодовые базы, которые:
None выполнено успешно, и любой Some(...) содержит сообщение об ошибке».Either[?, Throwable])Очевидно, что это нехорошая практика, но пока вы последовательны, это не имеет значения В самом деле. Условие, которое я лично использую как для отдыха, так и на работе:
Option, когда допустимо отсутствие значения (например, при анализе JSON с использованием playframework).Try при попытке сделать что-то, что может потерпеть неудачу (если только это не в будущем, и в этом случае я просто использую .recover), где я забочусь о соответствии типа исключения, но также хочу, чтобы результат успеха был там, где он доступен.Either, когда я не хочу возвращать Exception/Throwable в случае "сбоя" (хотя, если честно, это бывает редко).Независимо от того, что из вышеперечисленного я использую, я лично считаю, что лучше держать его закрытым как можно дольше. Это предотвращает появление ненужных (haha) объектов Throwable в вашем коде и упрощает отладку, поскольку нет скрытых getOrElse строк, возвращающих значения по умолчанию (это может очень раздражать в больших кодовых базах).
Спасибо за ваш комментарий. Я решил пойти, как я предложил в своем вопросе. Использование Try для перехвата исключений от третьих лиц и Either[A, B] в качестве общего возвращаемого значения, при этом A является настраиваемым типом ошибки с дополнительной информацией. Option, как «обычно», используется всякий раз, когда допускается отсутствие значения. И вообще я вообще избегаю использования исключений, поэтому никогда не выбрасываю и не создаю их.
Вы можете довольно легко определить подкласс
Throwable, который не создает трассировку стека через конструктор сwritableStackTrace.