论坛首页 Java企业应用论坛

开贴再论为何DTO在大型架构里是必须的。

浏览 15219 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-12-03  
引用

如果你真的遇到过这个问题,给俺讲讲吧 

的确,这样的例子不是很多。但是,这样的例子还是有的。不妨看个通用的例子:

两个对象平面:
1、房子;
2、房子里的东西,各个东西之间没有关系;

业务需求:列出各个房子的东西备选。

这里我们有两种实现方式:
1、建立房子和里面东西的静态关系,根据房子ID分别自动load各个内部的东西,然后你在业务逻辑的某个地方重塑成一个界面可理解的对象并实现和界面的绑定。
2、采用DTO,直接load,直接绑定。房子和里面的东西关系可选。

当然,也许这个例子不是很恰当。其实我更想表达的意思是:
如果你的系统拥有最优秀的领域专家,最好的建模师。你实现了系统最完美的建模,那么用持久对象及其关系可以解决98%以上的业务问题。当然没有任何问题。
但是如果你的Team做不到这一点,同时还要整合大量的遗留系统。系统的模型总是处于演进过程中,你就会发觉纯的依靠持久对象的关系来透晰业务逻辑就是一场恶梦了。

btw:我非常喜欢微软的“精英团队”模式,但是现实中,国内的IT公司往往是做不到的。
0 请登录后投票
   发表时间:2004-12-03  
To tuskrabbit:
我觉得你使用DTO的位置不对。按照你的用法,我觉得还不如直接使用PO作为DTO,因为你虽然在上面进行了封装,但封装的的下面不是同样需要分解吗?
复杂程度并没有降低。只是转移了。

当然把PO对象直接当DTO使用也是有问题的,我不太清楚为什么这里的很多人
都有这种倾向。
看看martinflower的bliki吧。这样实现将导致"贫血的DomainModel"。

http://www.martinfowler.com/bliki/AnemicDomainModel.html
0 请登录后投票
   发表时间:2004-12-03  
对象直接有关系,不一定代表这个关系一定需要被持久化, 你可以load以后/save以前,做一些手工动作.

House h = session.load();
Items items = session.loadAll();
h.addItems(items);
return h;

客户端还是只需要使用h这个对象.这样不是足够清晰明了么?
0 请登录后投票
   发表时间:2004-12-03  
引用

我觉得你使用DTO的位置不对。按照你的用法,我觉得还不如直接使用PO作为DTO,因为你虽然在上面进行了封装,但封装的的下面不是同样需要分解吗?
复杂程度并没有降低。只是转移了。


首先,封装是统一的。分解只会做一次,而不是N次。其次,封装的结果带来各层的解耦,提高可重用度和可维护性。
引用

对象直接有关系,不一定代表这个关系一定需要被持久化, 你可以load以后/save以前,做一些手工动作.

House h = session.load();
Items items = session.loadAll();
h.addItems(items);
return h;

客户端还是只需要使用h这个对象.这样不是足够清晰明了么?

你这样把PO给到客户端,在规模非常大的系统里是不行的。这样的讨论robbin说的比较多,你可以在论坛里搜一下。
再说,不管是谁,拿到这个h都是需要取出东西来给前端显示的,这个转换工作少不了。
0 请登录后投票
   发表时间:2004-12-03  
tuskrabbit 写道

你这样把PO给到客户端,在规模非常大的系统里是不行的。这样的讨论robbin说的比较多,你可以在论坛里搜一下。

偶不管什么PO, VO, DTO这一堆O, 偶只知道Hibernate让偶们可以持久化任意的Object, 这样一个可以贯串所有层次的Domain Object, 才是最简单易用的.
如果你认为这是行不通的, 那么你一定比Hibernate的开发人员还熟悉Hibernate......你既然叫偶搜索论坛, 那么偶建议你先搜索hibernate的官方网站, 或者看看email list, 或者买一本Hibernate In Action, 不过偶可以先告诉你结论:Hibernate的开发人员推荐的做法恰恰和你做法相反.

请先查查DTO模式的目的和适用范围是什么, 系统的用户多少, 数据多少, 开发人员多少, 都不是用来判断它是否适用的范围.
0 请登录后投票
   发表时间:2004-12-03  
tuskrabbit 写道
目前我把这一层作为DTO来实现,现在业务逻辑开发人员就非常轻松了,也不用学习Hibernate了,他们看到的就是业务逻辑粒度的值对象的CRUD接口。业务逻辑的编写也变得非常轻松。系统的架构也因为层次的解耦而变得易于维护。


你的业务逻辑操作的是DTO而不是业务持久对象?这就是你的业务层?
这比贫血的DomainModel更不如因为至少贫血的DomainModel的
业务逻辑对象操作的是业务持久对象。

DomainModel不是这样的......
0 请登录后投票
   发表时间:2004-12-03  
我的观点也是慎用DTO的,我认为纯Web应用基本上不需要使用DTO。而使用DTO的场合往往是在需要分布式调用的情况下,使用Web Services。

另外我想你误会我前面的说法了,我前面曾经有一个帖子强调了很多人把Struts的FormBean和PO混用,实际上Struts的FormBean就是Struts MVC架构下Web层的DTO,我反对把DTO和PO混用,不意味着我支持DTO。只能说在Web层用DTO本来就够丑陋的了,然后再用DTO去做PO,就更加一塌糊涂。

至于争论嘛,还是拿出来具体的实例代码,否则就没有结论的。
0 请登录后投票
   发表时间:2004-12-03  
tuskrabbit 写道

如果你的系统拥有最优秀的领域专家,最好的建模师。你实现了系统最完美的建模,那么用持久对象及其关系可以解决98%以上的业务问题。当然没有任何问题。
但是如果你的Team做不到这一点,同时还要整合大量的遗留系统。系统的模型总是处于演进过程中,你就会发觉纯的依靠持久对象的关系来透晰业务逻辑就是一场恶梦了。


说到这里,我认为
首先:我认同你在项目中这样做是正确的选择,因为作为技术负责人,选择合适的技术才是最重要的,既然你的team适应这种模式,那就这么做,这很高明

此次:如果仅仅这么说,就失去了在这讨论的意义了,我想你发贴的本意也是希望从技术上讨论DTO模式的利弊,所以,不要拿团队的习惯来作为理由

最后:我看不到为什么业务需求中会出现需要无关联的对象的数据,如果有这个需要,我相这些对象之间就应该有关联,纵使没有静态关联,我们仍然可以使用编码或容器的IoC或者AOP等技术建立动态关联

这里我要说明的是:
无论是静态关联还是动态关联,它都代表着业务的诉求,如果业务上有这个需求,那这些对象就应该有关联,如果在业务中从领域层获得数据时发现有有业务相关的数据没有被获取,那么只能说明当初的需求或者设计的失败

另外,如果是需求发生了变化,无论采取哪种方式(DTO还是DO),有时候你都需要改动所有的层,这是不可避免,但好的架构可能使修改更方便些而已

以上是我的想法,Now, it's your turn.
0 请登录后投票
   发表时间:2004-12-03  
引用

我的观点也是慎用DTO的,我认为纯Web应用基本上不需要使用DTO。而使用DTO的场合往往是在需要分布式调用的情况下,使用Web Services。

robbin,不太同意你的这个观点。除非是中小规模的应用。对于千万以上级别的系统,比如电信、银行。没有分布式是不可想象的。Cluster更是必须。在这样的应用里,你不用DTO,那用什么来传递分布式数据?
引用

首先:我认同你在项目中这样做是正确的选择,因为作为技术负责人,选择合适的技术才是最重要的,既然你的team适应这种模式,那就这么做,这很高明

此次:如果仅仅这么说,就失去了在这讨论的意义了,我想你发贴的本意也是希望从技术上讨论DTO模式的利弊,所以,不要拿团队的习惯来作为理由

理论往往来自实践,作为我一个产品里的设计模式。我想把它抽取出来,还是有很多共性的东西。DTO不是万能的,但是起码在大规模、分布式系统里。你很难找到比它更有效的模式。
下面是一个简单的值对象和持久对象映射的配置:
<vopo-mapping>
	<vo class="org.sunny.vo.CustsInfoVO">
		<po name="CustBasePO" class="org.sunny.po.CustBasePO" table="t_ptcl_custinfo">
			<property name="custid"/>
			<property name="custname"/>
			<one-to-many voproperty="custid" poproperty="custid"/>
		</po>
		<po name="CustGroupPO" class="org.sunny.po.CustGroupPO" table="t_ptcl_groupinfo">
			<property name="custid"/>
			<property name="groupid"/>
		</po>				
		<relationid name="custid" property="custid"/>
	</vo>
	<vo class="org.sunny.vo.UserInfoVO">
		<po name="UesrInfoPO" class="org.sunny.po.UserInfoPO"/>
	</vo>	
</vopo-mapping>

这个配置是非常简单的。但足以说明其必要性。
引用

你的业务逻辑操作的是DTO而不是业务持久对象?这就是你的业务层?
这比贫血的DomainModel更不如因为至少贫血的DomainModel的
业务逻辑对象操作的是业务持久对象。


业务逻辑操作值对象有什么不好?这样的值对象和持久对象的区别就在于值对象通常来讲是平面化的。而持久对象是树状结构。呵呵,也许你误会了,值对象不是我的领域模型。在各个观点上,我想没有什么可争论的:领域模型在于持久对象里。

持久对象可以非常好的描述领域模型,Hibernate也可以很容易的load一颗对象树。但是具体业务上,你是不会把一颗对象树直接送到前端的,对不?因为太多信息是冗余或者没有用的。这种情形下,你怎么办?自己把要用的数据从对象树里提取出来!!这个工作你写在业务逻辑代码里。和我通过配置来描述有何差别??
0 请登录后投票
   发表时间:2004-12-03  
引用
robbin,不太同意你的这个观点。除非是中小规模的应用。对于千万以上级别的系统,比如电信、银行。没有分布式是不可想象的。Cluster更是必须。在这样的应用里,你不用DTO,那用什么来传递分布式数据?


都讲过n次了,分布式是分布式,集群是集群,两者是不同的。集群和DTO可没有什么关系,我没有DTO照样集群,没有任何区别。

至于分布式,请你先举个具体的实例来说明分布式的必要性,特别是在电信,银行的J2EE 纯Web应用中分布式的必要性

引用
持久对象可以非常好的描述领域模型,Hibernate也可以很容易的load一颗对象树。但是具体业务上,你是不会把一颗对象树直接送到前端的,对不?因为太多信息是冗余或者没有用的。这种情形下,你怎么办?自己把要用的数据从对象树里提取出来!!这个工作你写在业务逻辑代码里。和我通过配置来描述有何差别??


我干吗要送整颗树?我需要哪个,我就拿哪个呗!你所谓的“从对象树中提取”实际上就是 po.get(...).get(...),我没有看出来调用几次POJO的get方法有何不妥? 而本来简单的直接调用对象的get方法就可以搞定的事情,被你弄了那么多事情出来,这就是差别。
0 请登录后投票
论坛首页 Java企业应用版

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