锁定老帖子 主题:Rapae 弱化DAO的一种方法
精华帖 (0) :: 良好帖 (19) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-06-17
非常同意楼主的观点,
总是在DAO和Service里定义相同的接口,让人很不爽。 其实关于DAO弱化,将使复杂业务的service臃肿的情况, 为什么不在复杂业务的时候强化DAO呢? 让service同时持有弱化DAO和专有DAO怎么样? 实际上至少有一半的情况弱化的DAO方式更合适。 |
|
返回顶楼 | |
发表时间:2008-06-17
我又考虑了一下。
上面我提到了,这样的简化只是把本来是一行的代码写成了注解的形式而已。我还提到这种简化是没有必要的。 仔细考虑一下发现这根本就是没有必要的。^_^~~ 设想一下假如我们使用泛型DAO是什么效果?我们只要一个DAO就行了(你可以起名叫做Manager),CURD的代码也是自动获得的。比起注解的好处就是更加的灵活。 比如我们一个注册, save(user); sendMail(user.getEmail()); 这样的代码完全可以写在泛型DAO中达到DAO和Service合并的目的。 而采用楼主这样的注解形式的简化方法~碰到这样的问题,没有办法了。只能引入Service~~这不是一种简化了,并没有达到二合一的目的。只是让本来可以看起来“富”的DAO变成了一个空壳子,以前的Service还是Service。DAO不能进行任何的修改,如果修改就必须引入Service~这样的DAO是那么的“瘦”以至于变成了一种看着蹩脚的代码(嗯,那一堆一堆的getter、setter就是这样的~) |
|
返回顶楼 | |
发表时间:2008-06-17
我的认为这种简化方法不如泛型DAO直接有效。
和泛型DAO比较,问题归结在使用注解还是代码上 我在xml和注解之间的归结是: 如果是配置的内容就是用配置文件xml, 如果是代码的一部分而不是配置就是用注解。 现在是代码和注解的归结: 如果能使用代码描述优先使用代码描述,这样才合乎逻辑, 如果需要描述的信息是对代码的描述那么就使用注解。 |
|
返回顶楼 | |
发表时间:2008-06-18
感觉没有简直这回事,少了一个DAO只是把代码移到别处而已,开始可能会因为新鲜感而感到很方便,但是久了可能就会怀念以前的。其实各种构架没有纯粹的好和坏,只是某些长处和短处相互转换而已。
|
|
返回顶楼 | |
发表时间:2008-06-18
刚刚学院开毕业生会回来,昏昏欲睡,不过想清楚了一些问题。
这种构想的技术还是多在实战中用用比较好,所以我昨天晚上用来帮我的同学的毕业设计写了一个留言板,或许是我自己比较了解自己写的代码的缘故吧,觉得用Rapae还挺快...
写的过程中也总结出一些使用的技巧与规则。Service层严格避免相互调用,如果必须要自己实现的方法需要操纵数据库的,都统一通过ORM框架来完成。至于 downpour 写道
这样你就会发现,当你的Service层和Dao层合并以后,会造成你的业务逻辑层代码有多臃肿。我一直很困惑,如果一个业务逻辑方法中要包含5,6次的复杂数据库操作,你如果不搞个Dao,你的Service层代码很可能会瞬间超过1000行。
所说的问题。我认为是简单问题复杂化了。现在的ORM框架操纵数据库都非常简洁。基本上很少出现超过1000行的代码,如果真的出现了,那真的也是这条业务非常繁琐了。
roy042 写道
结合自己经历过的一个项目的体验,我觉得比较合适的做法是DAO层使用接口,DAO的实现类只封装数据库操作,而在Service层中处理业务逻辑。DAO层之间不相互调用,而由Spring向Service中注入要使用的DAO。
... 而如果DepartmentManager要操纵User,则注入UserManagerImpl,而并不是注入UserDAOImpl。 这样的做法以前我也迷茫过,不过后来实践中我发现一个问题:如果DepartmentManager需要操纵User做UserManager接口没有定义的业务,那这个模型要实现起来就必须要为UserManager暴露出很多没有必要的public method;而且将会束缚UserManagerImpl类的维护人员:他们不仅要测试UserManagerImpl,还得测试使用了这个接口的所有Manager!
虽然我在前面曾经说过: vlinux 写道
如图2所示。Service层不再相互独立,相互的调用使得整个Service层紧密的耦合在了一起。我不得不承认修改一处业务逻辑的方法非常很有可能会导致其他业务模块的改变。但是这样的确加快了我的开发效率。
但是同时也认为这是一种不好的行为。
也正如 aninfeel 所说,我也越来越觉得这更像是一种玩具了。只不过之前我们是这么玩,现在腻烦了换个花样玩,而且这个花样还不一定好玩罢了。 aninfeel 写道
感觉没有简直这回事,少了一个DAO只是把代码移到别处而已,开始可能会因为新鲜感而感到很方便,但是久了可能就会怀念以前的。其实各种构架没有纯粹的好和坏,只是某些长处和短处相互转换而已。
感谢和我一起讨论的所有javaeyer,让我看到了不足。感谢浏览过这个帖子的网友。同时我也觉得,我作为一个毕业生,参加的实际项目实在是太少了。要做出一个不像玩具的玩具,还是得经受更多的磨炼。当然,我不是想将这些代码变成一个框架,现在大家所学的框架已经够多的了,而且我也没这个资格。我只是希望能和大家更多的分享从 构想 -> 设计 -> 实现 -> 应用 的快乐。谢谢大家的支持。
顺便B4一下我的学院,为啥毕业论文的格式要求比Compiler还严,我已经重新打过不下5次了,气愤。
|
|
返回顶楼 | |
发表时间:2008-06-18
roy042 写道 结合自己经历过的一个项目的体验,我觉得比较合适的做法是DAO层使用接口,DAO的实现类只封装数据库操作,而在Service层中处理业务逻辑。DAO层之间不相互调用,而由Spring向Service中注入要使用的DAO。
比如: UserDAO,UserDAOImpl,UserManager,UserManagerImpl; DepartmentDAO,DepartmentDAOImpl,DepartmentManager,DepartmentManagerImpl; 其中UserManagerImpl中注入UserDAO的实现类UserDAOImpl, DepartmentManagerImpl中注入DepartmentDAO的实现类DepartmentDAOImpl, 而如果DepartmentManager要操纵User,则注入UserManagerImpl,而并不是注入UserDAOImpl。 这样可以将业务逻辑与具体的数据读写操作剥离。 1.没那么容易剥离,完全剥离的话很容易产生性能问题。 2.既然orm已经封装了基础crud,就在dao里写业务逻辑好了,单表的业务逻辑,没什么不好。 强调一点,业务逻辑CRUD不是基础CRUD,例如新增人员时,年龄小于5岁或者来自于日本的都不让注册或者数据库里已经有同名的用户名了,都抛出异常。这种代码就是业务逻辑,写在dao里面再合适不过了。 多表的放到ServiceImpl里去。 |
|
返回顶楼 | |
发表时间:2008-06-19
对于简单的操作,比如那个getCustomer(),用范型的DAO足够了。没看出你的改动简化在那里,还会带来其他一些问题,比如测试业务方式的时候,很难替换持久化层。
对于业务复杂的操作,DAO和Service整合到一起以后,会导致业务方法实在太复杂了。 在我涉及到的领域(电信的信息系统和GIS系统),你的所谓弱化毫无价值。在其他领域的情况我不了解,不好说。 个人感觉帖主在有了一定的商业项目实践经验以后再来看这个问题,可能会有截然不同的看法。 |
|
返回顶楼 | |
发表时间:2008-06-19
Frederick 写道
测试业务方式的时候,很难替换持久化层。
这个我写TestCase的时候遇到了,确实不能模拟DAO单独测试Service,只能在@Before、@BeforeClass的时候创建测试用的数据,然后再在@After、@AfterClass中进行清理。
写完这个帖子至少也让我明白Service与DAO层在项目中还是各自有各自的用途,谢谢。我现在也不再拿它来简化我在工作中遇到的Service,只是退一步简化DAO而已。 不过我打算会为以后接私活的时候考虑用来替换Service,毕竟那些小项目的业务逻辑都非常简单。 |
|
返回顶楼 | |
发表时间:2008-06-20
roy042 写道 结合自己经历过的一个项目的体验,我觉得比较合适的做法是DAO层使用接口,DAO的实现类只封装数据库操作,而在Service层中处理业务逻辑。DAO层之间不相互调用,而由Spring向Service中注入要使用的DAO。
比如: UserDAO,UserDAOImpl,UserManager,UserManagerImpl; DepartmentDAO,DepartmentDAOImpl,DepartmentManager,DepartmentManagerImpl; 其中UserManagerImpl中注入UserDAO的实现类UserDAOImpl, DepartmentManagerImpl中注入DepartmentDAO的实现类DepartmentDAOImpl, 而如果DepartmentManager要操纵User,则注入UserManagerImpl,而并不是注入UserDAOImpl。 这样可以将业务逻辑与具体的数据读写操作剥离。 我也在一直是用这种做法,感觉比较灵活,直观层次分明. |
|
返回顶楼 | |
发表时间:2008-06-26
liubaoshan 写道 roy042 写道 结合自己经历过的一个项目的体验,我觉得比较合适的做法是DAO层使用接口,DAO的实现类只封装数据库操作,而在Service层中处理业务逻辑。DAO层之间不相互调用,而由Spring向Service中注入要使用的DAO。
比如: UserDAO,UserDAOImpl,UserManager,UserManagerImpl; DepartmentDAO,DepartmentDAOImpl,DepartmentManager,DepartmentManagerImpl; 其中UserManagerImpl中注入UserDAO的实现类UserDAOImpl, DepartmentManagerImpl中注入DepartmentDAO的实现类DepartmentDAOImpl, 而如果DepartmentManager要操纵User,则注入UserManagerImpl,而并不是注入UserDAOImpl。 这样可以将业务逻辑与具体的数据读写操作剥离。 我也在一直是用这种做法,感觉比较灵活,直观层次分明. 正好热点中另有一个循环依赖的问题,DepartmentManager和UserManager不宜互相依赖。 http://www.iteye.com/topic/205271 针对这个例子把我的建议再阐述一下: 1.DAO和Manager合并,manager中的单表业务应该是被复用的。 2.上面说到复用,被谁复用呢,被service复用。只能在service中注入manager。 3.你可以说,你的DAO相当于我说的Manager,你说的Manager相当于我说的service,不一样,我认为一般情况,可以约定不允许在service中注入service。“只能在service中注入manager”。 |
|
返回顶楼 | |