该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-04-23
最后修改:2011-04-23
VO(DTO)模式在分层架构设计中是否需要的扯淡
Peter Wei
引子: 前两天,在内部讨论中。公司有一开发人员向我抛出问题:我们Web层和App应用层用DTO(VO)对象,没有直接用PO,你有什么好的建议?我自然知道他说这句话的意思,PO到DTO(VO)的不停转换,太麻烦,增加太多工作量了。因为我是负责系统架构的,他是想让我向上面CTO反映取消掉DTO对象。但现有的架构是原先就有的,而且在一定程度上,我也认为需要用DTO对象。所以最终没有全部取消。 概念扫盲 我们现在大多数的应用,我想都是基于分层架构的: Web层(Struts2 or SpringMVC等)App应用层(Service)Dao层(ORM)DB PO:也就是一般概念上的Domain Object,如hibernate 中的Entity.一般用于Service层--Dao层间的数据传输。 DTO(VO):也就是一般意义上的VO,封装后的对象。一般用于Web层—Service层间的数据传输入。 VO(DTO) VS PO 引子中开发人员是想用PO透传所有层。也就是共用PO,然后取消掉DTO。 1.PO透传的代码示例: 比如有一个Order的hibernate entity. 我们假设Order下还有Account等好几个对象和集合。 public class OrderAction{ private Order order=new Order(); private List<Order> orderList public String add(){ orderService.add(order); return xx; } public String query(){ orderList=orderService.find(Object param); return xx; } } public class OrderService{ public void add(Order){ orderDao.saveOrUpdate(Order o); } public List find(Object param){ return orderDao.find(Object param); } } 2.用VO(DTO)模式的代码示例: public class OrderService{ public void add(OrderVO vo){ Order order=new Order(); Account account=new Account(); account.setXX(vo.getXX); //一堆XX order.setAccount(account); //又一堆XX orderDao.saveOrUpdate(Order); } public List<OrderVO> find(Object param){ List list=orderDao.find(Object param){ for(xxxx){ //集合下的集合 //更多的XX转换 setXX setXX } } } } PO的透传的优点一目了然,就是不用进行大量的数据对象转换,极大的减少开发人员的工作量。而且大多数PO和VO是重合的,属性什么都一样。我们知道虽然有BeanUtils等工具进行自动转换,但依然很繁琐。 BeanUtils.copyProperties(desc,src); 为什么用VO(DTO) 我在以前的工作过程中做过各种企业应用还有网站应用。大多数的项目,我们都用的是PO透传View,Action,Service,Dao层。但有两个项目中没用。 1.一个是联通的某OSS系统,该系统的基本技术架构是这样的: Flex(Web层)BladeDSBusiness Facade(DTO)Service(Spring)Dao(hibernate) 我们一眼看出这是一个分布式的系统。也就是Flex和Java应用通迅的异构系统。在Flex和Java应用之间用DTO模式结合外观Facde模式就顺理成章,水道渠成了。为什么呢?因为两个进程间的通迅,复杂层级的Hibernate Domain Object不好直接传到Flex端,因为是用remote协议传输。Hibernate的lazy特性以及序列化都是个问题。所以加一个外观层进行PO到DTO的传输就很有必要了。 2.一个是一个电子商务网站,网站的基本技术架构是这样的: 有两部分,一部分是内部管理核心系统: Flex应用Hessian Remote协议App Service(Sring)Dao(hibernate) 另一部分是电子商务系统,也就是对外的部分 Web应用(Jstl,jsp,SpringMVC)Hessian Remote协议 App Service(Sring)Dao(hibernate) 其中Flex应用单独部署一个工程,Web应用单独部署一个工程,App Service和Dao又部署一个工程。Flex和web应用都是单独通过hessian协议访问App应用。 我们来总结一下为什么要用DTO: 1. JavaEE各层之间解耦,这是从设计角度来说的。也就是说Domain Object(PO)直接封死在Dao层。高内聚,低耦合是我们追求的一个目标。但由于在一般的应用中大量的PO,VO转换,增加了工作量,也有些人说是过度设计。 2. 隔离变化。当在一些大型的应用场景以及Domain经常变化的系统里,View层可以只关注DTO对象,不用关心Domain层PO对象,如hibernate entity的不断变化。 3. 利于发挥个人技术特长,特别是按层来分工开发的团队。如有人专注于Web层,只做SpringMVC和界面这部分。还有人专门做Spring和Hibernate部分。两组的开发人员定义好接口数据就行,也就是DTO(VO)。我们当时做的电子商务网站就是这样的。 4. 当系统发展大后,扩展成各种前端界面后,可以有效隔离核心应用层。如又有web界面,又有swing的cs界面,又有手机客户端。 5. 当分层部署时,也就是Web层(jsp,Struts2)和App层(Spring,dao)在不同机器上时,用Remote协议通迅,DTO是必需的。如处理hibernate lazy load和序列化等问题。在电子商务应用中分层部署的主要好处是减少各层负载量,提高性能。 6. 在一些特定场景,如需要防火墙的地方,需要把核心数据层(Service,Dao,DB)放在防火墙内。 小结 综合以上所述,我认为VO(DTO)模式还是必需的,特别是考虑到以后扩展性的问题。但是在我们的团队中为了开发进度和避免对以前开发的功能影响,没有强制要求在Action和Service层间一定用DTO.但是新开发的功能模块要求用DTO模式,算是一种折中吧。以后系统大了之后再重构好了。要不然以后怎么有事做呢?哈哈。而且boss有时间压力在那。毕竟现在还没打算分层部署,够用就行,先不过度设计了。 其它牛人的一些观点: 参考:Martin Fowler的POEAA(企业应用架构模式)中分布式模式中的Remote Facade模式和DTO模式。 Rod Johnson在J2EE without ejb中是反对用DTO的。 欢迎拍砖,谢绝漫骂! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-04-23
感觉DTO价值不在分层架构而在b-s间能大幅减少传输负载和浏览器端的内存损耗
如果是s测的分布式,价值大打折扣 如果DTO起抽象msg作用,那既不能替代别人也不应该被别人替代 |
|
返回顶楼 | |
发表时间:2011-04-24
如果web层和service层分离的话,那么service之间的调用是远程方式还是本地方式?
|
|
返回顶楼 | |
发表时间:2011-04-24
开发网站就用网站的技术。。。别把JAVA EE的搞进来。你追不上那帮搞PHP的。。追不上那帮搞RAILS的。。。追不上就==死掉
|
|
返回顶楼 | |
发表时间:2011-04-24
最后修改:2011-04-24
我做企业应用的,以前也听某某、某某谈论dto、vo、po甚至其他oo。
yangyiqian 写道
首先我想说“存在就是真理”,DTO、PO绝对不是一个范畴的概念,DTO!=PO,所以也就谈不上谁代替谁的概念。当然了,你非要说老板就不能做员工的话吗?当然可以,不过这是做事的规矩吗?!
一、DTO与PO的不对称关系决定了二者不能互相代替 DTO与PO存在在映射关系,可能是多对一,也可能是一对多,最特殊的关系就是上面大家说的这种情况“一对一”。也就是在“一对一”的情况下可以实现DTO与PO的混用,而其他情况下,如果混用都需要PO进行冗余设计,考虑这些冗余设计会比直接的、简单的造一个新的DTO出现要耗费更多的脑细胞,同时这个东西又不利于后期维护,可以说“牵一发,动从上到下”。 二、性能上决定了PO代替DTO是个蹩脚的设计 PO是与数据库直接交互的对象,比如我要在页面上显示数据库中的数据,如果用PO来实现那么这个PO就得一直保持与数据库的连接,直到数据显示到页面上来。这样如果在service层有复杂运算的话,那么数据库方面的延时是非常可观的,而如果转换成DTO之后,数据库连接就可以尽快释放。所以从性能上来说应该使用DTO--当然对于性能不是很苛刻的情况下不用DTO也行 --不过,熟练的程序员应该养成按统一的方式做项目的习惯,我觉得这样会更高效。
最佳实践: 软件是发展的,我只认设计中的bean,如果bean要持久化就有po的职责了,一切都只是手段而已
难道是ORM把我们绑架了!太在意po和dto这样的概念了,设计才是根本,满足设计的bean才是核心。
就正如时刻要记住的技术是为了实现业务需求而用,很多人反过来用了,为了技术而技术,被技术忽悠。最简单、是人就可以看懂的实现才是好实现
|
|
返回顶楼 | |
发表时间:2011-04-24
个人也觉得DTO都低用不用还是根据实际情况来,有时候不需要分布,就是一个小应用,多余的DTO只会带来复杂度。你给的几个案例但是用着DTO蛮合适的。没有绝对的哈,知道有这么个架构思想,剩下来一切从需求出发吧
|
|
返回顶楼 | |
发表时间:2011-04-24
最后修改:2011-04-24
首先我想说“存在就是真理”,DTO、PO绝对不是一个范畴的概念,DTO!=PO,所以也就谈不上谁代替谁的概念。当然了,你非要说老板就不能做员工的话吗?当然可以,不过这是做事的规矩吗?!
一、DTO与PO的不对称关系决定了二者不能互相代替 DTO与PO存在在映射关系,可能是多对一,也可能是一对多,最特殊的关系就是上面大家说的这种情况“一对一”。也就是在“一对一”的情况下可以实现DTO与PO的混用,而其他情况下,如果混用都需要PO进行冗余设计,考虑这些冗余设计会比直接的、简单的造一个新的DTO出现要耗费更多的脑细胞,同时这个东西又不利于后期维护,可以说“牵一发,动从上到下”。 二、性能上决定了PO代替DTO是个蹩脚的设计 PO是与数据库直接交互的对象,比如我要在页面上显示数据库中的数据,如果用PO来实现那么这个PO就得一直保持与数据库的连接,直到数据显示到页面上来。这样如果在service层有复杂运算的话,那么数据库方面的延时是非常可观的,而如果转换成DTO之后,数据库连接就可以尽快释放。所以从性能上来说应该使用DTO--当然对于性能不是很苛刻的情况下不用DTO也行 --不过,熟练的程序员应该养成按统一的方式做项目的习惯,我觉得这样会更高效。 |
|
返回顶楼 | |
发表时间:2011-04-24
最后修改:2011-04-24
既然是用了hibernate,还有种替代dto的办法,使用select new map()..
|
|
返回顶楼 | |
发表时间:2011-04-24
ppgunjack 写道 感觉DTO价值不在分层架构而在b-s间能大幅减少传输负载和浏览器端的内存损耗
说的有道理,正是如此。。 |
|
返回顶楼 | |
发表时间:2011-04-24
扫盲者没有说清楚DTO和PO的职责,其他人也没有说到点子上。
|
|
返回顶楼 | |