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 のようなライブラリを使用する価値があります。