作者 内容
 zengdou  关于业务逻辑与数据库分离的问题。
 

在面向对象的设计时,不可避免的要涉及到对象的持久化问题。由于目前关系型数据库的流行及SQL语言的强大功能,一般都以关系型数据库存储要持久化的对象。

但一般认为数据库是实现细节,应该和业务逻辑对象分离,以保持业务对象的可复用性及可扩展性。为了业务逻辑与数据库分离,比较常见的推荐的做法是使用Proxy模式。

举个例子如下:

有一个订单类Order,它包含一些订单项Item。象这样的对象的持久化问题大家都非常熟悉了。就是有个ORDER的表来存储ORDER对象,这个表有个ORDERID关键字用来唯一标识每个Order对象。还有一个表ITEM用来存储订单项,每个ITEM通过ORDERID同ORDER表关联。

假设使用PROXY模式分离Order的业务逻辑与数据库的做法是:Order分成3部分。第一部分是一个接口order,其中包括客户要调用的所有方法。第二部分是一个类orderimp,它从接口继承,它在不涉及数据库的情况下实现接口中的所有方法,第三部分是一个知晓数据库的代理类orderproxy。它也从接口继承.

比如现在我要计算某订单的总金额。ORDER接口有个TOTAL方法来实现这个业务问题。PROXY的工作原理是,客户使用调用ORDER接口的TOTAL方法。orderproxy从ORDER表中取出ORDER对象,然后从ITEM表中取出该订单的所有订单项并加到ORDER对象中。然后调用ORDER对象的TOTAL方法。

这样做的好处是。数据库完全不参与业务逻辑,实现了业务逻辑与数据库分离。但我认为这样做的代价是比较大的,特别是订单项比较多并且业务逻辑非常复杂的情况下。从数据库中取出数据组合成对象,然后通过对象完成功能不但增加了实现的复杂性并且效率也是个问题。如果直接用SQL语句完成,虽然偶合了业务逻辑,但简单直接,而且效率比较高, 其实上边的问题直接用SQL语句“select sum(item.price*item.quantity) from item where orderid= n " 不是更好么?

大家对这个问题怎么看?

 04/07/13 10:40 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 mazelin   回复: 关于业务逻辑与数据库分离的问题。
 

既然业务逻辑复杂了,用SQL实现不就更会难以理解了。复杂度也会上升。如果系统真的对效率有严格要求的话,也不一定在这里去优化性能。我个人认为,像楼主说的这样的应用,一般的性能瓶颈是在网络连接,数据库连接上,而不是在业务处理这一块,这样的话,相反,楼上的方法,会增加数据库的负担,性能反而不好。

 04/07/13 12:33 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/14 10:31 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/14 12:39 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/14 15:43 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/15 12:38 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

怎么没人关注呀?

 04/07/16 09:55 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  为什么没有人讨论呢?
 

为什么没有人讨论呢?

 04/07/17 12:32 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 sinohong   proxy在此是多此一举
 

不知道你的proxy具体的实现方式,就叫proxy吧。

现在,你在imp类中已经实现了所有的业务逻辑接口,那么就没有必要再用“proxy”再实现一次接口。现在需要的就是访问数据库的对象,就叫DAO好了。

你只需要实现一个DAO,DAO访问数据库,进行所有的数据库操作。你可以直接在DAO里采用任何SQL语句访问数据库,然后返回数据,可以是基本类型的数据,也可以是具体的业务逻辑数据对象,还可以使结果集,不过,结果集只在极少数情况下采用。

 04/07/17 13:35 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 mooniscrazy  回复: 关于业务逻辑与数据库分离的问题。
 

关于所谓的业务逻辑和数据库分离,其实是个骗局。真正意义上的分离,就是一个面向对象的数据库。如果那么容易,面向对象的数据库早就流行起来了。

 04/07/17 20:53 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

大家说得很好呀,继续呀!

 04/07/19 12:39 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  大家说得很好呀,继续呀!
 

大家说得很好呀,继续呀!

 04/07/19 16:11 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 dongcheng36   回复: 关于业务逻辑与数据库分离的问题。
 

本人认为将业务逻辑与数据库分离没有任何意义,只能增加系统的复杂度,对系统重用一点好处都没有!

 04/07/19 18:41 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 orientphoebus   看你是要做简单的系统还是复杂的系统
 

如果是一个小系统, 根本没必要这么复杂地进行de-coherent, 但是对于企业级的系统, 逻辑分离还是有其必要性的。 但是就算如此, 也有一个程度的问题,

楼主提到的proxy,算是偏复杂的一种解决方案, 其好处是如果计算total的算法不是简单的求和,比如银行风险计算, 有的甚至复杂到矢量运算或者泰勒展开,那么使用OrderImpl实现算法,并且把它和数据库脱钩,这样保证了scalability and reusability(假如有一些item及其价格不是从DB得到,而是从其他模块传来), 当然会相应降低系统整体的performance。但是在OOA/D和Distrubuted Computing的情况下,有connection pooling 和 object pooling的协助,这些performance 的降低相对scalability & reusability方面的改善是可接受的。

直接用SQL,看起来简单且易于维护, 但是假如order的种类和复杂度增加,scalability,reusability都会有问题, 随之而来的maintainability也会降低。如果你的系统中order的情况比较简单,你直接实现一个order 类,其中包含一个total()方法,而且直接调用一个用sun的SQL,当然是可以的。

moon提到的DAO是比较常用的一种折衷方案,把算法实现和接口分开,但是在实现上直接读取数据库。 这样order种类不同可以有不同的算法, 但是假设所有用于计算的数据均来自DB,这种假设在大多情况下是正确的。所以实际上这种方法是被最广泛使用的。而且这种方法的CODE比较清晰,维护性 & performance也不错。

所以,虽然软件设计是西方的东西,但是归根结底还是咱们古老的中庸之道。极端的解决方案只有在有极端需求的情况下才需要。

企业级的软件设计,不是只看performance 或者 functionalities, 而是performance, reusability, scalability, maintainability 以及功能需求(functionality/requirements)的一个平衡,面对不同情况,平衡点也不同, 这个平衡点就是中庸。

 04/07/19 22:51 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 orientphoebus  另外,单说performance,proxy也未必比直接SQL差
 

站在系统提供的一个系列操作的角度,而不是站在功能模块提供一个方法的角度来看performance:

用户通过系统浏览order信息, 或者前面tier或其他系统的其他模块通过这个模块获得order 信息,一般不会单独只要计算total, 而是:
1. 查看order的总计信息的同时,另外一个栏目现实order关联的item信息
2. 先显示order的ID,名字等基本信息, 点击链接后,第二个屏幕要显示具体的item信息,在最后显示价格总和。就算在第一屏需要显示价格总和,用户也很有可能需要察看具体的item信息。

在这两种情况下,item具体信息反正是要从数据库中读出来的,那么不如价格总和也在middle-tier计算,不用再麻烦数据库了。这样用户浏览整个order信息的时间理论上说还快一些。

但是,如果这个价格总和算法很复杂,而且结果需要经常被引用,同时引用无法被控制在一个用户登录的session内,那么这个计算total的方法的performance就是一个要考虑的因素了,常用的办法是在order表中加一个字段:total amount, 这种字段叫做derived column/property. 每次一有item变化就cascade到这个字段。这样虽然增加了做update时的开销,但是通常情形下, update相对于query并不是很经常使用或者performance critical的操作。这样也增加了系统的复杂度,并且难以维护,但是performance和maintainability本质上就是经常性的矛盾。 自己根据中庸之道来判断啦。
 

 04/07/20 02:45 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

首先,分离的优点是逻辑清晰,这是无可否认的。
其次,在业务逻辑类中包含SQL语句不适合程序扩展(比如换数据库),不适合分工合作(你不能保证每个团队成员都懂SQL)

但这样做却影响的程序的效率,增加了实现的复杂性!
这样做值得么?
有更好的方法么?

 04/07/21 08:46 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/21 16:01 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  1。你在未来更换数据库(SQLSVERER换到ORACLE? or change db design?)的可能性有多大?
 

“你不能保证每个团队成员都懂SQL”
2。不会最难的部分就是SQL吧?

3。在你的项目中,分离策略会对效率的影响有多大,是否是你不能承受的?

4。总存在一个最优设计,不清楚你的具体问题,不然我可以帮你设计设计,但需要收点费用。

(欢迎访问smilemac.blogbus.com)

 04/07/21 16:40 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 orientphoebus   “你不能保证每个团队成员都懂SQL”其实这种情况我真的遇到哦。
 



以前一个同事,做J2EE项目,title是 senior developer, 俺做了一个小辅助程序,结果存在数据库中,给他一个sql语句模板查询结果,一般的select语句, 复杂度只是加了一个multi-column 的 group by 以及一些option的order by, 相应参数要更具他自己的需要变一变。

他说,他不是DB人员,没有必要懂得SQL. BTW, j2ee的CMP的SQL没有这些group by, order by, 所以他可以在不懂得SQL的情况下干活。

最后发现, 他是我浙大的,还是同一个系的师兄,电子系的。只是半路出家到软件,直接进入J2EE。

 04/07/21 21:11 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 orientphoebus  “有更好的方法么?”有, 但是相对的,不是绝对的。
 

正如smilemac说的, 针对你的具体项目,总有一个最优的方案,这个方案就是中庸。

你要对你要做的东西很了解, 要考虑很多方面,当然不是每个方面都花相同的精力,有的问题一眼就看出来你的方案没必要去解决, 那么就跳过.

当然,做一个项目,没有人能够第一次就把所有的方面考虑清楚, 总有个学习过程, 在这个过程中,发现前面考虑不到,或者判断错误的东西就要相应地补救, 有的时候patching, 有的时候refactoring. 必要的时候对整个architecture进行refactoring. 所以还是RUP好啊.

没有广泛适用于任何项目的"更好" 或者 "最好"的方案.

 04/07/21 21:24 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  这样也能做senior developer?
 
 04/07/21 21:32 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 orientphoebus   是啊, 不过他网球打得真好, 是我们Architect的私人教练
 
 04/07/21 21:46 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 1。你在未来更换数据库(SQLSVERER换到ORACLE? or change db design?)的可能性有多大?
 

我非常想让你帮我设计,借此机会向你及大家学习!
但我想问问你的收费标准是什么?因为囊中羞涩,所以必须得先问问这个问题!

 04/07/22 08:42 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 sealw  万一他是专业开发编译器的呢?领导之道,知人善任而已.
 
 04/07/22 09:45 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  回复: 万一他是专业开发编译器的呢?领导之道,知人善任而已.
 

我不是说他不懂SQL有问题,而是他拒绝学习有问题。
一般在我的团队里,我要求根据问题来选择工具及方法,不懂就去学,不懂不能成为理由。而且对一个senior engineer来说,SQL应该是查查手册就可以用的东西,更没有理由推托不会了。

 04/07/22 10:33 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  回复: 1。你在未来更换数据库(SQLSVERER换到ORACLE? or change db design?)的可能性有多大?
 

不贵不贵,取决于问题规模和泥自己的要求
一般如下:
个人:一个图200元(文字说明加100),Q&A免费。可定制,比如说,你只要某一部分设计的类图就够了。如果要求只用文字,不用UML,那么一页纸300元(放心,不会写的很罗索,看看我以前的发言就知道了)

公司: double上面

所作设计未经本人同意,不可以公开。

比外面培训便宜多了吧,呵呵。

我的email: petrico@sina.com.cn

 04/07/22 10:42 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 看你是要做简单的系统还是复杂的系统
 
 04/07/22 12:36 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 orientphoebus   一本万利啊, 好生意, 有没有类似的生意,俺也尝尝鲜? smilemac, 不是和你抢生意,挂靠一下如何? 您吃累了分点羹给俺.
 
 04/07/22 21:28 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/27 09:37 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/27 09:37 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

?

 04/07/27 09:37 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

??

 04/07/28 11:22 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  不算好生意,已經是賠本的价了。
 
 04/07/28 18:03 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

怎么每人讨论了?

 04/07/29 12:24 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 大家说得很好呀,继续呀!
 

大家说得很好呀,继续呀!

 04/07/30 09:20 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  回复: 关于业务逻辑与数据库分离的问题。
 

没人讨论了么?

 04/08/03 15:39 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 umlzgs  有些人是太过分地考虑了
 

很多人的设计似平是把数据都用类封装起来,临时存储在类(内存)中处理,其实这不是太过返古了吗,就是直接处理变量嘛,只是处理方法不是函数,而是类方法罢了。为了跟数据库少发生关系而这样做,那还要数据库干嘛。

 04/08/04 16:48 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  ?
 

?

 04/08/06 09:38 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  大家发表发表看法呀
 

大家发表发表看法呀

 04/08/10 10:46 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  ?
 

?

 04/08/11 11:12 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 sealw   我按小时收费,从出门算起,机票住宿费用客户承担,呵呵
 
 04/08/12 09:43 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilemac  上门培训或咨询有另外的价格表,这只是远程提供设计方面的费用。
 
 04/08/12 14:01 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  ?
 

?

 04/08/13 10:41 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 littertiger  回复: 看你是要做简单的系统还是复杂的系统
 

个人认为对于一些小的逻辑单位可以做成存储过程放在dbms上,象函数库的样子,可以提高效率。
然后用proxy去调用存储过程,对外输出数据对象。proxy可能是一组类。

 04/08/13 12:39 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  大家讨论阿
 

大家讨论阿

 04/08/16 13:14 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  
 

 04/08/19 09:24 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  ?
 

?

 04/08/26 12:16 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wisewader  回复: 关于业务逻辑与数据库分离的问题。
 

使用业务模型建模完全与数据库实现分离。在我们的java项目中,利用JDO(JavaDataObject)完全实现了按照模型对象来访问数据,很方便。

 04/08/29 15:21 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 zengdou  大家继续讨论呀
 

大家继续讨论呀

 04/09/03 15:13 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首