视图的Getter/Setter主要说的是当视图操作DomainModel(或者与DomainModel对应的DTO-Data Transfer Object)的读取操作,如果使用的Passive View的方式就不用考虑这个问题了,因为这时候的View不存在对Model的操作。
Getter/setter指的什么
为什么在使用Supervising Controller的时候需要考虑?回答这个问题之前需要先说明这里说的Getter/setter分别是什么。比如我们定义一个MyView:
public class MyView{
……
public MyEntity{
get{
return myEntity;
}
set{
myEntity=value;
}
……
}
Getter是指由View提供的对某个实体(Domain Model 或 DTO)对象的读操作,presenter通过getter从view中读取实体的数据然后进行保存;Setter当然就是对应的写操作了,presenter将从model从取出的实体数据传给view就通过setter访问器。所以的这里说的getter和setter都是站在从view的外部看view的这个角度,比如说presenter对view的操作就是这种情况。
存在什么问题?
回到前面的问题,如果一个view同时有getter和setter访问器,presenter把entity通过setter传入view之后,view利用UI的数据对entity进行“更新”。注意这里的更新有两种做法,一种是由view将修改过的entity传给presenter,由后者进行更新,一种是view直接调用model中相应的方法进行更新,不要忘记了Supervising Contrller中view对model有一定的了解,它可以操作model。当采用第二种方式更新的时候view对model的了解太多,会导致view和数据访问层的联系过于紧密。初此之外,还有一个问题同时存在于这两种更新方式之中,就是对entity的修改可能既存在于view也存在于presenter,散布在多处的修改很容易导致不一致性,而且难以理解和维护。
DTO的好坏
使用DTO可以解决上面的问题。DTO是用于在层与层之间传递数据的一种中间数据形式,它的数据来自domain object,它的使用使得view不再依赖于具体的domain model,因为这时候的view只需要知道与presenter之间通讯的数据形式即可。使用DTO之后,view端得到和修改的都是DTO,presenter从view获得DTO之后进行一次DTO-Domain Object的转换,最后将转换得到的domain object存入数据库。这样一来view和presenter的分工明确,而且view对dto的修改不会影响到最终数据,因为真正的数据修改实际上只在presenter内部发生,dto只是做了临时存储之用。
使用dto也有它的坏处,如果系统很大,domain object很多,那就意味着DTO需要很多,对domain 的修改都要相应地在dto上实施,使得维护工作量变大。
用Update Method 替代Getter
这是Billy McCafferty在他的blog中提出来的方法。他提出保留view的setter访问器而“去掉getter访问器,其而代之的是由view提供一个Update方法”。这样view既可以从presenter处得到domain model的数据,又可以利用自己的Update方法更新来修改这些数据以反应用户的输入。注意这里的“Update”并不是写回了数据库,而只是是修改了Domain object的数据,还存在于内存中。以保存操作为例,基本步骤如下(Presenter:表示都是发生在presenter内部):
Presenter: view.Update(myEntity)
Presenter: presenter.Validate(myEntity)
Presenter: customerDao.SaveOrUpdate(myEntity)
可以看出对数据的修改发生在view,而presenter内部只是进行逻辑控制和数据验证。
总结
实际上DTO方式和Update Method 方式的目的都是为了控制对数据的修改,严格限制数据的修改只发生在一个地方不至于散布在各处,让view和presenter分工明确,理解和维护起来都容易。
我比较喜欢Passive View方式,因为View和Model完全分开,但是有时候Supervising的方式也很不错,比如在winform中要使用数据绑定,在asp.net中要使用Object Data Source,用后者就很方便。总之没有绝对的好坏,视情况而定。
没有评论:
发表评论