前言
之前寫過了Scalaz的Either(Disjunction)與Validation兩篇,今天老闆看到我的blog後,跟我說"寫一下Scalactic啊!",所以我就來寫了!!Scalactic
Scalactic這個東西,是從ScalaTest發展出來的,為了能方便直接"單獨"使用在Production的環境,當然ScalaTest裡面有包含了完整的Scalactic,如果你有使用ScalaTest的話,可以直接使用Scalactic。至於Scalaz和Scalactic的差異,細節可以參考這個影片(Comparing Functional Error Handling in Scalaz and Scalactic),簡單來說,有些觀念上的不同(沒有誰對誰錯),想讓使用上更明暸簡單,不用分Disjunction和Validation兩種型態,提供更單純的型態,而且在描述上可以更直覺。
概念上大自整理如下:
Or與其子類別Good與Bad
sealed abstract class Or[+G, +B] extends AnyReffinal case class Good[+G, +B](g: G) extends Or[G, B] with Product with Serializable
final case class Bad[+G, +B](b: B) extends Or[G, B] with Product with Serializable
Or就像是Either或Disjunction,因為Scalactic直接定義了Good和Bad,所以比Scala原生的Either用起來簡單,也比Disjunction看起來清楚。
而且Or的Bad子類別可以讓你累積errors,就像是Scalaz的Validation的功能一樣,比較有趣的是,開發的人覺得左邊的才是Good,右邊的是Bad,跟Scalaz的Validation相反。(分明就是讓大家用習慣後很難換去用另一種嘛!!!)
Every與其子類別One與Many
sealed abstract class Every[+T] extends PartialFunction[Int, T]final case class One[+T](loneElement: T) extends Every[T] with Product with Serializable
final case class Many[+T](firstElement: T, secondElement: T, otherElements: T*) extends Every[T] with Product with Serializable
Every是一個有順序性的、不可修改的、不能是空的元素的集合,One是繼承他,但裡面只有一個值,Many也繼承他,而裡面是兩個以上的值。
這裡的定義,其實就是為了讓Or裡的Bad可以是單一值與多值,就像是Validation中的accumulating errors的實作Non-Empty-List一樣,不過Scalactic是把這兩種合在一起(都叫Every),而不像Scalaz的Validation與ValidationNel(其實是Validation[NonEmptyList[E]])是兩種不同的型態。
Validation與其子類別Pass與Fail
sealed trait Validation[+E] extends AnyRefobject Pass extends Validation[Nothing] with Product with Serializable
case class Fail[E](error: E) extends Validation[E] with Product with Serializable
在使用Scalaz的Validation或是Either時,在用for或filter的時候,我們會不知道他是什麼型態,所以寫起來還要去判斷型態再來處理,這樣其實蠻麻煩的。
而Scalactic在使用Or型態的for或是filter的時候,讓你透過Closure在裡面可以回傳Pass或是Fail。可以把Validation想像成是Option,而Pass其實是None,Fail的時候才有值,這樣用起來不是更簡單嗎?
Accumulation
這裡面實作了accumulating errors的一些方法,包含了withGood, when, combined, validatedBy, zip,就是幫你把上面提到的Or, Every, Validation做轉換、或混在一起用的時候的工具。以下是使用Scalactic試寫的一段HTTP Request參數驗證 (亂寫的,邏輯不要太認真,主要是看用法)
沒有留言:
張貼留言