驗證Scala中的一個類凝聚力的方式我的目標是建立一個有效的User
實例之前驗證小號apply
方法User
「的object
內S場」:使用Scalaz 7
case class User(String userName, String password)
object User {
def apply(userValidator: UserValidator): ValidationNel[UserCreationFailure, User] = {
//call UserValidator's validate() method here and initialize effective User instance.
}
}
我選擇使用Validation
從Scalaz7積累潛在的非法論點/錯誤。
以下代碼的一個缺點是Scalaz7 API迫使我使驗證器自己創建實例。但是,通過遵循單責任原則,顯然不是它的作用。它的作用是驗證字段並返回一些錯誤列表。
讓我們先來介紹我的實際代碼(有關信息,Empty****
對象只是一些case object
延伸UserCreationFailure
):
class UserValidator(val userName: String, val password: String)
extends CommonValidator[UserCreationFailure] {
def validate(): ValidationNel[UserCreationFailure, User] = {
(checkForUserName ⊛
checkForPassword)((userName, password) => new User(userName, password)
}
private def checkForUserName: ValidationNel[UserCreationFailure, String] = {
checkForNonEmptyString(userName) {
EmptyUserName
}
}
def checkForPassword: ValidationNel[UserCreationFailure, String] = {
checkForNonEmptyString(password) {
EmptyPassword
}
}
}
我會想到的是僅僅返回此代碼片段:
(checkForUserName ⊛ checkForPassword)
並將相應的結果帶入我的User
類,從而可以通過執行以下操作創建有效實例:
def apply(userValidator: UserValidator): ValidationNel[UserCreationFailure, User] = {
userValidator(username, password).validate()((userName, password)(new User(userName, password))
}
事實上,它對SRP更友好。
但(checkForUserName ⊛ checkForPassword)
返回一個完全private
類型類型:
private[scalaz] trait ApplicativeBuilder[M[_], A, B]
,
因此,我沒有手的class
類型返回。
因此,我不得不直接將用戶的創建與它關聯。
我該如何保持SRP並保持此驗證機制?
----- UPDATE ----
由於@Travis布朗提到的,意圖使用外部class
我UserValidator
可能看起來怪怪的。實際上,我希望驗證器是可嘲弄的,因此,我不得不使用trait
/abstract class
的構圖。
爲什麼我想處理組成而不是特質(繼承)是因爲我期望我的'UserValidator'是可嘲弄的。整個目標是提供一個'可嘲諷的'UserValidator',以便適合我的'User'類的單元測試。 – Mik378 2013-05-05 20:39:23
當然,我們不能嘲笑任何一個預定班的任何特質/超類。 – Mik378 2013-05-05 20:51:00
我喜歡你的解決方案,儘管我認爲保持作文,因此與外部'UserValidator'類,但讓'用戶'類進行適當的不同驗證方法調用,就像你已經提出的。非常感謝 :) – Mik378 2013-05-05 21:39:57