JiveJdon Community Forums
在线164人 J道首页 | 论坛首页 | 培训咨询 | 开源框架 | 精华 | 查搜 | 注册 | 登陆 |
首页 » 论坛 » J2EE/JavaEE/JEE/EJB/JSF等技术讨论
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表
???en_US.forumThreadNext.name??? 下一主题
这个主题共有 16 回复 / 2 页 [ 1 2 下一页 ]  发表新帖子  回复该主题贴
Monday611

发表文章: 6
注册时间: 2007年06月11日 15:42
请教开发中的分层问题,急!!! 发表: 2007年06月11日 17:04 回复
现开发的项目,
持久层:hibernate
业务层:spring
表现层:没有使用什么Struts框架,使用了本公司的一个框架,并且JSP中使用的C标签。

现在拿页面数据的保存和显示,来说一下我所要请教的问题。
一、背景环境:
(一)保存
1> 利用公司的框架,会自动把页面数据绑定到formbean(formbean中的数据对应于多个表中的数据)
2> 利用公司的框架,会执行相应的业务类,把formbean中的值分到所对应的各个PO中,并把这些PO存放到list列表中。
3> 然后调用业务服务类,把list列表中的各个PO,调用DAO的相应方法持久化。

(二)显示
1> 利用公司框架,执行相应的业务类调用DAO中相应的方法,进行数据查询。假如是通过userid查询获得用户信息,方法返回为User对象(即PO),并把此对象存在request的attribute中(以便通过页面的C标签获得)。
2> 通过C标签获得User对象的各个属性值显示在JSP页面上。

二、请教问题
公司前一个小项目的工作形式,如上面所说的保存和显示。
现感觉有点问题,请指点:
A> 数据显示:在页面显示时通过C标签直接获得PO对象,并显示其各个属性值是否合适?是否应在业务类中把查询得到的PO对象进行封装,把PO对象的数据对应封装到Formbean中,然后把此Formbean对象存在request的attribute中,最后通过C标签显示在页面上。
B> 数据保存:我现在采用的这种方式是否有问题?

现在想,无论是保存还是显示,是否都不应直接操作对应于数据库的PO?如果不应该,我是否应在业务层加入BO,查看了一些资料,感觉BO和PO没有什么区别,那我要怎么做呢?
为了使项目针对需求的改动(如表中加入一字段、页面显示格式变化等),能有更大的适应性,也就是最少的代码改动,并且只在一层做改动即可。
由于项目经验不足,所以不知如何做,请banq指点。
十分感谢!!
banq

发表文章: 8920
注册时间: 2002年08月03日 17:08
回复:请教开发中的分层问题,急!!! 发表: 2007年06月12日 09:50 回复
你这个框架可以说比数据库驱动框架要前进一步,应该说处于数据库和对象模型之间的中间道路,你的PO实际是数据库的影子,只不过以对象形式存在,必须先有数据库设计才会有PO,这实际还是数据库驱动设计思路,比较符合那些传统过程思维的人使用。对象PO还是服从于数据库,数据库设计是父母,PO对象是儿子,是这样先后关系。现在真正的OO系统应该是PO是父母,数据库才是儿子,应该倒过来。

那么问题来了,数据库做父母时,我们知道如何先创造数据库,这可以凭我们所谓的直觉和经验(还有一些号称理论的数据库建模);现在改为必须先设计对象,如何从需求中将对象找出来,这方面就需要对象建模,如本站介绍的四色图 Evans DDD

纲举目张,当你将PO作为主要纲抓起来以后,它在各层实现以及关系就自然解决,这方面实际案例可以看看基于jdonFramework的JiveJdon3
[该贴被banq于2007年06月12日 09:53修改过]
Monday611

发表文章: 6
注册时间: 2007年06月11日 15:42
回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月12日 10:56 回复
首先谢谢banq的回复,最近也一直在看你的关于领域驱动设计的文章。
现在,还是有一些不太明的的地方,请赐教:
1> 假如我现在是以对象建模的方式工作,那么我在前台是否可以获得查询所得到的Model对象?这种方式是否合适?
2> 你所提供的案例JiveJdon3 中Model会实现或是继承com.jdon.controller.model包中的接中和类,而com.jdon.controller.model下的内容是保密的,所以我不能完全理解这个思想。你能发一个小的案例给我吗,利用此思想从设计建模的图到最后的代码,不知我的要求是否过分,十分感谢。

请发到我的邮箱:huangzihua1219@163.com ,对于你的指点我不胜感激。
leadyu

发表文章: 47
注册时间: 2005年03月29日 12:53
回复:回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月12日 12:43 回复
建议增加BO层,BO和PO是具有本质区别的,前者是面向对象分析的结果产物,后者是基于数据库分析结果的产物,虽然他们的表现形式可能类似。

如果你的系统达到一定复杂程度,你就会发现BO和PO开始不一样了,BO更接近抽象层次,PO只是具体存储实现的载体,比如一个BO(抽象业务概念)可能有多种存储的设计方式,不同的方式可能导致PO设计不同,如果只是单表,那么BO和PO样子确实很类似,但是最好预留这层,否则后面系统的模型复杂时,到后面PO就和真正的抽象概念越来越远,一个相同的抽象概念,可能客户不同,需求不同造成Po设计不同,造成系统复用性减低。

当然,系统还不是特别复杂的情况下,可以考虑把PO层和BO层结合,放到一个层次,复杂的BO通过组合多个PO实现,但是概念上一定要清楚,他们有本质区别。

Monday611

发表文章: 6
注册时间: 2007年06月11日 15:42
回复:回复:回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月12日 14:01 回复
to leadyu :
谢谢你的答复,还有一些不太明白的地方,请指点。
1> 我们系统中的PO是利用MyEclipse针对数据库中的表自动生成的。
你所说的“比如一个BO(抽象业务概念)可能有多种存储的设计方式,不同的方式可能导致PO设计不同”具体是什么意思,PO难道不是和库表对应的吗?能举个更具体的例子吗?
2> “复杂的BO通过组合多个PO实现”,你能举个复杂BO的例子的源码吗?

非常感谢。
leadyu

发表文章: 47
注册时间: 2005年03月29日 12:53
回复:回复:回复:回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月13日 13:20 回复
不敢说指教了,呵呵,我只是谈谈自己的理解。

比如说我设计一个电子商务系统:其中有个很重要的概念---产品。好,那么我们看看产品模型。

需求简单的时候,产品可能我只要用一张表存放就完了,比如Product表,那么我设计了ProductPO,ProductService,ProductDAO,三个类。

这没问题,好,那么现在需求变了,更复杂一点点了,产品需要对应多个产品图片,那么就有了Pic表存放图片路径,那么就又多了PicPO,PicService,PicDAO。这时候有些业务和图片有关,有些业务和产品主表有关,和图片有关的程序就调用PicService.XXX等方法,那么从此他依赖了Pic表,PicPO。好,这个时候问题还不大,那么接下来业务又更复杂了。

不同类别的产品需要不同的参数和属性,冰箱有冰箱的参数,电视有电视的参数。那么我们又通过一种更通用的数据库设计来解决这个问题,比如属性的纵表扩展,通过把横向字段变成竖向记录来存放,达到动态配属性,那么这时候又设计了AttributeDefine表,AttributeValue表,后面发现产品图片也可以用属性的方式来实现,那么Pic表被废除,产品的存储方式已经不同了。好,下面我们看看现状。

由于PO紧密结合表设计,那么原来的其他模块已经依赖了这些PO,比如PicPO,那么现在存储结构变了,怎么办,不得已,改!变成依赖AttributeValuePO。这只是第一个问题。

好,现在一个同事做的模块需要和产品打交道,他想了解一下产品这块的业务,好,我拿出数据库模型给他,天,产品的不同字段的值还放在不同地方,Attribute表是干嘛的阿?我只要Product,能够从里面取得参数就行,你的模型里面几十张表,都干嘛的阿?那么如果是新同事来了怎么办呢?一个系统中核心业务模型其实不会太多,但是当我们拿出数百张表的数据库模型给业务分析人员时,他们怎么看。

不好理解还只是个次要问题,系统之间由于这样现状,很多模块之间不得不依赖于其他模块的一些表设计,这种表设计其实是很不稳定的,这意味什么,反而,业务模型是很稳定的,比如我做个CRM产品,到北京做项目和到广州做项目,核心模型几乎一样,但是业务流程确千变万化。

所以,系统简单的时候BO不妨就是PO,VO,但是一定要记住,BO表达的是业务概念,不是表存储,当表设计不能表达业务概念时,一定要把他们区分出来,比如我不管怎么变,产品都只有一个概念Product,里面组合了一些PO,比如AttributePO,存储时,ProductService只需要调用组合PO的DAO就可以了。

所有其他模块和产品产生依赖,我只暴露业务模型相应对象给它,他不需要了解我怎么存储实现,其实大部分时候他是不关心的,当然,除了做一些很复杂的查询时,他才关心数据库实现,ORM就在这时候体现作用了,它连查询都按照对象思路封装好了,当然,有些统计逻辑,ORM还没解决的很好。

这样还带来另一个好处就是,复用性,由于整个系统是根据业务模型设计出来的,贴近业务,所以在有些新的业务出来时,你就会发现,完全可以组合现有BO,和Service实现新的业务流程,有点类似BPM的概念。就是因为BO设计贴近业务才有这种组合的可能,比如说现在,根据不同的定价策略+产品=衍生出商品的概念,那么很多我完全可以组合产品BO,和定价BO,完成一些业务,只要Service的接口定义的粒度够细。

Monday611

发表文章: 6
注册时间: 2007年06月11日 15:42
回复:回复:回复:回复:回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月14日 15:04 回复
to leadyu :
谢谢你这么详细的讲解。
还有一点不太清楚,请你再指点一下。
假如,有两个PO:PO1和PO2,并且这两个PO各包括两个属性name和type,并且类型都为string。
现在有BO层,并且BO中是通过上面的两个PO组合成的。
1> 那么BO是直接包含这两个PO对象吗?像下面这段代码:
public class SampleBO {
private PO1 po1;
private PO2 po2;
.................
}
2> 那在 SampleBO这个BO类中,是否只应该包含属性的set,get方法。不应该包含其它的业务方法?
3> 你所说的:“Product,里面组合了一些PO,比如AttributePO,存储时,ProductService只需要调用组合PO的DAO就可以了”。
这句话,有点不太懂。请看我下面的理解是否正确:
假如,要通过ProductService 保存ProductBO中的各数据。
在业务层调用业务服务类ProductService 来完成保存,假设在ProductService 中实现保存功能的方法叫saveProductBO(ProductBO bo),(请注意方法中的参数类型),并在此方法实现中得到AttributePO,调用DAO方法,从而实现AttributePO对象的持久化。
是这样的吗?
4> 如果3> 上所说的是正确的话,那么 saveProductBO(ProductBO bo)方法中的参数是否不应该设为ProductBO 类型,而是更是更通用的类型,如在BO层建一个BaseBO,做为所有BO的父类。saveProductBO方法中也应传BaseBo类型的参数。
不知我这样考虑是否正确?






leadyu

发表文章: 47
注册时间: 2005年03月29日 12:53
re:请教开发中的分层问题,急!!! 发表: 2007年06月15日 01:25 回复
1)关于复杂的BO组合PO这点,是我表达不清楚,其实PO只是ORM才有的概念,他的生命周期也应该交给ORM框架去管理,我个人认为真的没什么必要把PO这个概念暴露给DAO层以上的层次,也不应该暴露,PO对应的是数据记录,如果在视图上修改了,等于修改数据,而且只在连接有效时才有效.业务真没必要知道有PO这个概念,DAO层返回的就是值对象,服务的就是值对象,在DAO层完成PO和VO的转换,这种转换可以通过反射自动完成,复杂的BO再通过组合值对象来实现.说实在,我设计系统的时候还真没有PO这个概念,完全是ORM做关系映射没办法下的东东。个人觉得ORM就不应该把这个概念暴露出来。


2)关于BO里面有没有业务方法,呵呵,我想jdon里面有很多比我高手多了的哥们发表过文章了,你可以看看,我个人认为,BO里面可以放那些和领域模型有关的业务方法,对于大多数业务方法还是放在Service里面,什么叫领域有关,比如体现领域对象之间关系的get方法,以及一些跟业务流程关系不大,跟领域模型关系密切,可重用的业务方法。哪怕剥离了Service单独看模型也是有意义的那些业务方法。

这并不违反OO设计,服务本身就是一种对象抽象概念,就好像,人,银行两个概念,银行为人提供存款服务,跟人有关,但人才是核心模型,不管在原始社会还是现代社会,人都是有意义的,而银行,只是现代社会环境下,对人提供服务,这就像开发系统一样,对于不同客户,有不同的业务服务,核心模型却类似,难道我们还能把存款这样的方法放到人的类里面吗?人的类里面挺多就是getHead,getBody,speak之类的和人密切相关的业务。

banq

发表文章: 8920
注册时间: 2002年08月03日 17:08
回复:re:请教开发中的分层问题,急!!! 发表: 2007年06月15日 13:36 回复
>并不违反OO设计,服务本身就是一种对象抽象概念,....难道我们还能把存款这样的方法放到人的类里面吗?人的类里面挺多就是>getHead,getBody,speak之类的和人密切相关的业务。

非常赞同楼上这段观点。服务和领域对象分离并不违反OO设计,关于MF所提的贫血模型等概念只是一种善意提醒,不能走两个极端:一是将很多非关领域对象紧密行为加入领域对象;也不能将领域对象紧密的行为完全从该对象中分离出去(使该对象变成贫血对象)。

相关话题:贫血和充血模型的比较之我见:
http://www.jdon.com/jivejdon/thread/31369.html


这其实是一个尺度拿捏问题,也就是回到对象最原始的设计问题:哪些特征是属于该对象固有基本的;哪些则不是,哪些和应用特征相关的服务性质,比如楼上举例的人存款这个动作特征,其实和具体应用有关,而不是人对象固有基本的。

对象/类定义的尺度拿捏相关话题:
http://www.jdon.com/article/31041.html


其实Evans DDD将模型对象分为实体对象 值对象和服务,已经为我们进行具体尺度拿捏提供了很多的方法依据,可以说实际做起来就比较简单了:

BO是一个实体对象,还是一个主要实体对象,比如Product应该是一个BO,而ProductPic就不能算一个BO,但是如果有一个数据表专门保持ProductPic,那么ProductPic可以认为是一个PO,但是正如楼上所说:PO这个叫法其实不是完全OO的称呼,是一个局限于持久层内部的叫法。

楼上建议PO不要暴露给业务层,这是对的,实际上,我的观点是:正因为PO是数据表驱动设计的产物,我们采取Evans DDD等对象建模,那么就没有PO这个概念了,有的都是实体对象,ProductPic可以算一个实体对象,但是它是从属于Product的,是Product的关联子对象,被包含在product中,他们之间关系是对象的1:N关联关系。


以上稍微总结了一下在Evans DDD新体系下和以前数据表驱动半对象体系下的同一个对象不同的称呼,也是综合了楼上leadyu的观点,欢迎补充更正。


区分了以上新旧概念以后,对于楼主的问题:"为了使项目针对需求的改动(如表中加入一字段、页面显示格式变化等),能有更大的适应性,也就是最少的代码改动,并且只在一层做改动即可。"

试图通过更改一层的模型对象改动达到全部改动,这一目标目前可实现,但是要借助一些MDD自动生成代码工具MDSD( Model Driven Software Development ).原理也就是更改模型对象BO后,其他各层代码自动生成,TSS最近介绍了这方面一个工具Sculptor,可生成Spring+Hibernate多层架构代码:

http://www.theserverside.com/tt/articles/article.tss?l=ProductivityWithSculptor
[该贴被banq于2007年06月15日 15:28修改过]
leadyu

发表文章: 47
注册时间: 2005年03月29日 12:53
回复:请教开发中的分层问题,急!!! 发表: 2007年06月18日 13:24 回复
同意banq老师的观点,我一直觉得,BO应该有两个层次,不过好像没有什么观点支持:

一种是实体型的,他包含的业务方法,应该是和自身关系紧密的,同时细粒度的,应该是越细越好。

第二层是应用层的,也就是我们普遍叫的Service,他也是业务对象,只不过,它不是实体模型,他针对应用,由他对外提供服务,在整个架构中,由他实现业务

在整个架构中,整合的是应用层,实体模型属于核心
banq

发表文章: 8920
注册时间: 2002年08月03日 17:08
回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月18日 16:22 回复
你的思想我认为和Evans DDD的模型思想是相近的,只不过名称有些不同。关键是注意到业务模型的区别,这点很重要。
Ericx

发表文章: 39
注册时间: 2007年04月16日 18:06
回复:回复:回复:回复:回复:回复:请教开发中的分层问题,急!!! 发表: 2007年06月20日 12:50 回复
那把所谓的poZ转化到所谓的bo如果设计深度关联 怎么 办

比如 Product 类 里有 Category类 属性
如果 返回是 List类型 如何 深度复制 ?
效率如何
banq

发表文章: 8920
注册时间: 2002年08月03日 17:08
回复:回复:回复:回复:回复:回复:回复:请教开发中的分层问题,急!!! 发表: 2007年07月08日 17:06 回复
深度关联的复制可能是具体技术细节问题,比如可以借助lazyload 和动态代理,这方面Hibernate做得不错,特别是主对象修改save后,它支持对子对象集合和原来旧数据进行深度比较更新,这些都是Hibernate值得使用得地方
boyszz

发表文章: 15
注册时间: 2007年09月09日 04:22
re:请教开发中的分层问题,急!!! 发表: 2007年09月09日 05:05 回复
持久层:hibernate
业务层:spring

你把Spring归于业务层让我汗颜.Spring应该是用来让你把各个层在一个统一的框架下管理起来,他是一个框架,不是一个层
bngj

发表文章: 1
注册时间: 2007年11月24日 12:03
回复:请教开发中的分层问题,急!!! 发表: 2007年11月24日 12:23 回复
看了上面的几篇文章,感觉受益非浅,这里我也有几个问题想咨询一下:
1> 利用公司的框架,会自动把页面数据绑定到formbean(formbean中的数据对应于多个表中的数据)
这个是如何实现的,是通过formbean中的字段名和页面传过来的字段名的一个默认的规则,然后利用java反射来做的吗?
比如:formbean中有一字段为name, 我们默认request中有一个参数Name
通过遍历formbean中的字段进行依次赋值吗?
那对于checkbox这样的字段如何处理?
如果方便的话能不能再介绍一下Struts中的formbean是如何实现的?

2> 对于formbean中的方法,除了提供get和set的方法,还能提供一些别的方法吗?
比如说:页面上有一个日期输入,但是从页面上传过来的是一个字符型,那在form 中我们是不是应该设置为String型,然后再提供一个另外的方法来由字符型转换为日期型,这个方法放在formbean中合适吗?谢谢!
这个主题有 16 回复 / 2 页 [ 1 2 下一页 ]
???en_US.forumThreadPrev.name??? 上一主题
Go back to the topic listing   返回主题列表    返回页首  返回页首
???en_US.forumThreadNext.name??? 下一主题
热点TAG: AOP cache DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Spring Struts
查询本论坛内 回复超过的热门帖子
快速发表回复
标题
 
粗体 斜体 下划线 插入图片 插入代码 插入url链接 插入附件
内容
 

解惑之道在J道 ,打造中国最具影响力的的企业软件社区
OpenSource JIVEJDON v3.0 Powered by JdonFramework Code © 2002-07 jdon.com

anti spam