编写错误代码及其字符串消息:Scala

时间:2019-01-30 09:53:46

标签: scala

我以这种方式存储错误代码及其字符串消息:

object Error {
  def FileNotFound(filename: String) = Error("ERR01", s"${filename} not found")
  def UserNotExist(userName: String) = Error("ERR02", s"${userName} not exist")
}

case class Error(code: String, value: String) {}

像这样保持它的好处是我可以将字符串值传递给错误消息。

我正在创建它

def validate(data: SomeType): List[Error] = {
    var errors = ListBuffer[Error]()
    if (validation1("abc") == false) {
      errors+= Error.FileNotFound("abc")
    }
    if (validation2("lmn") == false) {
      errors+= Error.UserNotExist("lmn")
    }
    errors.toList
}

我是Scala和函数式编程的新手。 这样写错误代码是正确的方法吗? 它遵循函数式编程范式吗?

scala:2.11

1 个答案:

答案 0 :(得分:2)

这是我的两分钱,上面有一个完整的例子。

我假设您想以简单易用的功能样式进行此操作,因此让我们删除可变的ListBuffer并了解如何处理。步骤的描述在代码之后。

更新:我想指出,在您的代码中,可以使用ListBuffer,因为它不会破坏rerefential transparency。这是因为您不会在函数外部公开其可变性质,并且函数的输出仅取决于其输入。

尽管如此,我还是更倾向于避免使用可变数据,除非出于特殊原因,例如紧凑性或性能。

object StackOverflowAnswer {

  /* Base type with some common fields */
  class MyError( val code: String, val msg: String )

  /* FileNotFound type, subtype of MyError, with its specific fields */
  case class FileNotFound( filename: String ) extends MyError(
    "ERR01", s"$filename not found"
  )

  /* UserDoesntExist type, subtype of MyError, with its specific fields */
  case class UserDoesntExist( userName: String ) extends MyError(
    "ERR01", s"$userName doesn't exist"
  )

  /*
   * Validates the file. If it finds an error it returns a Some(MyError) with
   * the error that's been found
   * */
  def checkForBadFile( data: String ): Option[MyError] =
    if( data.contains("bad_file.txt") )
      Some(FileNotFound("bad_file.txt"))
    else
      None

  /*
   * Validates the user. If it finds an error it returns a Some(MyError) with
   * the error that's been found
   * */
  def checkForMissingUser( data: String ): Option[MyError] =
    if( data.contains("bad_username") )
      Some(UserDoesntExist("bad_username"))
    else
      None

  /*
   * Performs all the validations and returns a list with the errors.
   */
  def validate( data: String ): List[MyError] = {
    val fileCheck = checkForBadFile( data )
    val userCheck = checkForMissingUser( data )
    List( fileCheck, userCheck ).flatten
  }

  /* Run and test! */
  def main( args: Array[String] ): Unit = {
    val goodData = "This is a text"
    val goodDataResult = validate( goodData ).map( _.msg )
    println(s"The checks for '$goodData' returned: $goodDataResult")

    val badFile = "This is a text with bad_file.txt"
    val badFileResult = validate( badFile ).map( _.msg )
    println(s"The checks for '$badFile' returned: $badFileResult")

    val badUser = "This is a text with bad_username"
    val badUserResult = validate( badUser ).map( _.msg )
    println(s"The checks for '$badUser' returned: $badUserResult")

    val badBoth = "This is a text with bad_file.txt and bad_username"
    val badBothResult = validate( badBoth ).map( _.msg )
    println(s"The checks for '$badBoth' returned: $badBothResult")
  }

}

我开始为错误定义类型结构,类似于您。

然后,我有两个功能,可对所需的每张支票进行验证。当发现错误时,将使用Scala的Option类型返回错误。如果您不熟悉Option,可以看看at this link或进行一些谷歌搜索。

然后,我具有验证功能,该功能调用并存储上述每个检查。最后一点是使用flattendoc here),将List[Option[MyError]]变平为List[MyError],除去中间的Option

然后有一些实际的代码为您展示了一些示例。