ValueObject和DTO模式的一些疑问

cats_tiger http://www.jdon.com Nov 11, 2005 9:49 AM

ValueObject和DTO模式是常用的J2EE设计模式,模式所体现的不仅仅是一个设计技巧,更主要的是数据封装的思想。最近我在做设计的时候却对这个模式产生了一些疑问。
1. 对于位于持久层中的ValueObject,我是否应该限制他们的使用范围?以Hiberante为例,由于ValueObject的生命周期的特性,我们不能把他们当作DTO在层间传递。但是,如果使用BeanUtils等工具复制一个的话,却总是感觉有些浪费内存。如果是EntityBean则没有这些疑问——很显然我不能把EJB Bean实例当作DTO在层间传递——浪费就浪费吧。
2. 表现层的表单也需要对象封装,在Struts中就是FormBean,但是在JSF中却没有这样的概念,这样一不小心我们就容易在表现层直接使用model中的对象,这也是不合理的。
3. Business层需要处理从表现层传入的数据对象,这个数据对象也不能是FormBean或其他表现层VO,因为往往这些表现层VO直接反映的是表单数据,例如一个String格式的日期或者confirmedPassword,前者需要转化为Date类型而后者则在Business层用不到,这些处理也应该在表现层处理(?)。
4. DAO层接收Business层的数据,这个数据应是Business层对表现层数据的处理结果。
这样一来,我们在处理一个case的时候就出现了3个ValueObject:
 一个是表现层的用于反映页面数据。
 一个是Business层的,用于作为表现层和Business之间的DTO。
 另一个是Domain&DAO层的,用于持久化的ValueObject。
这真是浪费呀!
我的疑问是,我是否可以省略其中的一个或多个?还是根据不同情况和需求灵活处理,各位大虾是如何做的?


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 10:11 AM
回复此消息回复
发表人: 鲁中正气    发表文章: 50 / 注册时间: 2005-06
我一般是用一个来传递的,我主要是觉得封装太麻烦,包来拆去的。
你可以参考一下我以前的一篇贴子,好像是jsp 传2维数组。
这样做的缺点就是和面向对象的思想有些脱离,及每个对象,对业务的反映能力不强。
其实,这也是架构时常用的一种"模糊"技巧。只有模糊了,才能既是a 也是b,才能重用。具体实现中,我的手段主要是,接口,参数,弹性域,当然向上还有框架。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 10:28 AM
回复此消息回复
发表人: banq    发表文章: 6233 / 来  自: 上海 / 注册时间: 2002-08
DTO模式就是ValueObject模式,DTO是后来更名的,这在TSS首页的EJB模式或SUN的J2EE核心模式中有过说明。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 10:36 AM
回复此消息回复
发表人: cats_tiger    发表文章: 178 / 注册时间: 2003-05
>DTO模式就是ValueObject模式,DTO是后来更名的,这在TSS首页的EJB模式或SUN的J2EE核心模式中有过说明。
这些说明也不一定准确,值对象模式主要考虑的是数据封装,而数据传送对象则考虑数据层间传递的方法,二者虽然外表相同,但是考虑问题的角度却不同。例如在同一个层中,就没有DTO之说了。
但是这些区别并不重要,我的问题是DTO在不同层的属性是不同的,尤其是在以Hibernate为核心的DAO层,VO和PO是不能作为DTO使用的(?)。而表现层的Form数据和业务层所需要的数据也不同。对于一个UseCase而言,是否需要为每一个层都建立一个数据对象呢?

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 10:46 AM
回复此消息回复
发表人: 鲁中正气    发表文章: 50 / 注册时间: 2005-06
〉DTO在不同层的属性是不同的

DTO应该主要是指相邻层的层间传递的,因此只要把相邻的两层间的问题设计好了就行,至于,不同层的属性不同,那不应该属于DTO的问题。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:05 AM
回复此消息回复
发表人: cats_tiger    发表文章: 178 / 注册时间: 2003-05
是呀,我也觉得不属于DTO的问题,应该是“关于”DTO的问题吧。但是,我就是想知道,是否各个层都需要各自的DTO。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:14 AM
回复此消息回复
发表人: yuxie    发表文章: 50 / 注册时间: 2004-11
> 是呀,我也觉得不属于DTO的问题,应该是“关于”DTO的问题
> 但是,我就是想知道,是否各个层都需要各自的DTO。

8需要。hibernat持久层和业务层虽然用不同的object,但是是同样的domain model,完全不用担心new object()的开销,和持久层的远程调用比起来,这点耗费可以忽略不计
另外,我认为大部分的domain model完全可以传到展现层,使用FormBean有时候反而会造成混乱

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:23 AM
回复此消息回复
发表人: banq    发表文章: 6233 / 来  自: 上海 / 注册时间: 2002-08
>domain model完全可以传到展现层,使用FormBean有时候反而会造成混乱

非常正确,在我的Jdon框架里,我推荐FormBean是Model的完全拷贝,除非你在界面有一些只与界面相关的小功能,可以增加FormBean的一些字段。有的系统使用FormBean中调用Model(就是Model是FormBean的字段变量)的做法(如IBatis JPetstore),这实际将两者变成了一种调用关系,一旦成为关系,就打开潘多拉盒子,变得复杂或者混乱,我不喜欢这样使用。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:58 AM
回复此消息回复
发表人: cats_tiger    发表文章: 178 / 注册时间: 2003-05
>domain model完全可以传到展现层,使用FormBean有时候反而会造成混乱
这在使用DTO + EntityBean + DTO Assembler的情况下没有问题,因为DTO和EntityBean是游离的。DTO在传送过程中发生的变化不会影响EntityBean。这也算EntityBean的优点吧——强迫你使用DTO。
但是,对于使用Hibernate的轻量级DAO层来说却容易引发问题,因为你不能保证“那个坐在角落里的实习生”也和你一样注意实体的状态,一旦处于PO状态的实体被传送到其他层,那么就有可能对数据产生意想不到的破坏。所以好的方法是仍然使用DTOAssembler模式,其作用就是产生一个新的Object,其内容与Model层的内容相同,但是他的数据不会被持久化,它是完全的DTO。原来这是一个非常麻烦的工作,因为你需要写很多set/get,现在可以使用BeanUtil就方便多了。
在Hibernate的情况下,DTOAssembler其实相当于DAO层和Business层的解耦器。

现在明白了一些,对于“Model类”而言,持久层和Business都可以使用Domain中的“类”,而不必分开,正如banq所言,以model为中心。

那么表现层呢,你可以把Model中一个String类型的字段对应一个Text表单,但是其他类型呢?yuxie说“大部分的domain model”,这个大部分“大”到什么程度是很重要的。有没有更好的解决方法呢?

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:04 AM
回复此消息回复
发表人: banq    发表文章: 6233 / 来  自: 上海 / 注册时间: 2002-08
我觉得你的问题提到点子上了,持久层和界面层从两边向中间拱,甚至每个层建立一个数据对象,最后导致中间层混乱,整个系统反而变得难以维护,这是目前一些J2EE系统的通病,正是这种现象使得干净清爽的naked Object域对象模型受到欢迎。如下图,左图是现在混乱的J2EE多层系统,右图使用Naked Object的后的模型


实际上,不一定所有的系统都一定要使用Naked Object,而且Naked Object导致耦合性高,目前实验只适合在Swing界面端,在服务器端成功案例还没有出现。

这给我们一个启示,我们做一个J2EE系统时,一开始必须从中间层Domain Model开始,这就是域模型驱动,而不是被具体技术牵着鼻子走,各个层技术就象小孩子一样,闹腾厉害,如果你给他们每个人分一个果果(做一个数据模型),那么你整合起来时很难,所以,你必须只给他们一个Domain Model果果,以此设计为中心,再加入其他辅助对象,与Domain Model建立对象关联(通过类图实现的四种类关系),而各个技术都是围绕类图的类各自完成自己功能。

理清这个思路,从中间组件层入手,就能顺藤摸瓜,问题迎刃而解,这也是为什么组件层(有些人说是构件)如此重要,为什么要面向组件(面向构件)编程的重要性,为什么EJB和Spring等等吵得不可开交等原因。

实际上,也是我提出为什么域建模 模式 和框架如此重要的原因,使用UML依靠usecase设计出类图、用模式实现类图、使用框架(表现层 组件层 持久层框架)来进行代码级别实现,最终完成一个高质量的J2EE系统。

 


 

 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:49 AM
回复此消息回复
发表人: dabb    发表文章: 236 / 注册时间: 2004-04
你也太死板了吧,完全被pattern给套死了。在一般的应用中persistent object传导表现层又如何?何必再来个copy的无用功?即使用hibernate,在一个层次划分比较明显的系统里,难道view层的开发人员能够获取到hibernate的session从而修改你的逻辑吗?至于formbean,对于我来说只是利用到validation比较结构清晰,否则的话我宁愿request.getparameter来的直接。一般来说在business layer设计好接口后,都是按照business的接口需要来取request的数据,何必把business layer的设计邦定到formbean的设计上呢

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 11:53 AM
回复此消息回复
发表人: banq    发表文章: 6233 / 来  自: 上海 / 注册时间: 2002-08
哈哈 dabb好久不见了,很高兴看到你,我担心persistent object直接传到presentation layer,会造成这两个层耦合,这样,在这两者之间插一个第三者Model,就断了他们藕断丝连的想头了。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 2:15 PM
回复此消息回复
发表人: cats_tiger    发表文章: 178 / 注册时间: 2003-05
>会造成这两个层耦合
不仅如此,直接在表现层修改Persistence层的数据的危险性还在于:破坏了Domain的独立性。DomainModel的实例s构成了逻辑上Domain层,它相当于数据库在内存中的映射,在使用ORM的情况下更是如此。
在表现层修改Persistence层的数据相当于破坏了这种映射,其后果是十分严重的。
例如,表现层代码user.setUsername("CatsTiger");
看上去没有问题,但是如果User对象处于Persistent状态就麻烦了,等于没有经过Business层处理就保存了数据,回到C/S时代了。这有点像把EntityBean作为DTO了:(

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 12:05 PM
回复此消息回复
发表人: cats_tiger    发表文章: 178 / 注册时间: 2003-05
〉难道view层的开发人员能够获取到hibernate的session从而修改你的逻辑吗?
不是没有可能,即便如此,虽然view层的无法获得session,但是他可以任意修改persistence层的对象也是很危险的,persistence层是不会对数据进行验证的,它只会不管3721的保存数据。

我们应该确保各层之间认知程度最低。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 3:43 PM
回复此消息回复
发表人: dabb    发表文章: 236 / 注册时间: 2004-04
> 不是没有可能,即便如此,虽然view层的无法获得session,但
> 撬梢匀我庑薷膒ersistence层的对象也是很危险的,persis
> ence层是不会对数据进行验证的,它只会不管3721的保存数据
> ?>
> 我们应该确保各层之间认知程度最低。
>
我想这应该是框架 的 设计有关吧。在 open session in view的 模式下是存在 这种 危险的 。不过我一般 设计 都是 在 business layer里操作 domain model,然后把 domain model作为一个 普通 vo抛给 view去 操作 。尽管听说 open session in view有种种好处 ,但 我还是觉得我的这种方法 (tmd不知道叫什么名字 ,好像叫 open session per transaction吧)在设计上比较方便 ,当然这只是适合我们这类的项目。如果 有特殊需求 ,当别论 。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 11, 2005 4:31 PM
回复此消息回复
发表人: yuxie    发表文章: 50 / 注册时间: 2004-11
可能会流行的一种方法

将业务层返回domain model 转化为 xml 发布(比如burlap)
然后在表现层用js捕捉……

现在有个很好的国产框架bufflo可以做到~~
全新的开发体验和用户体验~~yeah~~

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 16, 2005 2:09 PM
回复此消息回复
发表人: Kyle_Yin    发表文章: 95 / 注册时间: 2005-09
呵呵

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 16, 2005 3:27 PM
回复此消息回复
发表人: Kyle_Yin    发表文章: 95 / 注册时间: 2005-09
就是。

DTO 那个东西的核心逻辑是“粗化通信粒度”,本意是为了克服 EJB1/2 的性能问题。在 ORM/EJB3 环境下,EJB2 中 ENTITY BEAN 的性能问题已经不复存在,DTO 的广泛渗透也由此成为一个不折不扣的“反模式”。

DOMAIN MODEL 既作为 ENTITY, 又作为 BUSINESS LAYER 的操作对象,本来就是 ORM/EJB3 的设计本意。非要把 EJB2 里那些补丁“模式”搬过来,

为什么好几天的记录都没了?天灾还是人祸?呵呵

> >
> 我想这应该是框架 的 设计有关吧。在 open session in
> view的 模式下是存在 这种 危险的 。不过我一般 设计
> 都是 在 business layer里操作 domain model,然后把
> domain model作为一个 普通 vo抛给 view去 操作
> 。尽管听说 open session in view有种种好处 ,但
> 我还是觉得我的这种方法 (tmd不知道叫什么名字
> ,好像叫 open session per
> transaction吧)在设计上比较方便
> ,当然这只是适合我们这类的项目。如果 有特殊需求
> ,当别论 。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 16, 2005 4:09 PM
回复此消息回复
发表人: banq    发表文章: 6233 / 来  自: 上海 / 注册时间: 2002-08
我觉得DTO模式是一种实践中的模式,它出现有很多因素,Yin认为和EJB有关,我认为更多和人们非对象化思考有关,但是DTO模式本身是中性的,用得不好成反模式,例如这个案例,

初学Hibernate的人虽然掌握了新技术的“技”,但是没有掌握新技术的“道”,这个链接中:http://www.jdon.com/jive/thread.jsp?forum=62&thread=23720

它画出数据库物理逻辑图,然后再使用Hiberante配置,也就是在O/R Mapping关系中,他不是首先定义好对象Model(也就是O),而是首先抓住数据库(是 R),就是典型的使用Hibernate本末倒置,最后导致什么结果呢?

导致我前面说,在表现层 Model组件层 数据库持久层这个多层中,因为表现层是根据需求确定不能随意更改,现在他又确定了数据库层,这类似地震原理,两个版块相挤(表现层版块和数据库版块),最后混乱地震的是表现在哪里呢?无疑是中间层,这时,只能用大量临时DTO来补救,进行前后台调和,也就是和稀泥。

这种情况下的DTO造成了系统混乱,甚至失败,但是它不是DTO模式的错误。

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 16, 2005 4:48 PM
回复此消息回复
发表人: Kyle_Yin    发表文章: 95 / 注册时间: 2005-09
无论如何,历史事实是,DTO作为模式最早出现在J2EE CORE PATTERNS, 原因就是为了克服 EJB1/2 的性能问题。在 EJB3 框架下,主要指在LOCAL ENTITY + OR MAPPING的框架下,DTO模式至少没有任何性能上的实际意义。在EJB3里用DTO,有点在C++里用 void * 的感觉。当然当年很多人就是喜欢写这个 void *“模式”的代码。

老板说说 DTO 在OR映射框架下有什么(可量化的)意义?

 


 
Re: ValueObject和DTO模式的一些疑问 发表时间: Nov 16, 2005 5:11 PM
回复此消息回复
发表人: banq    发表文章: 6233 / 来  自: 上海 / 注册时间: 2002-08
你太客气了,叫我“老版”就可以,实际是个老版主。
你的观点我是同意的:当将实体Bean 变成一个POJO,并且实体Bean必须由本地Session调用之后,DTO在性能使用上没有意义了。

作为交流,我还是说出一些我个人看法,现在我都犹豫了(说出自己想法被人认为是较劲;不说出被人认为是无科学精神,呵呵,开玩笑),我还是说说,说不定我思维有些问题呢。

我看DTO模式历史是这样的:
最早是VO也就是ValueObject, 后来,TSS那个架构师编写的"EJB模式"(至今还在TSS右边挂着呢,在EJB方面,TSS比我还死挺),将ValueObject称为DTO模式,并且还详细说明了DTO模式的几个变种,算是专业厉害了,后来J2EE Core Patterns也使用DTO替代它以前版本的VO了,当然这两者先后不重要。

一般模式使用是没有实际作用的(只是纯设计要求,不用这个模式程序照样可以跑,没什么两样),在“EJB模式”中,认为使用DTO模式可以省却客户端和EJB之间的通讯,将所有的数据或对象打包成一个对象传到EJB层,而不是一个参数一个参数的传送,每次传送都有可能涉及远程通讯和序列化,那多耗费性能啊。

后来,Hibernate出现了,提出数据的POJO,实际是VO概念,在这种情况下,VO和Domain Model可以合二为一,按照DTO模式定义:Data Transfer Object,这时Domain Model也是DTO模式实现一种,Model直接作为数据传送啊。所以,这种情况下:VO Domain Model 或DTO都是同一个东西,我觉得讨论他们区别没有意义,当该对象作为类图分析实现时,它是Domain Model;当该对象作为数据传送,它是DTO/VO。

DTO模式什么情况下不是Domain Model呢,就是我上帖举的例子,他不是从域模型驱动分析设计开发的,而是基于传统的数据库驱动设计,首先设计出数据库,再使用OR框架导出一个附属结果,这个附属结果并不是Domain Model,而是一个DTO,单纯传送数据用,这就造成了系统混乱。

不知我有无表达明白?这是我目前的想法,可能与一些权威思想不一致,也希望交流提高。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值