论坛首页 Java企业应用论坛

炒PO-VO-DTO的冷饭,Remote下PO的运用方式问题

浏览 25354 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-03-17  
Quake Wang 写道
假如我能够把Person这个对象直接传递到client的话, 我可以利用对象关系, 直接写:
Person.name, Person.company.name
和Person.name, Person.address.zipCode

来看一个重构的问题。
比如刚开始采用了你这种设计。后来发现Person其实不应该同Company绑在一起。而应该是Employee才和Company(不是每个人都属于某一家公司)有关。
这时DomainOjbect变为
public class Employee
{
....
  private Person person;
  private Company;
  private Place place; //职位
.....
}
那么客户端曾经使用原来关系的很多代码是不是需要修改?
原来传递Person的现在需要传递Employee。
0 请登录后投票
   发表时间:2005-03-17  
partech 写道

是的是和客户相关,但是Customer对象确实是不知道任何一个协议的,协议自己
知道自己属于那个客户。在这里强制了一个关联方向即协议 ---〉客户。
现实中的关联都是双向的,但在程序里我们可以将它实现为单向的。

你的意思是协议决定了客户状态,而客户不知道自己跟什么协议有关?
这样的场景,其实简单的把你在service中组装dto的代码移到getStatus()中而已.
0 请登录后投票
   发表时间:2005-03-17  
youcai 写道
partech 写道

是的是和客户相关,但是Customer对象确实是不知道任何一个协议的,协议自己
知道自己属于那个客户。在这里强制了一个关联方向即协议 ---〉客户。
现实中的关联都是双向的,但在程序里我们可以将它实现为单向的。

你的意思是协议决定了客户状态,而客户不知道自己跟什么协议有关?
这样的场景,其实简单的把你在service中组装dto的代码移到getStatus()中而已.

你的业务层没有子层吗?一个业务对象可以调用任何一个其他的业务对象?
那么你的Domain Model将会是块果冻。修改任何一个对象,你都会吃不准
会影响到多少其他的对象。
Customer低层的业务对象,相反协议层要高的多,所以
Customer中就不能有getStatus的方法,明白吗?
0 请登录后投票
   发表时间:2005-03-18  
partech 写道

来看一个重构的问题。

To partech:
那么我是否可以这样理解: 采用DTO目的是为了给Client一个承诺, 你们拿到的ValueObject是相对稳定的, 即便是业务对象模型改动了, 那么服务端的代码编写人员会修改原先的组合代码, 让ValueObject保持稳定, 这样Client端的代码就不需要进行改变了?

To jackyz:
我按照前面的想法试验了透明的分布式lazy load, 确实是可以用的, 这个周末我把代码整理一下, 发上来以后继续讨论.
0 请登录后投票
   发表时间:2005-03-18  
Quake Wang 写道

To partech:
那么我是否可以这样理解: 采用DTO目的是为了给Client一个承诺, 你们拿到的ValueObject是相对稳定的, 即便是业务对象模型改动了, 那么服务端的代码编写人员会修改原先的组合代码, 让ValueObject保持稳定, 这样Client端的代码就不需要进行改变了?

这只是DTO的效果,而不是它的目的。
DTO应当从用例交互的视角来设计,目的在于清晰的描绘交互的输入输出。
而和将来的业务层设计无关,正是这样它才不会依赖于业务层,只依赖于用例的交互,进而客户端也就不依赖业务层了。
0 请登录后投票
   发表时间:2005-03-18  
partech 写道

这只是DTO的效果,而不是它的目的。
DTO应当从用例交互的视角来设计,目的在于清晰的描绘交互的输入输出。

我去查看了一些关于DTO的定义:
http://martinfowler.com/eaaCatalog/dataTransferObject.html
http://c2.com/cgi/wiki?DataTransferObject
从这里看, 它的目的是为了减少在多层架构下, 减少remote call的次数.

退一步来说, 假设它还有你所说的"用来描绘交互的输入输出"目的, 那么你前面拿"重构"来置疑直接传递业务对象的问题, 也同样会发生在DTO上:
以前你设计的是PersonDTO, 它有name, companyName属性.
重构以后就多出来了另外一个EmployeeDTO, 而PersonDTO的companyName就没有了, 那么客户端还是需要修改很多代码.

论坛里面讨论过DTO的问题好像有很多了, 我还是认同这种观点: 在Hibernate + Spring 或者EJB3的帮助下, 只要能够减少remote call的次数和开销, 就不需要用DTO.

随着技术的发展, 模式是否也需要随着发展呢?
0 请登录后投票
   发表时间:2005-03-18  
Quake Wang 写道
我按照前面的想法试验了透明的分布式lazy load, 确实是可以用的, 这个周末我把代码整理一下, 发上来以后继续讨论.


Excellent!!!

partech 写道
这只是DTO的效果,而不是它的目的。DTO应当从用例交互的视角来设计,目的在于清晰的描绘交互的输入输出。而和将来的业务层设计无关,正是这样它才不会依赖于业务层,只依赖于用例的交互,进而客户端也就不依赖业务层了。


我觉得"用例交互的视角"应该是"UI设计层面"要主要考虑的问题.并不是一定要用DTO的原因.

如同Web应用中的Action/Controller等,这些类本质上就是定义用户交互的类,它们位于服务器端,它们的"DTO"是Request和Response.但这与他们在后端是直接使用DomainObject或DTO并无必然的关系.
0 请登录后投票
   发表时间:2005-03-18  
Quake Wang 写道

退一步来说, 假设它还有你所说的"用来描绘交互的输入输出"目的, 那么你前面拿"重构"来置疑直接传递业务对象的问题, 也同样会发生在DTO上:
以前你设计的是PersonDTO, 它有name, companyName属性.
重构以后就多出来了另外一个EmployeeDTO, 而PersonDTO的companyName就没有了, 那么客户端还是需要修改很多代码.

不是这样的。客户端可以不修改,因为当一个东西约定俗成后即使他不能精确的反应真实的情况,那也不是不可以的,因为它是面向交互的,只要能够清楚的描述交互就行了。比如股票。
股民说中国的股市(好比VO的定义)什么什么,其实是不准确的,按照交易所的定义应该说证券市场(就好比你的业务层的定义)。
证券不光只有股票一种。但是你说股市,大家都能理解,不会狭义的理解为只包含股票的市场。股民要炒股是否还有把交易所的交易系统研究清楚呢?你说股民会同意吗?直接传递VO正是后台开发人员要求前台开发人做类似的事情。
客户端不会知道也不必知道person,Employee等等业务层精确概念的区别。
从使用的角度来看,用户也是不会领悟到业务层如何如何的优雅的。

模式是会发展,但是得给出充分理由,罗素说过:“未经检验的生活不值得过。”
同样未经检验的新模式也不值得采用,并且我不太清楚你这种模式在那里有详细的论述?能告诉我吗?

直接传递PO,将导致下面的问题。
1.控制类同实体类分离,导致贫血的DomainMode的产生,违反了OO的封装的基本原则。使得结构同Transaction Script没有多大区别。
2.把DomainObject的结构暴露给前端,使得耦合过紧,加重了重构的努力。同时对前台开发人员的要求增多。
3.开发的并行受到很大的影响。
0 请登录后投票
   发表时间:2005-03-18  
to: All

我想大家的分歧并没有看上去的那么大.

在Remote的环境下,对象通过网络传输是必须的,即使是实现了透明RPC的LazyLoad,还是必须要传输数据到Client端.这就是所谓的DTO.

大家的分歧在于,是否有必要将这个被Transfer到Client端的Object作为一个独立的层次(接口)来看待.

我的观点是不要把它作为一个被明确定义出来的独立层次,而是将它作为内部隐藏的一个实现手段.

对外,它仍然是系统中已经存在的对象模型(DomainObject),接口完全一致,只是实现不同.它的内部实现是以这个"被Transfer到Client端的Object"为基础,通过一些RPC方法去提供DomainObject所定义的全部接口(主要是提供一些关联对象的访问方法).对于外部来说,这些RPC动作是完全透明的.

partech主要是站在软件工程的角度看待这个问题,DTO作为一个引入的层次提供了一个隔离机制(至少在大部分情况下都很有效),使得前后端开发可以并行.如果去掉了它,开发的效率如何保证?

实际上,这个问题不仅仅对于我们这里讨论的RIA,对所有的DomainObject-Over-Layers方案,都是具有现实意义的问题.这是另外一个层面上的问题,但这也是我们需要考虑的.
0 请登录后投票
   发表时间:2005-03-18  
partech 写道

直接传递PO,将导致下面的问题。
1.控制类同实体类分离,导致贫血的DomainMode的产生,违反了OO的封装的基本原则。使得结构同Transaction Script没有多大区别。
2.把DomainObject的结构暴露给前端,使得耦合过紧,加重了重构的努力。同时对前台开发人员的要求增多。
3.开发的并行受到很大的影响。

在domain model这样的设计中不存在实体类这样的东西,dto更加是一个极端的贫血domain model,有了dto倒是会导致并行是dto不够用,或多或少等问题,domain model相反这方面问题到少.

采用dto并不是不可,只是增加这一层,在一个没有remote call的情况下,带来的隔离变化等好处都很有限,相反编码量增加和dto增加更为可怕.

至于你举的几个例子,纯粹是设计思路不同,因为在我看来customer.getStatus()这样的设计一点问题都没有.哪怕这个status得来得更复杂也不会有影响,只不过在实现的时候随机应变罢了.
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics