2013-02-18 79 views
1

假設一個Car模型對象(如case class),不可變且使用構建器模式創建。 (由Joshua Bloch製作的模式)。Play Framework 2 /冗餘對象驗證

build方法調用CarValidator對象,以便允許創建或不相關的Car。否則,它會拋出一個IllegalStateException,其中包含意外的字段。

因此,在運行時,任何人都無法創建陳舊或無效的Car,太棒了!

現在假設一個web表單創建一個Car。 Play的控制器將含有這種形式的映射:

val carForm = Form(    //this is a conceptual sample 
    mapping(
     "brand" -> nonEmptyText, 
     "description" -> nonEmptyText, 
     "maxSpeed" -> number 
     "complexElement" -> number.verifying(........) //redundant validation here 
    )(Car.apply)(Car.unapply) 
) 

在這個例子中,有一些基礎領域,但想象的複雜領域,要求複雜的業務驗證喜歡這裏的complexeElement

我真的有這樣的感覺,我很容易打破幹(不要重複自己)。

事實上,無論表單驗證會帶來什麼結果,這將由我的Car構建器的驗證器提供,因爲對模型的驗證是最重要的驗證位置,不應該依賴於其他任何內容。

我想象一下Helper類的解決方案,該類接近我的Controller,處理與構建器使用的相同驗證器對象。然而,它迫使我得到所有驗證方法public,以便在我的Web表單的任何驗證步驟(如上面的代碼段中)獨立調用。

保持這個建設者的原則,同時避免打破DRY會是一個很好的做法嗎?

回答

2

如果您想保留構建器模式,則不應該有Form創建實例。表單應該確保所輸入的信息是正確的類型。該表單無法創建最終的Car,因爲它不知道生成Car的規則。

所以我想說你讓表單把東西放入一箇中間對象(一個元組或PossibleCar個案類),並用該對象構建您的Car(使用構建器)。

還有另一條路線可用,但這意味着您必須創建(可能是複雜的)結構,讓您調整不同類型的驗證。然後構建者和表單可以使用這些驗證(藉助適配器)創建有效的汽車。我對你所處的情況不夠了解,以便告訴你需要採取哪條路線。

+0

如果我沒有直接在映射中進行直接驗證,我怎麼能在映射表單時使用由Play提供的錯誤通知機制? – Mik378 2013-02-18 00:43:02

+1

您可以使用Form'類的'withError'方法 – EECOLOR 2013-02-18 10:40:52

+0

最後,我選擇在模型和表單之間共享一個Validator。這個驗證器返回一些'ValidationNEL'(從scalaz),我不得不將它們調整爲'Constraint',以便設置它們來驗證我的表單的方法。第一個建議的解決方案並不是最佳的,因爲有了它,我們永遠無法在一個步驟中顯示整個錯誤列表。 – Mik378 2013-02-21 21:32:54