2013-02-18 84 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