Kuberski - 酷伯司机

写在代码边上
posts - 14, comments - 118, trackbacks - 4, articles - 1
  博客园 :: 首页 ::  :: 联系 :: 订阅 订阅 :: 管理

回复:什么是ActiveRecord

Posted on 2008-05-09 10:23 kuber 阅读(1445) 评论(24)  编辑 收藏
我在 前一篇文章中提到ActiveRecord, 有人在回复中问什么是ActiveRecord. 说实话,从去年开始用SubSonic, 我就一直有点困惑, 什么是ActiveRecord, 什么不是ActiveRecord, 以及应该怎么样使用它才对. 把我的一些想法写下来, 希望能和大家交流. 欢迎拍砖.
ActiveRecord
是什么:
1. 每一个数据库表对应创建一个类.类的每一个对象实例对应于数据库中表的一行记录; 通常表的每个字段在类中都有相应的Field;
2. ActiveRecord同时负责把自己持久化. 在ActiveRecord中封装了对数据库的访问, 即CRUD;
3. ActiveRecord是一种领域模型(Domain Model), 封装了部分业务逻辑;

ActiveRecord不是什么:
1. Row Data Gateway
Row Data Gateway模式中每个对象也封装了数据库记录的状态和持久化到数据库的访问方法; 这两个有时候很难区分. 细微的区别在于Row Data Gateway不封装任何业务逻辑;

2. TableGateway
TableGateway是一种数据访问模式, 对每个表有一个类, 类的方法封装了对单个表的数据操作, 如CRUD; 方法的接受表字段的值作为参数;
比如说对表Person有DAOPerson, 有以下方法:
int Create(string name, bool isMale)
DataSet Find(int personId)
void Delete(int personId)
void Update(int personId, string name, bool isMale)
微软的很多代码示例中使用了此模式;

ActiveRecord的区别在于ActiveRecord的对象中保持了记录的值, 是有状态的, 而TableGateway是没有状态的, 只是一系列数据库访问方法的集合;

3. Table Module
Table Module是一种领域逻辑模式, 一个类对应于数据库中的一个表; Table Module通常和Table Gateway合作, 前者负责基本的业务逻辑, 后者负责数据库访问, 以达到逻辑层和持久化层的隔离; 微软的实例代码经常使用这两者, 如对表Person, 通常会定义两个类, PersonBL和PersonDB, 在PersonBL中处理验证等逻辑, 并调用PersonDB访问数据库, 层间调用使用DataSet或自定义数据传输对象传输数据

在业务逻辑比较简单并且有和表的一一对应时, ActiveRecord相对来说更简单, 因为它在一个类中包括了业务逻辑对象和数据访问, 而且不需要数据传输对象, 减少了维护的工作量;
和Table Module比较起来, ActiveRecord与数据库耦合更紧;

ActiveRecord适用于:
1. 业务逻辑比较简单;当你的类基本上和数据库中的表一一对应时, ActiveRecord是非常方便的, 即你的业务逻辑大多数是对单表操作;

2. 当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script), 把跨表事务提升到事务脚本中;

3. ActiveRecord最大优点是简单, 直观; 一个类就包括了数据访问和业务逻辑. 如果配合代码生成器使用就更方便了;

4. 这些优点使ActiveRecord特别适合web快速开发, 而正是快速开发框架ROR采用了ActiveRecord, 并且很多类ROR框架如Castle的纷纷效仿才使ActiveRecord重新进入大家视线;
我想这也是为什么Martin Fowler在PoEAA中早就提出了这个模式, 但是直到最近两三年ActiveRecord才热起来可能就是这个原因;

ActiveRecord不适合于
1. ActiveRecord虽然有业务逻辑, 但基本上都是基于单表的. 跨表逻辑一般会放到当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script)中. 如果对象间的关联越来越多, 你的事务脚本越来越庞大, 重复的代码越来越多, 你就要考虑Domain Model + O/R Mapper了;

2. ActiveRecord保存了数据, 使它有时候看上去像数据传输对象(DTO). 但是ActiveRecord有数据库访问能力, 不要把它当DTO用. 尤其在跨越进程边界调用的时候, 不能传递ActiveRecord对象;
Tag标签: activerecord

Feedback

#1楼    回复  引用  查看    

2008-05-09 10:55 by Clark Zheng      
关注一下

#2楼    回复  引用  查看    

2008-05-09 11:04 by 怪怪      
不错, 很准确, 赞一个。

另外, 这个模式只是在POEAA中介绍过, 并非Fowler提出的(其实Fowler这辈子, 基本没提出过什么自己的东西); 这种用法也早就普遍存在了, 只是最近一热炒, 就被人为放大了。

不过我个人认为,ActiveRecord虽然提供了便利性, 同时也会带来思维方式和实践方法上的禁锢和负面影响, 所以并不总是提高, 有时也会降低生产效率。这是因为从根本上讲, 有时候我们并不真的需要一个有着固定接口的对象或者类。

回头说到SubSonic, 说实话其作者可能比园子里一些做框架的同志水平还菜很多, 但是SubSonic在很多场景下确实轻量、好用, 这反而是我们的同志应该好好思考的了。

#3楼    回复  引用  查看    

2008-05-09 11:56 by wanghualiang      
@怪怪
为什么说作者水平菜?
是代码写的有问题还是架构不是很合理?
没看过源码,但用在项目上了,很简单很好用。

#4楼    回复  引用  查看    

2008-05-09 12:08 by 金色海洋(jyk)      
好久没见到怪怪了。

#5楼    回复  引用    

2008-05-09 12:26 by jackyw [未注册用户]
SubSonic提供了很好用的代码生成工具,框架也比较轻量级
是比较好的实现了ActiveRecord模式的框架

#6楼    回复  引用  查看    

2008-05-09 12:56 by lovecherry      
在SubSonic之前也看到过buildprovider做orm的demo,但是SubSonic对作者把它做成了产品

#7楼 [楼主]   回复  引用  查看    

2008-05-09 13:37 by kuber      
@怪怪
任何方法都有其要解决的问题域, 我想是因为最近两年Web 2.0热导致的快速的web应用开发大行其道使ActiveRecord被重新注意了.

另: 好久没有看见怪怪有新的文章了. 我很喜欢"闲言碎语"这篇文章. 不过里面好像还有很多未竟之言, 我还等着下文呢.

#8楼    回复  引用    

2008-05-09 13:44 by designbeauty [未注册用户]
第一次听见有人说Rob菜的。。。,那正常的人应该是什么水平。
btw. subsonic真的很好用很强大。 楼主可以分享一下经验

#9楼    回复  引用  查看    

2008-05-09 15:10 by 怪怪      
@金色海洋(jyk)
没时间啊..., 而且感觉江郎才尽, 白活不出什么有价值的内容了。 倒是今天早上无缘无故的感觉到一阵喜悦, 似乎有些事更明白了, 但暂时又说不清楚明白了什么。 反正接触的东西越多, 感觉需要学的东西和需要做的工作就更多了。

@kuber
嗯, 可以这么说。 不过其前提是在面向对象或者基于对象的设计和实现方式下。 我对AcitveRecord、 Row Data Gateway、 DTO等等一些方法的质疑, 实际上更多的是针对面向对象的一些痼疾了。

比如就这种CRUD较多的场景, 不采用这些方式, 很显然光写代码时的类型转换, 和数据字典存取的安全性和便捷性, 就够我们一呛。 而采用这些方式呢, 通过对象我们就得到了一组固定的接口, 要么接口太多, 要么接口太大, 且不说什么性能和维护的问题, 损失掉的灵活性和直接性也非常可惜; 如果再通过新增接口去适配不同的场景, 除了显配一下自己的面向对象功力, 很多时候只是徒增麻烦。

只是我也仅仅在探索阶段, 说些怪话的目的只是抛砖引玉, 呼吁大家一起来看看有啥新的路子没有, 而不是局限于过去那些旧的观点和争论。那篇文章之所以写不下去了, 关键是在现有的语言框架下, 我还没找到能完全满足我的想法的设计和表达方式, 感觉还需要琢磨一阵子。 如果仅仅是一些小的改进, 感觉说起来也没啥意思~

@designbeauty
呵呵, 菜不菜的也要看那些方面。 我是指对概念的理解和掌握的技巧这两方面。 我看过他的一些Video, 说实话此人对很多概念是相当的模糊; 也用过和改过一阵子SubSonic,这个东西涉及的技巧也绝对比不上园子里一些高手的东西。

不过就像@lovecherry说的, 人家在做产品这一块, 可一点也不菜, 我还是相当的佩服的。另外, 去你网站看了, 很漂亮啊, 至少我很喜欢这种风格, 唉感觉设计还是比技术需要更多的天赋。

#10楼    回复  引用  查看    

2008-05-09 16:34 by good man      
其实在这里我们应该对别人多鼓励,不能说菜不菜,你应该
把别人的错误找出来,达到共同学习,一起进步啊

#11楼    回复  引用  查看    

2008-05-09 16:37 by RicCC      
ActiveRecord的主要优点是一个过渡模式,当你没法从失血一步走到充血模型,或者不大确定是否该这样做时,是一种比较好的选择
另外就算使用充血模式的复杂项目,还是会存在很多适合ActiveRecord的对象
我想当你ActiveRecord使用熟练之后思路应该会不大一样,选择范围会比较开阔

#12楼    回复  引用  查看    

2008-05-09 17:07 by 怪怪      
@good man
哈哈, 这不是个老外吗, 他又不会跑博客园来, 跑来也不认识中文~ 另外, 我一向对名人比对咱一般的兄弟要求严格的多, 可以说刻薄了~

@RicCC
写的比较乱, 重新编辑一下, 两点:

1. 在面向对象这个大前提下, AcitveRecord、 Row Data Gateway、 DTO等形式是否是必要的。

是不是一定要将数据包裹以任何一种形式的对象的方式来处理, 我觉得也是可以有多种判断方式的; 比如对于最简单的CRUD系统,或许可以根据在于我们在展示与持久之间, 需要(比如各种逻辑包括业务逻辑产生的)手工编码操作数据的次数(和工作)来进行选择? 如果在其它地方下功夫(如操作和流程的自动化),可以使得没有对象化而导致的问题小于一个限度, 我们也许就没有必要对象化。

这个问题的根本在于首先要确认我们手头的这个活儿,是否在大模型(不是我们常说的模型)上真的需要将数据对象化, 还是可以用其它模型更好的解决。

2. 如果其实现的核心不是面向对象特性, 比如说利用FP的特性, 或者在支持TMP的语言里。

如果我能得到使用某一方式方法的一切好处, 避免它基于面向对象实现时的缺陷, 根据其特征, 也许各种方式方法还可以分别叫做 AcitveRecord、 Row Data Gateway、 DTO, 但由于不再带有面向对象令人不爽的阴暗方面, 那么也许进行选择和判断就容易的多。

如果能够做到, 而且成本很低, 那么也许我们可以忽略这个问题, 长期的按一定规则使用某些方式方法, 这样就可以更加集中注意力解决其它问题。

#13楼    回复  引用    

2008-05-09 18:25 by gakaki [未注册用户]
贴一篇DDD领域模型
http://www.umlchina.com/Chat/ddd2006.htm

#14楼    回复  引用    

2008-05-09 18:26 by gakaki [未注册用户]
在贴一篇 javaeye写的robbin
领略一下ruby的DSL能力
http://robbin.javaeye.com/blog/77223

#15楼    回复  引用    

2008-05-09 18:28 by gakaki [未注册用户]
domain model的延伸讨论
http://www.javaeye.com/topic/57075

#16楼    回复  引用  查看    

2008-05-09 20:02 by 怪怪      
@gakaki
老哥, 你翻出来的这些陈仓子烂谷子都是啥啊...

比如某人说的那些, 其实根本不是ruby的能力, 而是rails的能力。 当然在静态语言里实现一个能像RoR的ActiveRecord那样好用的东西比较难, 同时即使实现了一个比较好用的东东, 接下来的工作量中很多也是繁文缛节的废话。

问题的关键是动态语言也具有不了静态语言的优势。 如果我更看重静态语言的能力, 除非你拿把枪逼着我, 我绝对不会选择一门动态语言 + 测试的方式。 在我看来至少在目前, 这种方式无论多少人煽惑, 从根本上讲也没有形成构建可靠的软件的基础。

当然, 别人的想法可能和我不同, 也许别人也是对的; 但是假设比如某人选择了RoR, 那么他也不会碰到静态语言比如Java产生的问题不是很自然的吗? 拿出来弄个擂台, 这种无聊的、 没有结果的叽叽喳喳除了彼此不爽, 又有什么价值呢? 根本性的选择方向的不同所导致的碰到的问题不同, 就只能从最初的地方解决; 可问题是那样的论题更大, 是很难说清楚的。

你看看他们这种讨论, 解决了Java固有的问题吗? 所以说实在的, 你贴的某站和某些人的这堆东西, 不怕得罪某些人地说里面噪音居多含金量相当小。 各自解决各自的选择可能产生的问题得了,何必争论不休呢?

我对某些有既定价值观的同志拿某站的东西到别处让大家“领略”一下的做法, 一向是非常反感的; 因为某站一些人的宣传和讨论,对那些的思考没有超出这种讨论水平的人来说, 我个人认为非常的容易中毒。 另外Martin、Kent说的大家是不是应该全盘接受还有待商榷, 更何况一群嚼舌根的二次加工的产物了。

比如什么DSL、DD,纯净的DDD是不是某人拿出来的这种东西还另说呢。 那个讨论里不是有人就提出某人是“伪domain”么? 你作为一个读者, 又觉得谁更又道理呢?我觉得在基础认识和思考形成自己的风格之前, 即使在自己喜欢的话题上, 去看他们这种论战唯一的作用也只是多走弯路, 甚至造成暂时的选择性失明。

我的想法是, 应该关注和思考如何解决自己面对的各种问题, 而不是去嚼剩饭。 你也可以看看某站这些讨论都是什么年代的, 一般越百花齐放越热闹, 年代就越早, 也就是说那会儿他们的水平一定比现在差。 于是也就可以推出个人水平和对这些东西的热衷程度之间的关系了。

#17楼    回复  引用  查看    

2008-05-09 20:09 by 金色海洋(jyk)      
@怪怪
我想写一个“表单控件”,目的就是针对 简单的表的添加、修改的,要快速的实现,而且几乎不用编码。

近期想写一下,希望多提宝贵意见,谢谢。

#18楼    回复  引用  查看    

2008-05-09 20:18 by 怪怪      
@金色海洋(jyk)
得了, 还是回我blog上说吧, 我是走到哪儿, 污染到哪儿... 我把我MSN站内短消息给你。

#19楼    回复  引用  查看    

2008-05-09 21:04 by hxm      
http://hideto.javaeye.com/blog/92156" target="_new">http://hideto.javaeye.com/blog/92156

Rails宝典之第二式: 动态find_by方法,这个就是你说的没有办法做的原因,动态语言是破坏性的,但不一定实现不了,不是有BOO吗
http://hideto.javaeye.com/blog/105380

这才是主题

Rails源码研究之ActiveRecord:一,基本架构、CRUD封装与数据库连接
http://hideto.javaeye.com/blog/92156" target="_new">http://hideto.javaeye.com/blog/92156
你的文章恰恰说明你在看着rails哦



#20楼    回复  引用  查看    

2008-05-09 21:12 by hxm      
我说那么喜欢ROB的话 一起翻译他的BLOG吧

#21楼    回复  引用  查看    

2008-05-09 23:39 by RicCC      
@怪怪
如果不是极尽所能的去利用面向对象的各种手段,应该不会碰到它的缺点

有很多人极力的挖掘面向对象的概念,去实现"复杂业务"和"扩展性"、"伸缩性"、"可靠性"、"维护性",而另一手却高举"没有银弹"的旗帜
很多的设计者对业务设计的关注几乎为0,结果是研究透了设计模式、重构、面向对象等方法却还是做不出好项目、好产品,而对各种问题的本质却可以夸夸其谈

这样的场景下什么方法、思想都没用

#22楼    回复  引用  查看    

2008-05-10 00:12 by RicCC      
@怪怪
结构化设计和面向对象设计之间的话题太大了,这里大部分人用.net开发应该面向对象的倾向会多一些。不同开发语言的特长和最适用的开发模式、应用环境都不一样,要综合各家优点适用于各种场景也不大现实

我理解你说的意思,各种方法论、实现方式都是力图解决后面的本质问题,回过头来这些本质问题的解决方法决不局限于单纯的某种方法论或实现方案,采用不同的视角看问题,可能他们之间本身也是相通的。基于复杂度方面考量,我比较倾向于中庸之道,ActiveRecord是符合这种精神的

poor model->ActiveRecord->rich model这样一个路线走下去,很可能就是走上EJB的路子,以及对rich model优劣的讨论是否该回归poor model,不管是应用能力还是方法论水土不服带来的问题,在我看来复杂度过高就代表着不合适,或者得异常关注确信可以克服
另外 ActiveRecord并不妨碍poor model设计思想,甚至是基于RecordSet的结构化设计思想,并且的确可以带来编码上的便利性、一致性,尤其是对.net这个平台而言。而在的确需要rich model的场景下也可以方便的应用。中庸之道的好处就是随时随地可以两边倒,面对各种需要处理的场景可以灵活运用,这是我认可的优点

FP我不大了解,原本结构化设计思想就是不错的方法,面向对象的流行和普及现在不少人已经看到了它不适应的状况,因此我比较怀疑FP是不是又走了另外一个极端,来一个大规模的运用遇到的问题可能不亚于面向对象方法。不过确实在某些方面能够运用一些FP的特性的确是好事情,正如在该使用面向对象、设计模式的场景它的确能够带来极大的优点

#23楼    回复  引用  查看    

2008-05-10 10:24 by 怪怪      
@RicCC
是啊, 没有出发点的方法和思想, 除非有一天编程发展为数学那样形式化的东东, 否则毫无意义。

FP我觉得注定不可能走向极端, 因为它不好用的地方太明显了...。 我就是担心如果各种编程范式都融合在一起, 这对我这样兴趣在此、 时间充裕的人仍然需要耗费大量精神, 学习成本是不是又陡然增加了?

#24楼    回复  引用    

2008-05-15 10:09 by Matt [未注册用户]
Dude..先留个名,看了。。you blow my mind

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-06-11 12:18 编辑过
 
另存  打印