3

次の検証方法があります。

def validate(wine: Wine): List[Error] = {

  var errors = List[Error]()

  if (Validate.isEmptyWord(wine.name)) {
    errors ::= ValidationError("name", "Name not specified")
  } else {
    if (isDuplicate(wine, "name")) {
      errors ::= ValidationError("name", "There already exists a wine with the name '%s'".format(wine.name))
    }
  }

  if (Validate.isEmptyWord(wine.grapes)) {
    errors ::= ValidationError("grapes", "Grapes not specified")
  }

  if (Validate.isEmptyWord(wine.country)) {
    errors ::= ValidationError("country", "Country not specified")
  }

  // more stuff like this and finnally
  errors.reverse
}

あなたはアイデアを得る

var List[Error] を回避してより機能的にするには、どのように変更しますか?

4

2 に答える 2

10

ScalazValidationは、この種の問題に対する関数型アプローチを非常に簡単にするクラスを提供します。この Stack Overflow answerValidationには、使用方法のより詳細な例がありますが、ここでは、状況でどのように機能するかを示すスケッチも示します。次の設定を想定しています。

case class Wine(name: String, grapes: String, country: String)
case class ValidationError(name: String, msg: String)

これで、いくつかの検証メソッドを書くことができます (私は Scalaz 7 を使用していることに注意してください):

import scalaz._, Scalaz._

def checkNonempty(v: String, name: String, msg: String) =
  if (v.nonEmpty) v.successNel else ValidationError(name, msg).failNel

def checkDuplicate(v: String, name: String, msg: String) =
  if (true) v.successNel else ValidationError(name, msg).failNel

もちろん、最後の行に独自の重複チェックを追加する必要があります。次に、すべてをまとめてラップできます。

def createWine(name: String, grape: String, country: String) = (
  checkNonempty(name, "name", "Name not specified").flatMap(_ =>
    checkDuplicate(name, "name",
      "There already exists a wine with the name '%s'".format(name)
    )
  ) |@|
  checkNonempty(grape, "grape", "Grape not specified") |@|
  checkNonempty(country, "country", "Country not specified")
)(Wine.apply)

今、次のように書くと:

val result: ValidationNEL[ValidationError, Wine] = createWine(
  "Whatever Estates", "Whatever Grape", "U.S."
)

成功値を取得します。

Success(Wine(Whatever Estates,Whatever Grape,U.S.))

しかし、無効な入力を与えると:

val result: ValidationNEL[ValidationError, Wine] = createWine(
  "", "Some Grape", ""
)

蓄積されたエラーのリストを取得します。

Failure(
  NonEmptyList(
    ValidationError(name,Name not specified),
    ValidationError(country,Country not specified)
  )
)

もちろん、独自の検証ロジックを作成することもできますが、このようなことを頻繁に行う場合は、Scalaz のようなライブラリを使用する価値があります。

于 2012-09-22T21:29:11.613 に答える
3

の代わりにisXを返すメソッドを記述してから、Option[Error]Boolean

List(
  Validate.isEmptyWord(wine.name, "name", "Name not specified").
  orElse( Validate.isDuplicate(wine.name, "name", "There already exists...") ),
  Validate.isEmptyWord(wine.grapes, "grapes", "Grapes not specified"),
  ...
).flatten

エラーが発生します。また、削除できる重複は他にもたくさんあります (たとえば、常に"x", "X not specified"である場合は、供給"x"して残りを で埋めることができますisEmptyWord)。

于 2012-09-22T20:47:45.467 に答える