- 浏览: 415110 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
liyuanhoa_:
...
struts2.0中struts.xml配置文件详解 -
chenmingde:
...
Velocity应用(一) -
weizhikai_ai:
第二十六,当一个线程进入一个对象的一个synchronized ...
Java常见面试题(含答案) -
Aurora_lr:
...
Spring宠物商店学习笔记(一) - -
zs911zs:
all copy from http://www.iteye ...
Mule入门文档
陶文发起的对领域模型的最新讨论:领域模型的价值与困境,在这个讨论当中,我的关注点是,在现在的技术水平下,我们如何把领域模型的理论和我们实际应用开发框架结合起来,总结出最佳实践:
第一、DAO层和TransactionScript层是邪恶的!
我们在2004年一直跨度到2007年讨论来讨论去,其实都有一个隐含的前提条件:你的领域模型终究无法脱离对DAO层的依赖,以及需要TransactionScript层的包裹。而这样一来,领域模型的通用性、可移植性、业务逻辑的表达能力基本全部丧失,沦为框架限制下的奴隶。
而我们看看现在Java领域的技术进步,JPA已经普及,EJB3的隐含事务管理,甚至连Spring也可以简化成@Transactional,现在已经是我们可以去掉DAO和TransactionScript的时代了。
第二、Seam在消除了DAO层和TransactionScript以后,领域模型的感觉已经呼之欲出
这个不用多说,大家自己去看Seam文档好了。我唯一想强调的是entity bean和business bean分开有没有必要性,我的看法是有必要!这还是和Java本身语言的限制有关系:
1、Java语法表达能力有限,entity bean又不得不弄一大堆getter/setter方法,都放在一个class里面,代码的可阅读性非常差
2、business bean的很多业务逻辑方法需要容器环境,不像Rails的model可以直接mixin进来
3、Java做为目前最主流的工业语言,开发团队都是大规模编码协作的,你都放在一个class里面,团队协作会遇到很大的麻烦(事实上RoR现在也有这样的问题,但是RoR开发效率高,往往不需要那么大规模的开发团队)
3、领域模型不同类别的业务逻辑可以很容易的分到几个不同的business bean里面,这样对团队协作的好处很大。
第三、不考虑框架限制,All-in-One的领域模型好不好?
比方说RoR的model就是All-in-One的,但是一旦出现可以抽象出来,比较通用的业务逻辑,我们还是会把这些逻辑抽出来,单独实现,然后再mixin回去。所以没有必要All-in-One,根据你的实际需要来决定放在一个class里面,还是拆开成几个class。
所以最终我对这个问题的总结就是:
一、只要技术框架能够实现,尽量使用领域模型
二、无论Java还是Ruby,必须消灭DAO和TransactionScript
三、领域模型不必All-in-One,Java可以分割为 1个entity bean和几个business bean,而Ruby可以分割为1个model和几个mixin的module。
15:16 浏览 (3482) 评论 (22) 分类: Java 收藏 相关推荐 评论
terranhao 8 小时前 回复
为什么使用seam能消除DAO?
对一些查询,我还是需要一个DAO来封装啊,要不每次需要select e.* from entity as e where...,我都得调用entitymanager来执行这个sql?
如果用dao,我直接注入一个无状态的dao,然后调用dao就可以了,也避免了代码重复啊
期待解答。
netbaixc@gmail.com 昨天 回复
upheart 写道
netbaixc@gmail.com 写道
呵呵,职责单一了不就是应对变化啦?具体说,就是一个类就干这个活,不要干A还干B,否则如果仅仅干A的方式改了你就得去改这个类,重新部署测试;DAO就负责持久化的活,像你说的,如果数据库不同了持久化方式要改变则就改DAO;DOMAIN就负责业务逻辑,比如某个财务数据的计算方式变了,就改DOMAIN;Service负责完成用户和系统的基本交互;Command则是针对所有类型的用户交互的服务,因为有些时候有那种“快捷按钮”,你一点就要求系统给你做“一串”处理,所以Command就可以组织发起几个Service。这样按这种分类标准划分的类,哪个方面要变化,就改哪个方面啦。职责似乎可以无限细分下去,这取决于你对变化的预期,如果我预期存储方式99.9%不会变,我是不是就可以先不考虑用一层DAO呢?我做一个web应用,现在也用不着command,没有撤销前进的功能。当然我还是主张职责单一的,我只是不主张无谓的分层。
DAO和DOMAIN看上去不是界限分明的,很明显地为了提高效率往往把可以java运算的业务逻辑用复杂sql表达,相应的domain就架空了,这时domain的方法就直接调用一下dao对象的方法即可,当然有时候可能要发个邮件短信什么的,那指定是不能放到dao里的。DOMAIN和SERVICE也不是界限分明的。但是其实分层的意义在于它是和整个软件工程协作的。我们做软件时总是先定义需求用例,这时候能够划分出command,再从中抽象提炼出service来供command组合调用。一般情况下用户和系统的交互用例都需要事务保护,自然而然地service层里就会体现事务保护,有时还有业务锁同步逻辑。当我们再往下到概要设计时,就会从service里抽象出很业务的domain出来,每个domain都面向比较稳定的业务职责,相互之间也是可以组合调用的,统一交给service来组合调用,这里多数情况又会发现一个service基本上就是调用一个domain,“界限也不是那么分明,何必分层呢”,最后到详细设计实现时那些数据库的活就从domain里明确出来,自然而然地就出来了dao层,当然这时多数情况下又发现一个domain就是调用一个dao拉到,又何必分层呢?呵呵,比较绕。其实分层是这个过程自然的结果,既然这个过程自然产生了分层,何必要抹杀这个成果呢?毕竟分层达到了良好的OO效果,利用代码可读性可维护性,在IOC环境下更加明显。但我其实开始想说的是必须要有辅助工具来帮助程序员面对一个现实,就是这样的分层产生了太多类文件,对于开发人员手工开发起来一不小心打错个字符啥的,还要命名那么多方法,太辛苦啦,开发人员又觉得没有创造性太八股,很难管理啦!虽然设计和需求人员觉得总算可以通过非编程语言和开发人员交流(限制其创造性)了!
upheart 前天 回复
netbaixc@gmail.com 写道
呵呵,职责单一了不就是应对变化啦?具体说,就是一个类就干这个活,不要干A还干B,否则如果仅仅干A的方式改了你就得去改这个类,重新部署测试;DAO就负责持久化的活,像你说的,如果数据库不同了持久化方式要改变则就改DAO;DOMAIN就负责业务逻辑,比如某个财务数据的计算方式变了,就改DOMAIN;Service负责完成用户和系统的基本交互;Command则是针对所有类型的用户交互的服务,因为有些时候有那种“快捷按钮”,你一点就要求系统给你做“一串”处理,所以Command就可以组织发起几个Service。这样按这种分类标准划分的类,哪个方面要变化,就改哪个方面啦。
职责似乎可以无限细分下去,这取决于你对变化的预期,如果我预期存储方式99.9%不会变,我是不是就可以先不考虑用一层DAO呢?我做一个web应用,现在也用不着command,没有撤销前进的功能。
当然我还是主张职责单一的,我只是不主张无谓的分层。
jerryeye 前天 回复
DAO做的事情不做了吗?不做了当然取消,做了却取消,只是搬了个地方而已,这样有意思?DAO只是三个字母而已,惹谁了?大概robbin被国外的"血型"弄的迷糊了。
netbaixc@gmail.com 前天 回复
upheart 写道
为什么要分层呢?——大部分人是为了分层而分层,比如我们以前的一个做法就是强制一个实体对应一个dao、一个service一个action等等,就像是写八股文章,还美其名曰规范化,为了以后好维护。结果都是一两行的代码在几层之间包来包去。我觉得分层最主要的目的是解耦。很多人可能觉得分层是为了分类职责,这可能是分层带来的一个好处,但不是主要目的。要的目的是解耦,解耦的主要目的是应对变化。比如我分一个dao层,可以屏蔽掉hibernate或jpa或jdbc的具体实现,这样我可以切换不同的实现了。你看spring里边的petstore例子提供了不同的实现。问题是对于变化我们应该什么态度。我觉得应该在三个方面考虑:1.变化发生的可能性和机率;2.提前准备应对这个变化要增加的成本(包括机会成本)3.如果不提前考虑这个变化,以后通过重构来应对的代价。比如你有多大的可能要切换hibernate到jdbc或其他的实现呢?如果hibernate已经被证实足够稳定,那依赖它有什么问题呢?就像你依赖java.util一样是吧。这种被Rod JSon成为“幻影需求”提前为此而分层实在不值得吧。其实就算你分了层以后切换的时候还是会有很多问题的,除非你的应用就像petstore一样简单。所以与其这么做,不如完善你的测试,如果变化来了,有测试做保障,提炼重构付出的代价不一定比你提前预防这种变化的的代价要大很多。而且一定要考虑这种变化的机率的大小。分层的另一个好处是可以做孤立测试,说白了就是分离职责然后单独测试。但我前面说过分离职责不一定要分层的,你可以把业务复杂职责单一的功能放在另外一个类中。我现在的做法是用spring web flow做控制层,不需要java代码,只要xml的flow定义,其中调用service层。这个service层负责事务边界也代理业务,直接使用JPA接口。domain对象除了jpa等元数据的映射,提供一些get方法(我是说计算方法,比如getTotalSize()),还提供一些验证逻辑。页面使用Rich Faces。service测试大部分不做mock,而是连接数据库做测试,spring test框架支持自动回滚,可以用dbunit初始化测试数据就可以了。业务计算复杂的提炼出一个类来可以做mock测试了。可能以后还想加上selenium做验收测试,现在还没有加。
呵呵,职责单一了不就是应对变化啦?具体说,就是一个类就干这个活,不要干A还干B,否则如果仅仅干A的方式改了你就得去改这个类,重新部署测试;DAO就负责持久化的活,像你说的,如果数据库不同了持久化方式要改变则就改DAO;DOMAIN就负责业务逻辑,比如某个财务数据的计算方式变了,就改DOMAIN;Service负责完成用户和系统的基本交互;Command则是针对所有类型的用户交互的服务,因为有些时候有那种“快捷按钮”,你一点就要求系统给你做“一串”处理,所以Command就可以组织发起几个Service。这样按这种分类标准划分的类,哪个方面要变化,就改哪个方面啦。
upheart 前天 回复
为什么要分层呢?——大部分人是为了分层而分层,比如我们以前的一个做法就是强制一个实体对应一个dao、一个service一个action等等,就像是写八股文章,还美其名曰规范化,为了以后好维护。结果都是一两行的代码在几层之间包来包去。
我觉得分层最主要的目的是解耦。很多人可能觉得分层是为了分类职责,这可能是分层带来的一个好处,但不是主要目的。要的目的是解耦,解耦的主要目的是应对变化。比如我分一个dao层,可以屏蔽掉hibernate或jpa或jdbc的具体实现,这样我可以切换不同的实现了。你看spring里边的petstore例子提供了不同的实现。
问题是对于变化我们应该什么态度。我觉得应该在三个方面考虑:1.变化发生的可能性和机率;2.提前准备应对这个变化要增加的成本(包括机会成本)3.如果不提前考虑这个变化,以后通过重构来应对的代价。
比如你有多大的可能要切换hibernate到jdbc或其他的实现呢?如果hibernate已经被证实足够稳定,那依赖它有什么问题呢?就像你依赖java.util一样是吧。这种被Rod JSon成为“幻影需求”提前为此而分层实在不值得吧。其实就算你分了层以后切换的时候还是会有很多问题的,除非你的应用就像petstore一样简单。所以与其这么做,不如完善你的测试,如果变化来了,有测试做保障,提炼重构付出的代价不一定比你提前预防这种变化的的代价要大很多。而且一定要考虑这种变化的机率的大小。
分层的另一个好处是可以做孤立测试,说白了就是分离职责然后单独测试。但我前面说过分离职责不一定要分层的,你可以把业务复杂职责单一的功能放在另外一个类中。
我现在的做法是用spring web flow做控制层,不需要java代码,只要xml的flow定义,其中调用service层。这个service层负责事务边界也代理业务,直接使用JPA接口。domain对象除了jpa等元数据的映射,提供一些get方法(我是说计算方法,比如getTotalSize()),还提供一些验证逻辑。页面使用Rich Faces。
service测试大部分不做mock,而是连接数据库做测试,spring test框架支持自动回滚,可以用dbunit初始化测试数据就可以了。业务计算复杂的提炼出一个类来可以做mock测试了。
可能以后还想加上selenium做验收测试,现在还没有加。
icewubin 前天 回复
wangchao_17915566 写道
数据库+展现,剩下的一概不要
你这样不就是分了一层么?“展现”就是你的分层,你的展现如何实现?再分层么?呵呵。
czx566 前天 回复
wangchao_17915566 写道
数据库+展现,剩下的一概不要
不同意,除非你的业务逻辑都是单纯增删改查
wangchao_17915566 2008-12-01 回复
数据库+展现,剩下的一概不要
icewubin 2008-12-01 回复
引用
5. 如果对分层的体系结构熟悉的话,开发效率并不低(虽然代码量较大,但不复杂,易于调
试、测试和实现),可能有点boring,但更易于合作分工。
分层未必代码量大,完全是看你打算把什么东西分层,如何分层和分层的粒度问题。有时候更多的是逻辑上的分层,甚至于可以理解为编程规范,分得好或者说理解的好的话,不会增加多少代码和配置的。
xiaosi 2008-12-01 回复
说的很有道理
dicom 2008-12-01 回复
1. Domain Model是用来描述业务领域内的对象及其之间的关系的,目前的Domain model能够
做到这个,那就不能称其“贫血”。Domain Model应该是纯粹的,业务逻辑和持久化不应该是
Domain Model里描述的,业务逻辑属于Business Process Model, 持久化则是系统功能。
Domain Model不应该依赖DAO,是DAO依赖领域模型,Business Service则依赖Domain Model和
DAO
2. 分层,是把复杂系统进行分解成多个可把握的简化模块,由于系统本身还需要重新组合,
所以分层本身是将复杂系统更复杂了(增加了模块间的组合的复杂性和分层体系结构本身技术
复杂性),但各个模块简化了,易于理解把握和工作。
3. 分层本身适合按模块分工,和当前大多数按功能分工不相符。按功能或特性分工协作,要
求每个人都把握整个体系结构,分层增加了复杂性,但按特性分工不易整合。
4. 分层结构易扩展,适于大型项目(到底多大所大型呢?)
5. 如果对分层的体系结构熟悉的话,开发效率并不低(虽然代码量较大,但不复杂,易于调
试、测试和实现),可能有点boring,但更易于合作分工。
andycui 2008-12-01 回复
Dao要消灭的话,可以使用一个通用dao,而不要一个domain object一个dao,我们现在的项目就是,导致了太多的dao,或者干脆把dao的操作直接整合进domain object。
至于transaction的包裹,通过spring的话需要配置文件或者annotation,唉,其实我估计大家用的最多的就是spring的事务支持了,看看也就没啥了,以前的EJB早就提供了的功能,EJB3不也很好吗? 另外spring的事务支持团队里自己实现也是非常容易的,大家不要为了spring而spring。
netbaixc@gmail.com 2008-12-01 回复
robbin,大概看了那几个“血型”,嘿嘿,以前呆在国内一个知名公司里,平台是基于spring开发的,就要求分层,service里是描述事务和对外的门面,domain是针对业务的逻辑处理,dao是数据库操作,至于你说的domain object,是简单JAVA对象.当时的开发真是麻烦啊,尤其是要求不能跨层调用,就是command(响应http request)->service->domain->dao,而且这些都是通过spring的IOC配置在XML中,哇塞,那个配置文件看得人是头晕眼花,开发个CRUD那是一个痛苦啊,公司虽然提供了代码机来生成,可是也蛮麻烦的,让人忍不住想,这么搞有么价值?因为庞大的代码和配置文件,使得在开发和维护过程中需要阅读太多的东西了。虽然这些文件确实因为OO而变得职责单一,但是文件太多了,看起来也很费劲的!
说分层也好,说OO划分单一职责也好,不就是希望提高开发效率,利于后期维护么?但是如果分得太细,就会导致代码庞大;如果想要精简代码,有人说就得all-in-one。许多人在这个权衡上争辩,其实有一些更好的想法反而被埋没了,特此拍砖。
1.可以划分得越细越好,涨血到爆血,但是要伴随提供一个图形化的IDE,开发者使用IDE开发,将那么庞大的文件通过工具精简透明掉,开发人员在开发思路上仍然保持清晰的划分,但实际开发和维护通过图形化的向导啊之类的工具帮助来实现。现在很多中间件厂商都有提供哦。
2.采用元数据。记得有个技术公司的技术总监提点我:“小伙子,你看我们的项目,里面的代码不都是在描述业务么?什么校验,什么计算,什么查询”。其实可以将这些业务规则用纯数据来描述,按关系数据表来细粒度管理,然后通过一个框架式的代码来读取这些数据,进行“解析式”执行。这里的数据才是最精简的代码。
icewubin 2008-12-01 回复
czx566 写道
程序员最终要被智能编程消灭到
汇编被C取代的时候,也没见程序员失业啊。
china8jie 2008-12-01 回复
Why 消灭 Dao ??
那我们一直实践的东西是落后的? 噁待淘汰的 ?
czx566 2008-12-01 回复
先消灭 DAO
再消灭 View bean
最后程序员 只剩下 Business bean摆弄了
呵呵
程序员最终要被智能编程消灭到
upheart 2008-12-01 回复
抽象,抽象,抽象,一层,两层到N层
简化,简化,简化,N层,两层到一层
seven2seven 2008-12-01 回复
有点意思
didasoft 2008-12-01 回复
didasoft 写道
Robin能够简单解释一下:领域模型All-in-one指的是什么概念?
无法修改评论?写错字了。
Robbin能否简单解释一下:领域模型All-in-one指的是什么概念?
第一、DAO层和TransactionScript层是邪恶的!
我们在2004年一直跨度到2007年讨论来讨论去,其实都有一个隐含的前提条件:你的领域模型终究无法脱离对DAO层的依赖,以及需要TransactionScript层的包裹。而这样一来,领域模型的通用性、可移植性、业务逻辑的表达能力基本全部丧失,沦为框架限制下的奴隶。
而我们看看现在Java领域的技术进步,JPA已经普及,EJB3的隐含事务管理,甚至连Spring也可以简化成@Transactional,现在已经是我们可以去掉DAO和TransactionScript的时代了。
第二、Seam在消除了DAO层和TransactionScript以后,领域模型的感觉已经呼之欲出
这个不用多说,大家自己去看Seam文档好了。我唯一想强调的是entity bean和business bean分开有没有必要性,我的看法是有必要!这还是和Java本身语言的限制有关系:
1、Java语法表达能力有限,entity bean又不得不弄一大堆getter/setter方法,都放在一个class里面,代码的可阅读性非常差
2、business bean的很多业务逻辑方法需要容器环境,不像Rails的model可以直接mixin进来
3、Java做为目前最主流的工业语言,开发团队都是大规模编码协作的,你都放在一个class里面,团队协作会遇到很大的麻烦(事实上RoR现在也有这样的问题,但是RoR开发效率高,往往不需要那么大规模的开发团队)
3、领域模型不同类别的业务逻辑可以很容易的分到几个不同的business bean里面,这样对团队协作的好处很大。
第三、不考虑框架限制,All-in-One的领域模型好不好?
比方说RoR的model就是All-in-One的,但是一旦出现可以抽象出来,比较通用的业务逻辑,我们还是会把这些逻辑抽出来,单独实现,然后再mixin回去。所以没有必要All-in-One,根据你的实际需要来决定放在一个class里面,还是拆开成几个class。
所以最终我对这个问题的总结就是:
一、只要技术框架能够实现,尽量使用领域模型
二、无论Java还是Ruby,必须消灭DAO和TransactionScript
三、领域模型不必All-in-One,Java可以分割为 1个entity bean和几个business bean,而Ruby可以分割为1个model和几个mixin的module。
15:16 浏览 (3482) 评论 (22) 分类: Java 收藏 相关推荐 评论
terranhao 8 小时前 回复
为什么使用seam能消除DAO?
对一些查询,我还是需要一个DAO来封装啊,要不每次需要select e.* from entity as e where...,我都得调用entitymanager来执行这个sql?
如果用dao,我直接注入一个无状态的dao,然后调用dao就可以了,也避免了代码重复啊
期待解答。
netbaixc@gmail.com 昨天 回复
upheart 写道
netbaixc@gmail.com 写道
呵呵,职责单一了不就是应对变化啦?具体说,就是一个类就干这个活,不要干A还干B,否则如果仅仅干A的方式改了你就得去改这个类,重新部署测试;DAO就负责持久化的活,像你说的,如果数据库不同了持久化方式要改变则就改DAO;DOMAIN就负责业务逻辑,比如某个财务数据的计算方式变了,就改DOMAIN;Service负责完成用户和系统的基本交互;Command则是针对所有类型的用户交互的服务,因为有些时候有那种“快捷按钮”,你一点就要求系统给你做“一串”处理,所以Command就可以组织发起几个Service。这样按这种分类标准划分的类,哪个方面要变化,就改哪个方面啦。职责似乎可以无限细分下去,这取决于你对变化的预期,如果我预期存储方式99.9%不会变,我是不是就可以先不考虑用一层DAO呢?我做一个web应用,现在也用不着command,没有撤销前进的功能。当然我还是主张职责单一的,我只是不主张无谓的分层。
DAO和DOMAIN看上去不是界限分明的,很明显地为了提高效率往往把可以java运算的业务逻辑用复杂sql表达,相应的domain就架空了,这时domain的方法就直接调用一下dao对象的方法即可,当然有时候可能要发个邮件短信什么的,那指定是不能放到dao里的。DOMAIN和SERVICE也不是界限分明的。但是其实分层的意义在于它是和整个软件工程协作的。我们做软件时总是先定义需求用例,这时候能够划分出command,再从中抽象提炼出service来供command组合调用。一般情况下用户和系统的交互用例都需要事务保护,自然而然地service层里就会体现事务保护,有时还有业务锁同步逻辑。当我们再往下到概要设计时,就会从service里抽象出很业务的domain出来,每个domain都面向比较稳定的业务职责,相互之间也是可以组合调用的,统一交给service来组合调用,这里多数情况又会发现一个service基本上就是调用一个domain,“界限也不是那么分明,何必分层呢”,最后到详细设计实现时那些数据库的活就从domain里明确出来,自然而然地就出来了dao层,当然这时多数情况下又发现一个domain就是调用一个dao拉到,又何必分层呢?呵呵,比较绕。其实分层是这个过程自然的结果,既然这个过程自然产生了分层,何必要抹杀这个成果呢?毕竟分层达到了良好的OO效果,利用代码可读性可维护性,在IOC环境下更加明显。但我其实开始想说的是必须要有辅助工具来帮助程序员面对一个现实,就是这样的分层产生了太多类文件,对于开发人员手工开发起来一不小心打错个字符啥的,还要命名那么多方法,太辛苦啦,开发人员又觉得没有创造性太八股,很难管理啦!虽然设计和需求人员觉得总算可以通过非编程语言和开发人员交流(限制其创造性)了!
upheart 前天 回复
netbaixc@gmail.com 写道
呵呵,职责单一了不就是应对变化啦?具体说,就是一个类就干这个活,不要干A还干B,否则如果仅仅干A的方式改了你就得去改这个类,重新部署测试;DAO就负责持久化的活,像你说的,如果数据库不同了持久化方式要改变则就改DAO;DOMAIN就负责业务逻辑,比如某个财务数据的计算方式变了,就改DOMAIN;Service负责完成用户和系统的基本交互;Command则是针对所有类型的用户交互的服务,因为有些时候有那种“快捷按钮”,你一点就要求系统给你做“一串”处理,所以Command就可以组织发起几个Service。这样按这种分类标准划分的类,哪个方面要变化,就改哪个方面啦。
职责似乎可以无限细分下去,这取决于你对变化的预期,如果我预期存储方式99.9%不会变,我是不是就可以先不考虑用一层DAO呢?我做一个web应用,现在也用不着command,没有撤销前进的功能。
当然我还是主张职责单一的,我只是不主张无谓的分层。
jerryeye 前天 回复
DAO做的事情不做了吗?不做了当然取消,做了却取消,只是搬了个地方而已,这样有意思?DAO只是三个字母而已,惹谁了?大概robbin被国外的"血型"弄的迷糊了。
netbaixc@gmail.com 前天 回复
upheart 写道
为什么要分层呢?——大部分人是为了分层而分层,比如我们以前的一个做法就是强制一个实体对应一个dao、一个service一个action等等,就像是写八股文章,还美其名曰规范化,为了以后好维护。结果都是一两行的代码在几层之间包来包去。我觉得分层最主要的目的是解耦。很多人可能觉得分层是为了分类职责,这可能是分层带来的一个好处,但不是主要目的。要的目的是解耦,解耦的主要目的是应对变化。比如我分一个dao层,可以屏蔽掉hibernate或jpa或jdbc的具体实现,这样我可以切换不同的实现了。你看spring里边的petstore例子提供了不同的实现。问题是对于变化我们应该什么态度。我觉得应该在三个方面考虑:1.变化发生的可能性和机率;2.提前准备应对这个变化要增加的成本(包括机会成本)3.如果不提前考虑这个变化,以后通过重构来应对的代价。比如你有多大的可能要切换hibernate到jdbc或其他的实现呢?如果hibernate已经被证实足够稳定,那依赖它有什么问题呢?就像你依赖java.util一样是吧。这种被Rod JSon成为“幻影需求”提前为此而分层实在不值得吧。其实就算你分了层以后切换的时候还是会有很多问题的,除非你的应用就像petstore一样简单。所以与其这么做,不如完善你的测试,如果变化来了,有测试做保障,提炼重构付出的代价不一定比你提前预防这种变化的的代价要大很多。而且一定要考虑这种变化的机率的大小。分层的另一个好处是可以做孤立测试,说白了就是分离职责然后单独测试。但我前面说过分离职责不一定要分层的,你可以把业务复杂职责单一的功能放在另外一个类中。我现在的做法是用spring web flow做控制层,不需要java代码,只要xml的flow定义,其中调用service层。这个service层负责事务边界也代理业务,直接使用JPA接口。domain对象除了jpa等元数据的映射,提供一些get方法(我是说计算方法,比如getTotalSize()),还提供一些验证逻辑。页面使用Rich Faces。service测试大部分不做mock,而是连接数据库做测试,spring test框架支持自动回滚,可以用dbunit初始化测试数据就可以了。业务计算复杂的提炼出一个类来可以做mock测试了。可能以后还想加上selenium做验收测试,现在还没有加。
呵呵,职责单一了不就是应对变化啦?具体说,就是一个类就干这个活,不要干A还干B,否则如果仅仅干A的方式改了你就得去改这个类,重新部署测试;DAO就负责持久化的活,像你说的,如果数据库不同了持久化方式要改变则就改DAO;DOMAIN就负责业务逻辑,比如某个财务数据的计算方式变了,就改DOMAIN;Service负责完成用户和系统的基本交互;Command则是针对所有类型的用户交互的服务,因为有些时候有那种“快捷按钮”,你一点就要求系统给你做“一串”处理,所以Command就可以组织发起几个Service。这样按这种分类标准划分的类,哪个方面要变化,就改哪个方面啦。
upheart 前天 回复
为什么要分层呢?——大部分人是为了分层而分层,比如我们以前的一个做法就是强制一个实体对应一个dao、一个service一个action等等,就像是写八股文章,还美其名曰规范化,为了以后好维护。结果都是一两行的代码在几层之间包来包去。
我觉得分层最主要的目的是解耦。很多人可能觉得分层是为了分类职责,这可能是分层带来的一个好处,但不是主要目的。要的目的是解耦,解耦的主要目的是应对变化。比如我分一个dao层,可以屏蔽掉hibernate或jpa或jdbc的具体实现,这样我可以切换不同的实现了。你看spring里边的petstore例子提供了不同的实现。
问题是对于变化我们应该什么态度。我觉得应该在三个方面考虑:1.变化发生的可能性和机率;2.提前准备应对这个变化要增加的成本(包括机会成本)3.如果不提前考虑这个变化,以后通过重构来应对的代价。
比如你有多大的可能要切换hibernate到jdbc或其他的实现呢?如果hibernate已经被证实足够稳定,那依赖它有什么问题呢?就像你依赖java.util一样是吧。这种被Rod JSon成为“幻影需求”提前为此而分层实在不值得吧。其实就算你分了层以后切换的时候还是会有很多问题的,除非你的应用就像petstore一样简单。所以与其这么做,不如完善你的测试,如果变化来了,有测试做保障,提炼重构付出的代价不一定比你提前预防这种变化的的代价要大很多。而且一定要考虑这种变化的机率的大小。
分层的另一个好处是可以做孤立测试,说白了就是分离职责然后单独测试。但我前面说过分离职责不一定要分层的,你可以把业务复杂职责单一的功能放在另外一个类中。
我现在的做法是用spring web flow做控制层,不需要java代码,只要xml的flow定义,其中调用service层。这个service层负责事务边界也代理业务,直接使用JPA接口。domain对象除了jpa等元数据的映射,提供一些get方法(我是说计算方法,比如getTotalSize()),还提供一些验证逻辑。页面使用Rich Faces。
service测试大部分不做mock,而是连接数据库做测试,spring test框架支持自动回滚,可以用dbunit初始化测试数据就可以了。业务计算复杂的提炼出一个类来可以做mock测试了。
可能以后还想加上selenium做验收测试,现在还没有加。
icewubin 前天 回复
wangchao_17915566 写道
数据库+展现,剩下的一概不要
你这样不就是分了一层么?“展现”就是你的分层,你的展现如何实现?再分层么?呵呵。
czx566 前天 回复
wangchao_17915566 写道
数据库+展现,剩下的一概不要
不同意,除非你的业务逻辑都是单纯增删改查
wangchao_17915566 2008-12-01 回复
数据库+展现,剩下的一概不要
icewubin 2008-12-01 回复
引用
5. 如果对分层的体系结构熟悉的话,开发效率并不低(虽然代码量较大,但不复杂,易于调
试、测试和实现),可能有点boring,但更易于合作分工。
分层未必代码量大,完全是看你打算把什么东西分层,如何分层和分层的粒度问题。有时候更多的是逻辑上的分层,甚至于可以理解为编程规范,分得好或者说理解的好的话,不会增加多少代码和配置的。
xiaosi 2008-12-01 回复
说的很有道理
dicom 2008-12-01 回复
1. Domain Model是用来描述业务领域内的对象及其之间的关系的,目前的Domain model能够
做到这个,那就不能称其“贫血”。Domain Model应该是纯粹的,业务逻辑和持久化不应该是
Domain Model里描述的,业务逻辑属于Business Process Model, 持久化则是系统功能。
Domain Model不应该依赖DAO,是DAO依赖领域模型,Business Service则依赖Domain Model和
DAO
2. 分层,是把复杂系统进行分解成多个可把握的简化模块,由于系统本身还需要重新组合,
所以分层本身是将复杂系统更复杂了(增加了模块间的组合的复杂性和分层体系结构本身技术
复杂性),但各个模块简化了,易于理解把握和工作。
3. 分层本身适合按模块分工,和当前大多数按功能分工不相符。按功能或特性分工协作,要
求每个人都把握整个体系结构,分层增加了复杂性,但按特性分工不易整合。
4. 分层结构易扩展,适于大型项目(到底多大所大型呢?)
5. 如果对分层的体系结构熟悉的话,开发效率并不低(虽然代码量较大,但不复杂,易于调
试、测试和实现),可能有点boring,但更易于合作分工。
andycui 2008-12-01 回复
Dao要消灭的话,可以使用一个通用dao,而不要一个domain object一个dao,我们现在的项目就是,导致了太多的dao,或者干脆把dao的操作直接整合进domain object。
至于transaction的包裹,通过spring的话需要配置文件或者annotation,唉,其实我估计大家用的最多的就是spring的事务支持了,看看也就没啥了,以前的EJB早就提供了的功能,EJB3不也很好吗? 另外spring的事务支持团队里自己实现也是非常容易的,大家不要为了spring而spring。
netbaixc@gmail.com 2008-12-01 回复
robbin,大概看了那几个“血型”,嘿嘿,以前呆在国内一个知名公司里,平台是基于spring开发的,就要求分层,service里是描述事务和对外的门面,domain是针对业务的逻辑处理,dao是数据库操作,至于你说的domain object,是简单JAVA对象.当时的开发真是麻烦啊,尤其是要求不能跨层调用,就是command(响应http request)->service->domain->dao,而且这些都是通过spring的IOC配置在XML中,哇塞,那个配置文件看得人是头晕眼花,开发个CRUD那是一个痛苦啊,公司虽然提供了代码机来生成,可是也蛮麻烦的,让人忍不住想,这么搞有么价值?因为庞大的代码和配置文件,使得在开发和维护过程中需要阅读太多的东西了。虽然这些文件确实因为OO而变得职责单一,但是文件太多了,看起来也很费劲的!
说分层也好,说OO划分单一职责也好,不就是希望提高开发效率,利于后期维护么?但是如果分得太细,就会导致代码庞大;如果想要精简代码,有人说就得all-in-one。许多人在这个权衡上争辩,其实有一些更好的想法反而被埋没了,特此拍砖。
1.可以划分得越细越好,涨血到爆血,但是要伴随提供一个图形化的IDE,开发者使用IDE开发,将那么庞大的文件通过工具精简透明掉,开发人员在开发思路上仍然保持清晰的划分,但实际开发和维护通过图形化的向导啊之类的工具帮助来实现。现在很多中间件厂商都有提供哦。
2.采用元数据。记得有个技术公司的技术总监提点我:“小伙子,你看我们的项目,里面的代码不都是在描述业务么?什么校验,什么计算,什么查询”。其实可以将这些业务规则用纯数据来描述,按关系数据表来细粒度管理,然后通过一个框架式的代码来读取这些数据,进行“解析式”执行。这里的数据才是最精简的代码。
icewubin 2008-12-01 回复
czx566 写道
程序员最终要被智能编程消灭到
汇编被C取代的时候,也没见程序员失业啊。
china8jie 2008-12-01 回复
Why 消灭 Dao ??
那我们一直实践的东西是落后的? 噁待淘汰的 ?
czx566 2008-12-01 回复
先消灭 DAO
再消灭 View bean
最后程序员 只剩下 Business bean摆弄了
呵呵
程序员最终要被智能编程消灭到
upheart 2008-12-01 回复
抽象,抽象,抽象,一层,两层到N层
简化,简化,简化,N层,两层到一层
seven2seven 2008-12-01 回复
有点意思
didasoft 2008-12-01 回复
didasoft 写道
Robin能够简单解释一下:领域模型All-in-one指的是什么概念?
无法修改评论?写错字了。
Robbin能否简单解释一下:领域模型All-in-one指的是什么概念?
发表评论
-
利用动态代理的 Java 验证
2008-12-18 17:41 827从业务对象实现中去耦 ... -
Java 理论与实践: 用动态代理进行修饰
2008-12-18 17:41 782动态代理是构建 Decorator 和 Adapter 的方便 ... -
分布式软件系统
2008-12-18 15:49 1448分布式软件系统(Distributed Software Sy ... -
SOA实践 -- 使用IoC和AOP重构SOA应用
2008-12-18 15:35 968在本文中,作者通过一个Web Service访问的实例,具体描 ... -
SOA 案例研究:SOA 设计
2008-12-17 15:00 1050http://www.ibm.com/developerwor ... -
RUP
2008-12-12 16:53 698RUP(Rational Unified Proces ... -
什么是敏捷开发?
2008-12-05 11:17 2435敏捷开发(agile development)是一种以人为核心 ... -
深入理解敏捷开发的常见九大误区
2008-12-05 11:16 1476任人、开发者和用户应 ... -
领域模型的价值与困境
2008-12-04 17:02 958很久以前大家就关于这 ... -
OO设计原则----依赖倒置原则(DIP)
2008-12-02 01:52 1086这是一个类与类之间调用规则,术语上解释就是对于组合之间的规范。 ... -
工厂模式与OO设计原则
2008-12-02 01:50 1136如果把创建看作一个职 ... -
设计模式之--动态代理
2008-11-26 18:03 1610动态代理类是一个在运行时由开发人员所指定的一列接口的实现。动态 ... -
Facade外观模式
2008-11-26 16:06 983GOF《设计模式》一书对Facade模式是这样描述的: ... -
Adapter适配器模式
2008-11-26 16:05 834GOF《设计模式》一书对Adapter模式是这样描述的: ... -
Strategy策略模式
2008-11-26 16:05 1072GOF《设计模式》一书对Strategy模式是这样描述的: ... -
Bridge桥接模式
2008-11-26 16:04 902设计模式》一书对Bridge是这样描述的: 将抽象与其实现解 ... -
Abstract Factory抽象工厂模式
2008-11-26 16:03 748GOF《设计模式》一书对Abstract Factory模式是 ... -
Decorator装饰模式
2008-11-26 16:01 872《设计模式》一书对Decorator是这样描述的: 动态地给 ... -
Observer观察者模式
2008-11-26 15:59 921《设计模式》一书对Observer是这样描述的: 定义对象间的 ... -
Template Method模式
2008-11-26 15:58 975factory模式(包括简单工厂和抽象工厂),Strategy ...
相关推荐
10. **模型应用**:观点型阅读理解模型可以应用于各种场景,如在线评论分析、社交媒体情绪检测、产品评价总结等。 在提供的压缩包文件中,"基于capsule的观点型阅读理解模型实现"很可能是包含代码、模型结构图、...
总结来说,量化策略专题研究深入探讨了量化行业配置模型的构建和应用,结合最新的观点,为投资者提供了优化投资组合的有效工具。然而,理解和实施量化策略需要扎实的统计学基础、编程技能以及对市场的敏锐洞察,同时...
最后,通过实验验证模型的准确性和泛化能力,并对识别出的垃圾观点文档进行统计和分析,总结出垃圾观点文档的共同特征,这些特征可用于识别新数据集中垃圾观点文档的可能性。在此过程中,还需要讨论如何处理评论中的...
综上所述,本文在机器学习尤其是随机森林模型的应用上提出了创新的改进方法,即通过因子观点的融入来提升模型在金融市场中的灵活性和适用性,这对于金融领域的量化投资具有重要的实践意义和参考价值。同时,它也为...
总结来说,灰色预测及其改进模型是灰色系统理论的重要应用,它们在处理不完全信息的系统问题上展现了独特的优势,尤其在不确定性的数据环境中表现出色。随着技术的进步和更多改进模型的提出,灰色预测模型的预测能力...
这可能涉及到对新词汇的识别和其语义关系的推断,确保模型的适应性和时效性。 5. **实时分析**:最后,基于构建的领域语义关系图,对网络社区的短文本数据进行实时分析。这一步骤能够快速捕捉到文本中的关键信息,...
其中,AlexNet作为CNN的一个标志性模型,不仅在2012年的ImageNet大规模视觉识别挑战赛(ILSVRC)中一举夺魁,还因其卓越的表现极大地推动了深度学习领域的发展。 #### 二、背景介绍 四年前,即2008年左右,由Yann ...
数据偏见是指训练数据中存在的偏差,这种偏差可能会导致模型在预测时倾向于某些特定的群体或观点,从而影响模型的公平性和准确性。解决数据偏见的策略包括: - 确保训练数据覆盖广泛的人群、观点和情境。 - 使用统计...
情感分析是自然语言处理(NLP)领域的一个重要任务,旨在识别和提取文本中的主观信息,如情绪、观点和态度。 首先,我们要理解LSTM网络的基本结构。LSTM是一种特殊的循环神经网络(RNN),设计用于解决传统RNN在...
报告总结的核心观点包括:(1) 预计到2025年,AI将在全球范围内产生显著的社会和经济效益;(2) 计算力的快速增长将加速大模型的演进,预计到2028年,市场规模将增长超过1095%;(3) 大模型正逐步解决人工智能在数据...
总结来说,AI大模型的发展趋势和算力资源的稀缺性为计算机行业带来了新的发展机遇。企业若想在AI技术不断进步的浪潮中保持竞争力,就必须积极适应这一变化,加大技术研发投入,并制定出符合市场发展趋势的战略规划。...
- **作用**:它有助于减少误解和沟通障碍,确保所有人对系统的需求和设计有着相同的观点。 - **实践方法**: - **词汇表**:创建并维护一个项目词汇表,定义术语和其含义。 - **协作开发**:与业务专家紧密合作,...
该白皮书主要围绕人工智能大模型在医疗健康领域的应用进行了详尽的分析,并提出了以下几个关键观点: 1. **应用层面的全面覆盖**:人工智能大模型不仅能够应用于生命科学和医药器械的研发阶段,还能够覆盖医学影像...
IBIS模型广泛应用于项目管理、软件工程、政策制定、教育领域,以及任何需要团队协作和决策的环境。它鼓励开放的沟通,促进理解和共识的形成,同时避免了因信息过载而造成的混乱。 **文档详细内容** "IBIS模型详解...
本文介绍了一种新的线性估计方法,该方法通过两次AR(自回归)模型的估计来实现对ARMA模型的参数估计。此外,文中还讨论了一维时间序列开环系统与闭环系统的辨识方法及定阶问题,并通过仿真实验验证了该方法的有效性...
在这个领域,观点提取是一项关键任务,它涉及到从大量文本中识别、抽取和总结人们对于特定主题的观点、态度或情感。 观点提取通常包含三个主要步骤:情感极性判断、观点目标识别和观点值量化。情感极性判断是指确定...
总结而言,通过结合Black-Litterman模型和风险平价组合的方法,投资者能够在考虑风险的同时,合理地融入个人的预期收益率观点,从而在投资组合构建过程中实现更加灵活和定制化的资产配置。这种策略不仅丰富了投资...