【问题标题】:Best Practices and Approaches while implementing pure functional Scala code which is dependent on impure code/libraries实现依赖于不纯代码/库的纯函数式 Scala 代码时的最佳实践和方法
【发布时间】:2021-10-20 02:07:23
【问题描述】:

我目前正在实现业务逻辑代码,该代码依赖于自定义 scala 库,该库有很多不纯的函数,我们有很多代码依赖于这个库并且无法重构,因为它会影响其他人。因此,我正在尝试编写尽可能纯的 scala 代码,并且需要针对少数用例的建议。

我有一个执行以下操作的 LDAP 实用程序库 根据用户名和密码进行认证并返回布尔值,但是如果有连接异常或未找到用户则直接抛出异常。 根据 UUID 和参数(如名字和姓氏)读取和更新数据的作用几乎相同 我的身份验证用例方法如下

  def authenticateToUpdate(userName:String,password:String):Option[Boolean] =
    Some(ldapService.authenticate(username,password))

// or using either type to get the message as well
  def authenticateToUpdate(userName:String,password:String):Either[String,Boolean]=
    (ldapService.authenticate(username,password)) match {
      case true => Right(true)
      case false => Left("Validation failed, Invalid Password")
      case exception: Exception => Left(exception.toString)
    }

//##for Some type
  authenticateToUpdate(userName,password).fold(InvalidPassword)(updateOrder(orderId,userName))

//##for Either type
// Looking into how to implement

所以我想尽可能将我的代码编写为函数式和接近纯函数的代码,需要帮助和建议如何处理这种情况来编写函数式 scala 代码。

【问题讨论】:

  • 上面的代码示例与我的工作代码非常相似,但不一样,请忽略未知变量名和其他。因为我想展示我的方法,并想知道我做对了
  • 如果库抛出异常,将调用包装在 Try

标签: scala functional-programming purely-functional


【解决方案1】:

正如 Tim 所说,在 Scala 中处理错误时,最简单的做法是将引发异常的代码包装在 Try 块中。例如:

import scala.util.{Try, Success, Failure}

Try {
  connector.makeCall()
} match {
  case Success(value) if value => Right("yay")
  case Success(value)          => Left("☹️")
  case Failure(ex)             => Left("An exception was thrown")
}

如果connector.makeCall() 行返回true,这将返回右,如果该行返回false 或异常,则返回左。

这是一个人为的例子,但这是您使用它的一种方式 - https://scastie.scala-lang.org/irmbBQ9ISeqgitRubC8q5Q

【讨论】:

    【解决方案2】:

    实际上,提供的这段代码不可能是纯的,因为结果 authenticateToUpdate 不仅取决于其参数(用户名、密码),还取决于ldapService 服务。

    话虽如此,我建议authenticateToUpdate 使用以下定义:

    def authenticateToUpdate(userName:String, password:String)(ldapService: (String, String) => Boolean): Either[String, String] = {
      Try(ldapService(userName, password)) match {
        case Success(value) if value => Right("OK")
        case Success(_) => Right("Failed to authenticate")
        caseFailure(ex) => Left(s"Something wrong: ${ex}")
      }
    }
    
    authenticateToUpdate("user", "password"){ case (user, password) =>
     ldapService.authenticate(username,password)
    }
    
    

    在提供的示例中,我们只是用一个纯函数包装了一个不纯函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 1970-01-01
      • 2023-03-31
      相关资源
      最近更新 更多