Правильное использование Both, Try и Exceptions/ControlThrowable в scala

В моем коде scala (библиотеках, а также приложениях) я в настоящее время использую смесь Option и Try, когда любой из них кажется более подходящим.

Я склонен реализовывать методы "doSomething", которые могут быть успешными с возвращаемым значением или с ошибкой с помощью Try. То есть они могут содержать код, который бросать, или, когда я обнаруживаю ошибки «вручную», я искусственно создаю Throwable и возвращаю Failure. Следовательно, возвращаемое значение этих методов — это Try[ReturnType].

Теперь я прочитал, что создание исключений несколько неоптимально, потому что оно создает трассировку стека (и, следовательно, медленно), что мне даже не нужно. Я также видел примеры, использующие подкласс ControlThrowable, которые не создают трассировку стека, однако у них также нет сообщения, и Try, конечно же, не поймает его.

Теперь мой конкретный вопрос будет заключаться в том, должен ли я вообще предпочитать EitherTry, когда я хочу выполнять обработку ошибок во время выполнения / возвращаемые значения метода, и использовать Try только в ситуациях, когда мне действительно нужно что-то поймать (например, сторонний код)?
Таким образом, мне не пришлось бы создавать неуклюжие Throwable, а вместо этого использовать только, например. строки в Left для ошибок.

Итак, в основном:

  • Option: ежедневное использование чего-то, что просто имеет значение или нет
  • Try: перехватывать исключения внутри методов, но не использовать их как возвращаемое значение
  • Either: универсальное возвращаемое значение, содержащее ошибку (строку) или значение успеха

Будет ли эта концепция работать хорошо, или есть более жизнеспособный/общий подход?

Вы можете довольно легко определить подкласс Throwable, который не создает трассировку стека через конструктор с writableStackTrace.

Travis Brown 13.02.2019 09:10

в Scala также есть черта NoStackTrace

Thilo 13.02.2019 09:13

На самом деле это не ответ, но я считаю, что два соответствующих варианта — это Try и Either[Throwable, ?], и решение в значительной степени зависит от культуры: выберите Either, если вы используете кошек и библиотеки, связанные с кошками, рассмотрите Try в противном случае и будьте последовательны, конвертируя при необходимости как можно раньше.

Travis Brown 13.02.2019 09:13

Что бы вы ни делали, держитесь подальше от ControlThrowable. Это предназначено только для внутреннего использования, когда разработчикам языка нужно возиться с потоком управления способами, которые в противном случае были бы невозможны.

Thilo 13.02.2019 09:17

Не существует такой вещи, как одно кольцо, чтобы править всеми. Используйте Try (или свой собственный ADT продукта), где вы хотите вернуть типы продуктов, и используйте Either, если вам нужен возврат типа суммы.

sarveshseri 13.02.2019 09:22

Что ж, основное отличие будет заключаться в том, что часть ошибки в Try — это всегдаThrowable, но в Either это может быть что угодно, и, как я уже сказал, создание Throwable — это то, чего я хотел бы избежать. Или, другими словами: должен я все еще создаю Throwable для передачи описаний ошибок в возвращаемом значении, в то время как того же можно добиться с помощью Either[String,_] + верно?

user826955 13.02.2019 09:42

@Travis Brown: Какая польза от использования Either[Throwable, ?] вместо Try?

user826955 13.02.2019 09:45

@user826955 user826955 1) Вы работаете с библиотеками, которые используют Either (например, circe), проще взаимодействовать с не-Throwable представлениями об ошибках, меньше волшебства, связанного с перехватом исключений, и т. д.

Travis Brown 13.02.2019 10:45

@TravisBrown Почему вы хотите вернуть либо [Throwable, ?], если ваша ошибка не была сгенерирована из-за перехваченного Throwable и достаточно строки, описывающей ошибку, или, например, класса case с метаданными о контексте ошибки? Он говорит о создании исключения для представления ошибки.

angelcervera 31.01.2020 09:57

Остаток: Scala Throwable — это псевдоним java.lang.Throwable. Я всегда стараюсь избегать нативных java-приложений.

angelcervera 31.01.2020 10:03
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
10
1 653
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как заявил Трэвис Браун в комментариях, не существует условности настоящий, и это в значительной степени культурная вещь. Согласованность — это самое важное, чтобы ваш код оставался читабельным. Я видел кодовые базы, которые:

  • Используйте параметры, чтобы обозначить «None выполнено успешно, и любой Some(...) содержит сообщение об ошибке».
  • Используйте Try, чтобы вернуть либо Success, содержащую пустую строку, либо Failure, содержащую сообщение об ошибке.
  • Используйте Либо наоборот (т.е. Either[?, Throwable])

Очевидно, что это нехорошая практика, но пока вы последовательны, это не имеет значения В самом деле. Условие, которое я лично использую как для отдыха, так и на работе:

  • Option, когда допустимо отсутствие значения (например, при анализе JSON с использованием playframework).
  • Try при попытке сделать что-то, что может потерпеть неудачу (если только это не в будущем, и в этом случае я просто использую .recover), где я забочусь о соответствии типа исключения, но также хочу, чтобы результат успеха был там, где он доступен.
  • Either, когда я не хочу возвращать Exception/Throwable в случае "сбоя" (хотя, если честно, это бывает редко).

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

Спасибо за ваш комментарий. Я решил пойти, как я предложил в своем вопросе. Использование Try для перехвата исключений от третьих лиц и Either[A, B] в качестве общего возвращаемого значения, при этом A является настраиваемым типом ошибки с дополнительной информацией. Option, как «обычно», используется всякий раз, когда допускается отсутствие значения. И вообще я вообще избегаю использования исключений, поэтому никогда не выбрасываю и не создаю их.

user826955 21.02.2019 14:01

Другие вопросы по теме