如芒在背- -| 回首页 | 2004年索引 | - -PolyBloodyHardReuse

J2EE应用的典型架构- -

                                      

我们现在的做法是Transaction Script模式(http://www.martinfowler.com/eaaCatalog/transactionScript.html)。实体(也就是需要持久化的对象,有时我们也说它们就是领域对象)只是原始数据的对象形式,或者加上一些最简单的操作(只涉及本身数据的简单处理)。DAO负责将数据转化为实体对象,我们通常用Hibernate来实现。业务逻辑放在service里,每个service方法是一个Transaction Script。AppFuse(http://https://appfuse.dev.java.net/)也是按这种方式架构的。
 
Martin Fowler更倾向于Domain Model模式(http://www.martinfowler.com/eaaCatalog/domainModel.html)。领域对象不仅是原始数据的对象形式封装,而且包含几乎所有重要的业务逻辑。领域对象可以直接访问数据库,因此DAO不是必要的,而是通过一个他称为“mapper”的东西提供O/R映射。由于领域对象封装了业务逻辑,service只是一个很薄的facade,提供面向服务的接口。Spring的JPetstore范例就是按照这种方式架构的。但是,JPetstore的业务逻辑相当简单,我草草看了一下,似乎领域对象没有直接操作持久化逻辑,因此这并不是一个很有说服力的例子。或许更有说服力的是Pluto(http://jakarta.apache.org/pluto/)。在Pluto这里,需要持久化的大多是些配置信息(包括portal本身的配置、portlet的配置和用户配置),它并没有使用DAO,而是直接通过XML binding持久化到XML文件。
 
我不知道应该如何选择这两个体系结构模式。我不知道Transaction Script模式的缺点在哪里。我不知道Domain Model模式用起来会有什么困难。我不知道Martin Fowler为什么如此激烈地批评“贫血的领域对象”。这让我感到困惑和苦恼。我要首先再看一遍PoEAA的相关章节,再想想,再问问。我不喜欢感觉自己像个白痴。

- 作者: gigix 2004年05月21日, 星期五 21:20

Trackback

你可以使用这个链接引用该篇日志 http://publishblog.blogdriver.com/blog/tb.b?diaryID=166013

回复

- 评论人:canonical

Thu Mar 10 16:32:46 CST 2005  作者Blog

在不需要重用的时候,使用transaction script

- 评论人:thugf

Fri Dec 24 15:34:13 CST 2004  作者邮箱  作者Blog

fghfgh

- 评论人:魔之眼

Tue May 25 11:09:38 CST 2004 

如果我没记错,oo不是目的,而只是一个手段,基本上传说中的"复用".
这个"transaction script"虽然看上去"不太oo",但其实在我们的某些项目,比方说无复杂逻辑等等,还是蛮好用的,起码对开发来说.但的确有service层复杂的问题,我发现了一个1k多行代码的service,唉.

- 评论人:charon

Sun May 23 15:08:51 CST 2004  作者邮箱 

hehe,tell和ask有区别吗?
在agent交互的讨论中,一个一致的结论是实际上只需要tell就能把所有东西表达出来(虽然每个基于speech-act的语言不仅仅有tell原语)。而实际上,tell也好,ask也好,或者别的什么东西,一个动作或者交互的目的都是对接收方产生影响,所谓的原语是从影响的角度来划分的。
tell或者ask和是不是oo一点关系都没有。

- 评论人:Ronald Matt

Sun May 23 13:27:38 CST 2004  作者Blog

 感觉上blog来blog去都只是些fancy words,对什么是OO都还没搞清楚。

推荐一篇Dave Thomas的文章《Tell Don't Ask》
http://www.pragmaticprogrammer.com/ppllc/papers/1998_05.html
Transaction Script是Ask方式,
而Domain Model是Tell方式——真正的OO。

- 评论人:Ronald Matt

Sat May 22 23:21:35 CST 2004 

去读Domain Driven Design吧,Martin Fowler,Ward Cunningham,Kent Beck等人都对它赞叹到无以复加。

- 评论人:charon

Sat May 22 19:19:06 CST 2004 

我感觉大家对service的定义有点太狭义了。

- 评论人:potian

Sat May 22 13:49:04 CST 2004 

我说了一万遍了,service层的目的两个:
1 一般是客户代码,随客户而变
2 一般是服务代码,封装内部模型的复杂性

在分布式程序中的一个副作用是提高效率(通过DTO)

- 评论人:partech

Sat May 22 11:53:35 CST 2004  作者Blog

补充一下,关于Transaction Script,Table Module,Domain Model 的选择从martin Fowler的那张图可以
看出他的选择。我没有系统的研究过三者的差异,我感觉这对的。
按照图上的含义,对于小型项目首选应该是Table Module,随着业务逻辑的复杂程度的增加Domain Model 将是首选。
在.NET环境中因为有ADO.NET类似“内存数据库”的支持使得使用Table Module很自然。
Java环境中也可以通过组合纪录集的形式实现Table Module。
对于批量类型的对象操作可以考虑Transaction Script,因为单个记录或者单个对象操作效率可能太低。

服务层本质上是facade,确实不应该包含业务逻辑。

- 评论人:partech

Sat May 22 11:24:22 CST 2004  作者Blog

按照你们现在的做法,业务层还不能说是面向对象,因为对象的数据和操作这些数据的行为不是封装的而是分离的。
要发挥面向对象的所有威力需要将整个Domain层对象化,行为和数据必须封装,这是最基本的,然后还要考虑分层,对业务层进行抽象等等。

你们的做法我说一个缺点,不知道你们的应用同参与者是否只有一种交互形式?比如只通过WEB。然而参与者进行业务
可能有很多种方式,拿银行来说吧,可以通过柜台,也可以通过ATM,还有电话,和网上银行。很明显这些应用后台都需要服务,而且这些服务的交互方式是不同的,也就是用例不同。所以Service层会不同,DTO会不同。但是如果我在这些
应用中都进行转账业务,那么不管我使用的是哪一种途径,
负责转账的代码都该只有一份。Service层的代码没多少复用
价值,真正需要考虑的是Domain层的复用。
领域对象不单包含实体对象,还应该包含控制对象。很明显
转账的整个操作没法划给单个对象,但是分解出的转出和转入操作还是可以作为帐户实体的方法的。
不过我感觉有人常常将领域层的控制对象同应用层的服务对象混淆。区分两者很简单,一个是不针对特定应用的,一个是针对特定应用的,也就是系统中烟囱的部分。
服务层充当的是系统中烟囱的部分,所以在不同应用中不考虑复用。或者说尽量避免进行复用,这样各应用就可以独立演化了。
可以看看下面的网站,作者的书里提到了很多如何进行
领域层开发的方法。
http://domaindrivendesign.org


- 评论人:taowen

Sat May 22 02:15:12 CST 2004  作者邮箱 

是不是一些经典的模式将成为反模式?

- 评论人:匿名

Fri May 21 22:07:51 CST 2004 

好了好了,原来有大师支持哦们了。商业对象一定应该包含商业逻辑,只是简单封装数据库数据的算什么商业对象啊,session bean+DAO算什么OO啊。
现在还很土的用javabean,因为OO得自然。


- 评论人:曹晓钢

Fri May 21 21:38:50 CST 2004 

我很早就在hibernate中文论坛说过,我反对使用DAO,因为在使用or mapping之后,不应该再有data access的概念。
只不过很惭愧的是,我的论断大多只是自己的工程做出来的一些小经验,远远无法提高到模式的地步。

service加上transaction script的问题之一就是难以重用。

评论内容: