Grails消灭Dao带来的问题

作者:wlmouse 发表时间:2008年06月04日 10:25 回复此消息回复

原贴网址: http://www.jdon.com:8080/jivejdon/thread/34173.html
标签列表 grails(3)      dao(31)      模型(35)      ddd(126)     

Grails自己学了一段时间了。感觉快速开发的感觉很不错。以前要干好几天的事情,一天就能完成。不过Grails对领域对象持久化使用AOP的方式让对象自己持久化自己。比如new A().save()。
这样一来就给我们造成可以在控制器里很容易的CRUD,对数据库的访问随时随地都可以,而不用访问Service->Dao的方式处理。而且Grails自己产生的CRUD代码也都在控制器里进行了持久化操作。
对此我感觉很疑惑了。Grails、ROR这类快速框架的层次划分该怎么算?持久化操作该随时自己做还是仍然放Service里?
以前Dao可以看作持久化服务组件。我们通过应用层调用持久化服务。现在持久化服务给领域对象自己了。那么我们在哪里调用呢?是随时使用领域对象来调用还是专门写一个Service封装起来?

这个主题共有 13 回复 / 1
回复:Grails消灭Dao带来的问题 发表: 2008年06月04日 11:45 回复
wlmouse 发表文章: 117/ 注册时间: 2006年11月09日 15:58
如果需要很多领域对象、服务一起工作,我当然会在Service里写。
传送参数到Service,Service调用服务、领域对象处理数据,最后保存并返回结果。
我主要疑问是最简单的CRUD,而不涉及其他业务的时候还需要到Service里吗?

re:Grails消灭Dao带来的问题 发表: 2008年06月04日 13:08 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
语言的限制和框架的限制。
RUBY的model似乎自己持有一个连接,这在java里是需要被释放掉的。
正是因为在使用Hibernate,所以不可能消灭掉dao,或许它会以另一种形式出现,做为范型基类来简化一些东西。
对于rails当然是要模型自己调用自己了,有血了。但是不要把相同的操作在service再实现一次,web会不知道它应该调用哪一个。
[该贴被freebox于2008-06-04 13:17修改过]

回复:re:Grails消灭Dao带来的问题 发表: 2008年06月05日 09:26 回复
wlmouse 发表文章: 117/ 注册时间: 2006年11月09日 15:58
Grails确实消灭了Dao。Grails的领域对象也是充血模型。领域对象自己可以用Save、Find等方法自己查询访问自己。Grails只是把Hibernate作为自己的持久化实现GORM的底层。
所以我才要问,基本上只是最简单的CRUD,而不涉及其他事务和其他业务的时候,还需要Service层参与吗?控制器里自己就可以把自己保存或查询。

re:Grails消灭Dao带来的问题 发表: 2008年06月05日 10:57 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
Service参与之后,web来调用哪一个呢?web会不知所措,web明明看见model是自管理的。所以我才认为对于它们不需要service。

回复:回复:re:Grails消灭Dao带来的问题 发表: 2008年06月05日 11:29 回复
banq 发表文章: 9485/ 注册时间: 2002年08月03日 17:08
是否使用service,取决于领域建模Evans DDD,而不是具体平台实现,在DDD中,service不是定义专门用来调用Dao的。

DDD中也不是没有DAO,而是repository,仓储,我们获取一个冬眠的对象要从仓储中获得,因为仓储中储存的是我们的对象。

DDD认为领域对象应该是充血丰富的,但不是说save等数据库行为方法放到领域对象中就代表充血了,这些都是片面理解DDD

领域对象中应该是丰富的业务行为,有时这种业务行为还会被我们用设计模式分离到其他类中,那么当前类就没有业务行为,但是你不能认为当前类就是失血模型,这是片面的,盲人摸象的。

将查询和save等行为放到对象内部,会产生悖论:一个对象能够自己获得自己吗?万事万物都有其母,孙猴子还从另外一方石头中蹦出来的,到了我们对象语言中,对象就可以找到自己了?创建自己了?这不是猫追自己尾巴吗?

回复:回复:回复:re:Grails消灭Dao带来的问题 发表: 2008年06月05日 13:16 回复
wlmouse 发表文章: 117/ 注册时间: 2006年11月09日 15:58
可能是我没说明白吧?
传统Java开发一般分为表现、应用、领域和持久四个层。持久化的功能DDD里应该算服务吧,提供一个领域对象持久化的服务。传统上应用层调用领域对象、服务、值对象,通过这三者处理业务。Grails的GROM把这个服务给了领域对象自己。领域对象可以用类的静态方法查询该类的实例,领域对象的实例可以保存、更新自己。
这样就造成了我们可以在表现层、应用层都可以调用持久化服务。只要控制器或者Service里能调用到领域对象,那么就可以使用其持久化服务。
所以,在Grails简单的CRUD中,控制器里就可以完成持久化服务了。它自动生成的脚手架代码也是这么写的。比如你建立了一个领域对象,赋值后,直接调用其save方法就可以保存了。因为这么做和传统开发不一样了,感觉别扭,所以在这里发问。
[该贴被wlmouse于2008-06-05 13:18修改过]

re:Grails消灭Dao带来的问题 发表: 2008年06月05日 19:36 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
一:我理解出来的意思是:他的业务逻辑就是简单CRUD,没有更多的内容。
是在这种业务逻辑情况下,是否还需要service。
在这里不是指复杂的业务逻辑。
当把复杂业务逻辑写在model里的时候,model会越来越复杂,所以我并不认为这是个好方式。

二:我认为持久化不是领域服务,算是基础服务吧。

Grails消灭Dao带来的问题 发表: 2008年06月06日 09:51 回复
banq 发表文章: 9485/ 注册时间: 2002年08月03日 17:08
>领域对象可以用类的静态方法查询该类的实例,领域对象的实例可以保存、更新自己。
前面我没说明白吗?这种方式根本就不是OO的嘛,不对的啊,哪有物体还不存在的情况下,自己找自己?逻辑悖论啊,领域对象可以冬眠 唤醒,但是不可以在自己还没有的情况下找自己啊,这不是疯子吗?我的意思不够明白吗?

>因为这么做和传统开发不一样了,感觉别扭,
无论什么框架和语言,当前都统一在Evans DDD思想指导下,凡是和这个开发不一样的就是歪门邪道。
[该贴被banq于2008-06-06 09:52修改过]
[该贴被banq于2008-06-06 10:01修改过]

re:Grails消灭Dao带来的问题 发表: 2008年06月06日 10:37 回复
coolzyt 发表文章: 9/ 注册时间: 2007年04月15日 09:05
BANQ现在有点偏执了

回复:re:Grails消灭Dao带来的问题 发表: 2008年06月06日 13:53 回复
pub 发表文章: 93/ 注册时间: 2008年04月13日 18:39
==BANQ现在有点偏执了
与其拍拍脑袋加入对象和对象方法属性,还不如这么偏执的选择DDD
DDD从细节上告诉我们如果划分对象如何构建业务层,没有什么方法比这个简单好用!

re:Grails消灭Dao带来的问题 发表: 2008年06月06日 15:04 回复
lgx522 发表文章: 104/ 注册时间: 2004年04月28日 15:37
本来很是期待Grails,做了个性能测试和Spring一比,差距很大。
看来这个懒偷不得。

re:Grails消灭Dao带来的问题 发表: 2008年06月06日 17:26 回复
freebox 发表文章: 279/ 注册时间: 2008年03月01日 01:08
我觉得rails不认为model是单纯的实体概念。
看见的存取器或实例变量都是实体意义,而其它的find之类方法属于操控意义,把实体和仓储压缩在一起。

回复:回复:re:Grails消灭Dao带来的问题 发表: 2008年06月10日 11:11 回复
banq 发表文章: 9485/ 注册时间: 2002年08月03日 17:08
>与其拍拍脑袋加入对象和对象方法属性,还不如这么偏执的选择DDD
不是我偏执啊,Ruby on Rails当初诞生时打的旗帜就是Evans DDD啊,不信看看很多英文资料,作为ROR的翻版Grails如果舍本求末,忘记当初特点,不能说我偏执吧,我指出了这样一个事实本质,只是你们之前没有看到罢了。

当然,单从这点不能全部否定Grails,但是可以肯定的是,使用Grails之前必须掌握Evans DDD,这些rails兄弟就是为更好实现DDD诞生的。

个人不赞成在模型中加入find功能,那么关于save呢?在Java中我们可以使用模式来实现save,比如JiveJdon3加入的内部消息功能,当用户看完消息后,以后不再提示有新消息,也就是说,消息的内容被读取了,那么就更改消息的状态,我们可以使用观察者模式实现,如下,消息模型:



public class ToShortMessage extends ShortMessage {

public String getFilterMessageBody() {
this.shortMessageState.setHasRead(true, this);
return messageBody;
}

}

public class ShortMessageState extends Observable{

.....

public void setHasRead(boolean hasRead, ShortMessage shortMessage) {
this.shortMessage = shortMessage;
if ((hasRead) && (!this.hasRead)){
this.hasRead = hasRead;
setChanged();//出发
notifyObservers(this);
}else
this.hasRead = hasRead;

}

}
public class ShortMessageRepository implements Observer{
....
public void update(Observable obj,Object arg){
logger.debug(
" Observable update ");
ShortMessageState shortMessageState = (ShortMessageState)obj;
try {
this.shortMessageDao.updateShortMessate(shortMessageState.getShortMessage());
} catch (Exception e) {
e.printStackTrace();
}
}

}



getFilterMessageBody是在jsp输出消息内容时,被调用,由于ShortMessageState 的setHasRead是事件触发,导致ShortMessageRepository 的update被执行。

从这里看出:ToShortMessage 也包含了复杂的业务行为,不只是简单的Property get/Set,所以,不能认为ToShortMessage 是贫血模型,而且贫血模型也不是完全不好,特别在冬眠到关系数据库时非常简洁轻量。这又涉及另外问题,这里主要说明:不能教条主义看待失血和充血,JiveJdon3的ForumMessage粗看上去是失血,只有set/get,没有业务逻辑,但是看看其子包下MessagRender就发现业务行为不少,这些都是从FourmMessage中分离出来的,是细节设计考虑,当然如果为了面对形式上充血,我完全可以将MessageRender功能都并入ForumMessage,那谁能看得懂ForumMessage呢?OO宗旨又跑到哪里了呢?再说Evans DDD最终必须结合设计模式的。



[该贴被banq于2008-06-13 21:18修改过]

这个主题共有 13 回复 / 1
 
上一篇: 有用过db4O的吗? 下一篇: web.xml中的监听错误如何解决
 
查询本论坛 最热门帖子

热点Tag: AOP cache 缓存 DDD EJB 集群 设计模式 Hibernate IOC JiveJdon OO RBAC Seam Spring Struts

标签总列表


Jdon框架演示

JiveJdon3.0
源码下载

GoF设计模式

在线教程

社区精彩讨论




google yahoo 新浪ViVi 365Key网摘 天极网摘 CSDN网摘 添加到百度搜藏 POCO网摘 博采网摘





手机阅读 add to google add to yahoo
联系我们 | 关于我们 | RSS订阅 | 广告联系 | 网站地图
Copyright (C) 2002-2008 Jdon.com, All Rights Reserved 版权所有 上海解道计算机技术有限公司
沪ICP备05018152号 如有意见请与我们联系 Powered by JdonFramework