在web开发中(包括asp.net)有个特常见的需求,把一个实体实例(对应数据库中的表)的字段填充到页面,页面提交后把控件中的值回填到一个实体实例中,提交之前对输入验证。例如:用户信息详情显示/修改功能。当然在实际中还会有如下需求,修改用户密码的时候需要再次输入进行验证,密码不会直接存入数据库而是要做hash加密等等。以前遇到这类问题,我常常是利用反射来做实体和页面控件之间的相互填充,大多数情况下这么做没问题,只是缺乏灵活,逻辑不明确。比如,再次输入密码这个字段肯定不属于数据库表中的字段,它只是一个逻辑上的辅助字段而已,但是我又必须要它。所以在UserInfo这个实体里面就会有一个PwdConfirm之类的字段,然后通过Attribute来区分是否为数据库表字段。显然这种做法味道很不好。而且实际开发中一个实体类在不同的场景下需要的逻辑辅助字段并不一样,有时候连字段是否必填这种验证要求都不一样。所以我们死守着实体类来解决从UI到数据库的所有应用是行不通的,而引入一个间接概念Form对象就好多了。
在django中Form就是针对一个页面或一个应用场景而定制的“实体类”,它有自己的字段,验证方式,初始值,UI控件类型等等,这样做的好处非常明显,验证,UI展示都非常灵活,将Form对象装换为一个实体也非难事。有一点点小麻烦就是要我们在需要的时候就要定义一个Form,比如LoginForm、UserForm,虽然这两个Form都是为了处理User相关逻辑的,但是使用场景不同一个是登陆,一个用户信息展现。虽然说是小麻烦,这个代价还是能接受的,因为你既可以手工来定义Form中的字段,也可以根据已有的实体类来生成Form对象。从设计模式上来说MVC中,M一般指领域对象,它本身就不应该暴露出来,而C与V之间的传输对象就应该是Form obj。试想我们的系统中V这一层可能有web,winform或silverlight等等。我们的Form obj就可以根据V的不同需求而生成不同的样子。这点上单凭一个实体或领域对象可是解决不了的。
感叹啊,Form这东西简单实用也不需要特定的语法支持(当然在.net中实现要比python中困难一些,而有c#3.0会方便一些)我怎么就没想到呢,看来我等小球只能慢慢体会大师们的思想了。