Подтвердить что ты не робот

Является ли использование исключений плохой практикой в ​​scala?

Я видел много раз фрагменты кода scala, используя Option (для простых значений) или Либо [List [Error], T] для обработки ошибок.

это дает место для кода вроде этого

def createApplicationToken(accessToken: AccessToken): Either[List[Error], ApplicationToken] = {

// go to social info provider and fetch information
retrieveProviderInfo(accessToken).fold(
  errors  => Left(errors),
  info    => {
    // try to find user using the info from the provider
    // if it not there, create user
    User.findOrCreateFromProviderInfo(info).fold(
      errors  => Left(errors),
      user    => {
        // try to create a fresh token and save it to the user
        user.refreshApplicationToken.fold(
          errors  => Left(errors),
          user    => Right(user.token)
        )
      }
    )
  }
)

Что создает не очень приятное вложение кода, заставляет вас справляться с ошибками на каждом шаге, а также заставляет вас возвращать все ваши функции Aither [...]

Итак, я хотел бы знать, если

  • использование исключений не рекомендуется в scala (или вообще функциональном программировании)

  • есть какие-либо недостатки в их использовании (относительно неизменяемости или кода concurrency)

  • исключения как-то противоречат принципам или функциональному программированию

  • вы можете придумать лучший способ кодирования данного примера

-

Можно было бы избежать вложенности, выйдя из функции, как только ошибка будет найдена с помощью оператора return, но использование return также не рекомендуется в scala...

4b9b3361

Ответ 1

В следующей версии используется тот факт, что правая проекция Either является монадой и в точности эквивалентна вашему коду:

def createApplicationToken(accessToken: AccessToken) = for {
   info <- retrieveProviderInfo(accessToken).right
   user <- User.findOrCreateFromProviderInfo(info).right
   refr <- user.refreshApplicationToken.right
} yield refr.token

И гораздо лучше продемонстрировать преимущества Either.

В более общем плане правила такие же, как в Java: используйте исключения для исключительных ситуаций. Вы просто можете обнаружить, что вы изменили свое определение исключительного момента, когда работаете в этом стиле, например, неверный ввод пользователя не является действительно исключительным, тайм-аутный сетевой запрос не является действительно исключительным и т.д.

Ответ 2

Как сказал om-nom-nom, я задал аналогичный вопрос: Выбрасывание исключений в Scala, что такое "официальное правило"

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


Ответ 3

Ответ зависит от идеального и практического. В идеале избегайте использования исключений. Практически, вы не можете жить без них.

Scala кажется предпочтительным для однострочных линий, а вдоль этих строк v2.10 имеет новую монаду Try:

import scala.util.Try

def percentCompleted( total:Int, done:Int ): Int = Try (done * 100 / total) getOrElse 100

percentCompleted( 0, 10 )    // Catches divide-by-zero and returns 100% instead