锁定老帖子 主题:domain model的延伸讨论
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-03-03
我感觉java实现充血型模型有难度关键是:
一方面,如果使用ioc,则由于entity bean是不受ioc管理. 另一方面,Java实现的domain如果能够象ror的domain继承类似于ActiveRecord那样的来实现持久化,就会向ejb那样被人指责 依赖于具体的框架,具有不可携性,很难移植... 而rails则不会,因为ruby只有rails,没有形成真正的平台,况且rails足够好,框架的侵入性没有什么不可接受的. |
|
返回顶楼 | |
发表时间:2007-03-03
很漂亮的实现,不过仍然有问题。
1.kind只是一个字典表,而现在却被扩充为很庞大的DomainModel,这个从业务分析的角度来说是不太自然的 2.processing_task这个业务逻辑已经在user,task,kind这三个类中都出现了,这样做是否合理?是否可以重构?重构以后是否会破坏DomainModel? 3.指定用户user的统计当月总的任务数,已完成任务数,未完成任务数 all_tasks, processed_tasks, processing_tasks = kind.tasks.current_month_tasks(user) 这个为什么是kind的领域逻辑而不是user的领域逻辑? 比如写成user.tasks.current_month_tasks(kind) 越复杂的关系运算就越难归结为某个DomainModel的领域逻辑,虽然ruby在这点上比java强,但是强的也有限。 |
|
返回顶楼 | |
发表时间:2007-03-03
昨天晚上就为这个话题在网上逗留了许久,今天再一看发现robbin同学很是快手,把这个话题又重新整理了一遍,真是辛苦,虽然争论依然激烈,不过很多问题也得到了澄清,看着各位大侠在场上刀来剑往,我想在这里说上几句:
1.这个问题的来源是fatzhen发的一个名为"主题: 为什么java里不能把域对象和DAO合并,rails里面就可以?",原贴子的地址是http://www.iteye.com/topic/56949。 2.在这篇贴子里,robbin还提到了另一篇精彩的文章叫“完美就是生产力”,一位老兄在半夜挑灯夜战抽烟搞出来的一篇文章,我建议参与讨论的网友如果对ruby不够了解的去看看,我看了后是很有收获的,很多背景问题(因为我是搞java的,rr只是搞了些皮毛)能搞清楚。 3.讨论的问题还是域对象模型在两种语言中的支持和实现优劣,而不是某某要取代某某。 4.域模型比oo模型要高级,对业务的描述性更好,也利于业务的计算实现,rr对域模型的支持和实现我认为是要优于java,但是,java也未必需要如rr一般的方法去实现域对象模型,正好比一个使刀的,一个用剑的,没必要说非得弃剑用刀或者弃刀用剑,尤其是java语言和rr语言在本质和风格上面相差太大。 5.代码强阅读性和LOC少是rr的最大热点,当然ActiveRecord做得也是非常不错,但是Java同样有很多出色的优点。 6.贫血模型还是涨血模型,我看还是根据实际应用来论,robbin也对这个问题做了分析,我也不多说了,我认为分析得还是很到位。 7.既然是刀来剑往,我想没有一个人能够100%保持彬彬有礼的形象,出言不逊在所难免,但是既然都是武林中人,能够互相切磋技艺心法,实在是人生之幸事,那些激昂言语也大可在一笑中抛诸脑后。 |
|
返回顶楼 | |
发表时间:2007-03-03
再放一箭 楼上的朋友说话和其照片让我感觉很相辅!
多谢robin等的耐心讲解,thinking |
|
返回顶楼 | |
发表时间:2007-03-04
如果单从语言层面上看,我觉得两者没有什么可比性,两者都是比较好的OO语言,不过ruby可能更灵活更动态而已。
在实现Domain model上,ruby也是借助于rails(对ror还不是很了解),那么java借助于hibernate/jdo来实现这样的模型应该也不是什么大问题 |
|
返回顶楼 | |
发表时间:2007-03-04
前面有一篇关于充血模型还是涨血模型的讨论我也看了,涨了不少见识. 感谢各位的精彩讨论.
|
|
返回顶楼 | |
发表时间:2007-03-04
fuliang 写道 我感觉java实现充血型模型有难度关键是:
一方面,如果使用ioc,则由于entity bean是不受ioc管理. 另一方面,Java实现的domain如果能够象ror的domain继承类似于ActiveRecord那样的来实现持久化,就会向ejb那样被人指责 依赖于具体的框架,具有不可携性,很难移植... 而rails则不会,因为ruby只有rails,没有形成真正的平台,况且rails足够好,框架的侵入性没有什么不可接受的. Java难于实现充血模型的根本原因还是在于:Java是静态类型的语言,难以运行期任意的动态改变其行为,所以必须依赖外部容器例如IoC进行对象依赖组装,也必须依赖特定的ORM框架进行增强其行为,这些容器和框架本质上都是通过动态代理方式来增强类,其结果就是对象的设计必须符合容器对它的要求,从而限制你追求理论上更完美模型的可能性。至于继承不继承类,这个根本无关紧要。 不知道大家有没有想过,为什么Java这么强调面向接口编程?面向接口编程为什么对Java这么重要?但是对于动态面向对象语言ruby来说,却根本不需要接口这种概念。这是因为在Java中是类型决定行为,所以类型的地位很重要,你一继承,对象的行为就被限制死了,所以Java很忌讳继承的使用;但是ruby的类型不决定行为,所以随便你怎么继承,也不会限制对象的行为。 技术的进步会影响到理论的实现和普及。在Java世界ORM流行之前,要对持久层进行对象建模,根本不切实际。我在2003年之前都是采取类似iBATIS的方式建模。 03年ORM开始流行,自从ORM框架逐渐成熟以后,人们可以开始在持久层进行对象建模了,这个时候Martin Fowler又说你们的模型是贫血的,必须给模型充血。04年的时候老马这么一说,着实让我们烦躁了一阵。你说要充血,可我们手里根本就没有输血的工具阿,何况我们贫血模型也用得挺好阿,干吗要充血? 05年以后RoR开始逐渐被人关注。这个时候我们发现原来RoR才是真正适合充血模型的工具。在RoR的支持下,充血模型果然可以玩的有声有色,所以我们也开始逐渐接受充血。 |
|
返回顶楼 | |
发表时间:2007-03-04
robbin 写道 ..... Java版本的实现代码大家都比较熟悉,因此绝大部分代码都省略了。Java版本需要3个持久对象,3个映射XML文件,3个DAO接口和实现类,4个Service和实现类,和一个IoC的bean组装文件,总共21个文件,全部逻辑写完整,代码行数至少上千行。 不要把Java一棒子打死吧, TOB上的充血模型也是Java的, 哪里不好请指点出来, 否则还是说 "主流Java实现" 比较合适. robbin 写道 通过对比,我们可以看到Java比较流行的实现是贫血的模型,按照面向对象的基本原则,对象的状态应该和它的行为封装在一起,因此Java多出来的这些XXXService是一些从纯理论角度而言应该放入其相应的持久对象中去。但是Java实现充血模型从技术上有一定的难度,如何Service方法挪入到持久对象中呢?如何解决Dao的注入问题?如何解决domain logic方法的事务封装问题?前者可以通过AspectJ的静态织入来解决,后者也许可以通过织入或者annotation声明来解决。但不管怎么说,Java从技术上很难实现充血模型,而且即使实现充血模型,也会导致一个Java类好几百行代码的状况,其代码的可阅读性,模块解藕能力都会变得很差,因此我们认为Java不适合充血模型,在表达复杂的业务逻辑的能力上,Java要比ruby差很多: 用TOB的话, 开发者只需要关心自己的代码, 就是我给出的那么多, 没有混局的代码呀. 其余有些是在编译应用代码的时候把所有需要的额外逻辑都自动生成出来的, 不需要关心, 而且不改动应用类bytecode, 只要子类有权访问就不用反射, 可以说对运行期效率基本没有影响. 编译时速度有些影响, 但是不影响在IDE中开发时的自动提示, 重构和其它辅助功能, 编译上稍微多花点时间应该可以接受吧, 换来的是运行期比Hibernate快几倍到上千倍的效率. robbin 写道 附件是完整的RoR版本的项目示例代码。要运行它,需要安装MySQL数据库(InnoDB表类型),Ruby和Ruby on rails环境。在MySQL数据库中分别创建demo数据库和demo_test数据库,修改demo\config\database.yml中的MySQL数据库配置,改成你的数据库密码。然后在项目跟目录下面执行: rake db:migrate rake db:test:clone_structure rake test 即创建开发环境数据库,创建测试环境数据库,和执行所有的单元测试。领域模型代码位于demo\app\models目录下面;单元测试代码位于demo\test\units目录下面 用RoR数据库还要自己建, 这点我自认TOB做得更好, 只要配置好连接参数, 运行期TOB会自动创建或者扩充数据库表结构, 应用开发人员只需要创建和修改Java源码, 编译后直接运行就可以了. |
|
返回顶楼 | |
发表时间:2007-03-04
to complystill:
我没有仔细看TOB的实现,TOB相当于构建一个内存当中的对象数据库,这种编程模式和主流的基于关系数据库直接驱动的web项目差别比较大。 rails是由DB schema来动态决定对象的状态。在development环境下,任何对数据库的修改都立即会改变对象的状态行为。这和Hibernate由映射文件来动态生成数据库DDL正好反过来。但不能说谁好谁不好,在TOB中你能一改数据库schema,不需要重起应用服务器就让对象的property立刻随着改变吗?也做不到不是。 |
|
返回顶楼 | |
发表时间:2007-03-04
呵呵, 所以是 "主流Java" 的问题, 而不是 "Java的问题" 嘛.
TOB的应用持久类改变以后, 不需要重启应用服务器呀, 热重新部署以后就可以让数据库表结构跟着更新, 这个不是更OO Centric么? 我觉得更好啊. |
|
返回顶楼 | |