我对NHibernate的感受(2):何必到处都virtual

  上一篇文章主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了。NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是virtual的。请注意这里的要求有两个细节:

即使是方法,也必须标记为virtual 即时是不和数据库有映射关系的属性,也必须标记为virtual

  这就让我觉得无厘头了,为什么没有任何关系的东西也要受到限制?我知道NHiberante要求将属性标记为virtual是为了延迟加载,因为只有这样它才能生成如上一篇文章中那样的延迟代理类,这样就可以实现只在第一次访问属性的时候才进行“加载”操作,从而访问数据库并获得数据,再填充字段。不过我认为这也不是合适的理由,因为这又关没有映射的属性,甚至方法什么事情呢?我在很长一段时间内一直没有想明白这个问题。

  直到看了NHibernate开发团队成员Davy Brion的文章《Must Everything be Virtual with NHiberante?》之后,我才了解了他们的设计思路——虽然我还是不认同。我真的不喜欢到处virtual。

  要求类中所有的公开成员(public/protected)都是virtual,是因为NHibernate想要保证在“访问任何公开成员”之前,数据已经被加载了。也就是说,无论您是想调用它的ToString方法,还是您自己写的辅助方法/属性,在真正进入您自定义的逻辑之前,数据肯定已经存在了——例如,存在于私有的域字段中:

public class Article{ private string m_tagNames public virtual string TagNames { get { return this.m_tagName; } set { this.m_tagNames = value; } } public void DoSomethingWithTagNames() { Console.WriteLine(this.m_tagNames); }}

  虽然NHibernate可以在TagNames属性第一次访问时加载数据,但是如果我们的DoSomethingWithTagNames方法直接访问m_tagNames字段,数据自然无法加载了。因此,NHibernate必须确保有能力在代理类中覆盖DoSomethingWithTagNames方法才行。这就是virtual方法的由来。

  但是在我看来,我们真的有多少情况会去访问私有字段呢?事实上对于大部分情况,我们会使用C#中“自动属性”特性来定义属性,这样自然只有属性,没有字段。即使我们使用了自定义的私有字段来保存属性的值,NHibernate也可以“叮嘱”我们应该访问属性,而不要直接访问私有字段——其实在编程上两者并没有差别。现在这样被强迫的感觉不好。

  不过昨天我忽然想到,这似乎也是可以理解NHibernate这么做的原因:因为Hibernate要照顾到Java语言开发人员的使用感受——请注意是Hibernate,没有N。不管怎么说,NHibernate是从Hibernate移植过来的。NHiberante的主力开发人员Oren Eini曾在博客中写道(可惜一时没找到),NHiberante刻意与Hibernate的实现保持同步,这样容易进行双向的同步,例如Hibernate解决了一些bug或性能问题,也可以较为轻易地在NHibernate上修补。

  不过这还是没有解释为什么Hibernate要一切都是virutal的原因啊。其实您只要看一下这段Java代码就应该明白了:

public class Product{ private String m_tagNames; public String getTagNames() { return this.m_tagNames; } public String setTagNames(String value) { this.m_tagNames = value; }}

  这是上面C#中Product的等价Java代码。由于Java里没有“属性”概念,因此Java语言自身一直有一个“约定”:getXxx和setXxx两个方法即为一个属性。这个约定用在很多地方,如IDE就会把它当作是一个属性方便设置及导航,框架在进行序列化时候也知道哪些东西是“属性”。这“约定”本没有问题,但是这就给Java开发人员造成了一定困扰:使用起来实在是太麻烦了。例如,Product有个属性叫做ViewCount,我们想要把它加1,在C#中我们可以写:

this.ViewCount++;

  而在Java中则必须是:

this.setViewCount(this.getViewCount() + 1);

  因此,如果是你的话,在写Java代码的时候,是愿意使用getXxx()这样的方法,还是直接访问类中的私有字段?因此我认为,是Java语言的特性,导致Java开发人员倾向于直接访问类中的私有字段,从而导致Hibernate需要避免未加载的私有字段,进一步导致Hibernate的代理类会去覆盖所有的公开方法(只有方法,因为Java语言没有“属性”)——最终,由于NHibernate在“统一大业”上的策略,使得我们.NET开发人员也必须把所有成员标记为virtual,无论是方法还是属性。

  您可能会说,但也没见Java程序员嚷嚷啊。没错,因为在Java语言中,默认情况下所有的成员都是virtual的。而在.NET平台下情况正好相反。因此在我看来,我们这里必须到处标记virtual所造成的不便,和Java语言本身有着非常大联系——我们需承受Java语言所带来的痛苦。

  虽然我理解NHibernate,但这又怎能让我满意呢?

  哦,对了。在未来的Java 7中,我们可歌可泣的Java语言终于有了a –> property这样的属性访问语法了。

  可惜,迟了。

时间: 2024-10-01 22:57:02

我对NHibernate的感受(2):何必到处都virtual的相关文章

艾伟_转载:我对NHibernate的感受(2):何必到处都virtual

上一篇文章主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了.NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是virtual的.请注意这里的要求有两个细节: 即使是方法,也必须标记为virtual 即时是不和数据库有映射关系的属性,也必须标记为virtual 这就让我觉得无厘头了,为什么没有任何关系的东西也要受到限制?我知道NHiberante要求将属性标记为virtual是为了延迟加载,因为只有这样它才能生成

jsp中如何使用Fotorama,到处都找不到教程,求大侠,详细点,谢了

问题描述 jsp中如何使用Fotorama,到处都找不到教程,求大侠,详细点,谢了 jsp中如何使用Fotorama,到处都找不到教程,求大侠,详细点,谢了

事情是这样的,我刚来这个公司不久,要维护一个系统,是基于C++,CORBA的服务器系统,写的好大好复杂,仅服务器这边就有10多个进程,而且没有任何文档,没有任何说明,代码乱七八糟,没注释,说是面向对象C++编写,可全局变量到处都是,类里边全是public变

问题描述 事情是这样的,我刚来这个公司不久,要维护一个系统,是基于C++,CORBA的服务器系统,写的好大好复杂,仅服务器这边就有10多个进程,而且没有任何文档,没有任何说明,代码乱七八糟,没注释,说是面向对象C++编写,可全局变量到处都是,类里边全是public变量.现在人家客户用的时候出问题了,客户端每调用一次服务端,服务端内存就增长几十兆,而且没有任何性能测试工具可用,开发这个程序的人都走了.大家说面对这种复杂系统的内存泄漏问题,在没有性能测试工具的情况下该怎么办,怎么找出问题在哪,想用L

iOS 的块操作也可以象Java匿名类一样到处都是

iOS 的块操作也可以象Java匿名类一样到处都是 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 整理一份之前对 ASIHTTPRequest 的分类封装 今天有点累,突然想到,先留个坑,明天

到处都是坑的微信支付V3

业务需要一个在微信上能付款的功能,于是乎想到了最普遍的支付宝,坑爹的是T与A是水火不容啊,默默的还是接微信支付吧,没想到从此掉进了连环坑-- 网上写微信支付接口的还是很多,PHP官方有(鄙视源码作者,连参数对应都错了,能跑通才怪),NET版 微信支付--入门篇 这篇算是比较全的,java版. PHP的只能参考,终究还是先按NET版的还创建项目,不过文章里面也没具体写到如何前后台交互(偶用的MVC),对于初次接触的人来说只能问题来一个解决一个. 至于怎么从0开发就不用详细说明了,参考这位仁兄的 微

到处都是坑的微信支付V3之 微信支付回调页面

据上次 到处都是坑的微信支付V3 后很多园友在被虐了千百遍后终于跳转到了亲切的微信支付界面,但输入密码支付后却不知道怎么处理了,接下来补上支付后的处理流程. 1. html中根据前台支付后反馈信息成功与否跳转到相关页面 if (res.err_msg == "get_brand_wcpay_request:ok") { // message: "微信支付成功!", window.location.replace("@Url.Content("~/

探营暴雪美国总部到处都充满着游戏的色彩

暴雪娱乐是一家全球知名的电脑游戏及电视游戏软件公司,其产品包括魔兽争霸系列,星际争霸系列以及暗黑破坏神系列,魔兽争霸及星际争霸均被多项知名电子竞技比赛列为主要比赛项目.今天我们给大家带来了一段视频,为我们展示了暴雪美国总部办公室及周边环境. 视频开始部分拍摄的是暴雪所在的园区的环境,非常干净,很优雅,加上天气的原因,看上去非常适合散步聊天. 进入办公室,前台我们看到了暴雪所获得了诸多奖牌.奖杯.随后进入了一楼办公室,可以看出,暴雪是一个有着独特文化的公司,办公室的墙上到处都贴满了各种各样的精美游

到处都是口水仗,谁笑到最后

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断淘宝客 站长团购 云主机 技术大厅 成都人有个爱好,多小的事情都有人围观,所以红了新闻现场,电视台的笑了.口水仗本应该是茶铺里面无聊的人打发时间的工具,但有了麻将,所以无聊的人换了种方式无聊. 现在中国网民上亿了,无聊的人不打麻将开始上网了,所以搞网络的笑了,但是笑的都是拿到钱的,没拿到钱的怎么办呢?既然无聊的人天生爱热闹,喜欢口水仗,那就让他们打吧```       

艾伟_转载:我对NHibernate的感受(1):对延迟加载方式的误解

NHibernate是.NET平台上最著名的ORM框架,虽说出身于Java平台上的Hibernate,但是从外部看来这几乎就是一个.NET平台上的原生产品:有自己的社区,有自己的用户,有自己的商业支持,有利用C#特性的独立扩展.它不像Lucene.NET那样,一眼就能看出浓重的Java气息,Java的命名方式等等.我用NHibernate时间不长,而NHibernate的复杂程度也决定了我无法像了解LINQ to SQL那样容易.不过在使用了一段时间过后,还是对它有一定体会.有欣喜,有误解,也有