前面我有一篇随笔重复,为什么我们要不断重复讲
述的是我在项目开发中的苦恼,引发了很多人讨论,大家各出高招,有人提到ORM,按我的愚见,ORM是在应用程序的类和数据库中表及视图建立一对一关系,
例如,数据库中有表tblarticle,那么与之对应,我们可以建立一个articleItem对象来表示单条的记录,表的每个字段做为
articleItem的成员变量,对应表的insert,update,delete以及select item及select
all等存储过程,我们可以为articleitem建立对应的方法,然后在方法中用ADO.NET及对应的存储过程来完成数据的抽取,修改等.并且,我
们可以在articleitem的基础上建立articleitemcollection以表示多条记录,这样,就将单条记录的更新变成了建立一个
articleitem对象,给article对象的各种属性赋值,最后调用像articleitem,update()这样的方法来完成数据操纵的目
的.这种实现方式其实很容易令人接受,并且,如果A负责写数据存取层的话,B用的时候,几乎不用关心是在操纵哪个表,而只关心操纵的是何种对象.非常类似
我们使用.NET类库中对象一样.
可是,听起来不错,但如果真的要你去用ORM做一个项目的时候,你会发现代码量远远大于使用"传统
"的直接用ADO.NET调用存储过程的方法.虽然使用ORM可以让我们项目在以后的维护中更加容易,可是,在项目的初期,真的会拖慢开发速度,所以,很
多博客堂的朋友觉得,与其ORM,不如就用ADO.NET来
可是,ADO.NET直接操作首先带来的问题是,你的项目只能模向分隔
(比如,你可以把为一个数据库中某几个表写数据存取层的任务交给A,另外的交给B),无法进行纵向层次的分割,如果用ORM,你可以让A负责写数据存取
层,让B写对象层,让C写业务逻辑层,协作上容易的多.
既然传统方法和ORM都不是那么完美.那有没有更好的方法呢?虽然我也听说过"银弹"故事.我也相信世界上没有银弹.但是我仍然孜孜不倦的追求完美,仍然想找到合适的解决方案.
CodeSmith
这个软件在博客堂和CSDN不知道有多少人提过了.大多数的解释是CODeSmith是一个快速代码生成工具.试用后,CodeSmith给我了强烈的震
撼,假如它只是一个基于模板的代码生成工具.那么我不认为有什么了不起.可是它竟然克服了模板生成工具的灵活性不足缺陷.它在高效率和高定制性间取得了完
美的平衡.如果你没有用过他,我可以告诉你他有以下特点:
1.他可以用于生成C#,VB.NET,TSQL以及其他任何语言代码
2.他本身是可以编程的(这是他的灵活性之源)
3.他提供了强大的SchemaExplorer对象,使数据库储过程的生成非常容易
4.有了他,你不会再向我一样埋怨从一个项目到另一个项目时,需要重新写许多代码.因为你只需要一套模板而已
5.他使用的语法是典型的ASP.NET语法,并且,可以像我们写ASP那样将代码和静态内容混和撰写(好像在写ASP的时代一样)
举一个简单的例子,你就可以明白他的强大
下面是我根据Quick Start Guide写的一个模板,作用是生成一个简单的类框架,不要小看他呀
<%@ Property Name="Developer" Type="System.String" Category="Context" Description="开发者名称" %>
<%@ Property Name="NameSpace" Type="System.String" Category="Context" Description="名字空间" %>
<%@ Property Name="ClassName" Type="System.String" Category="Context" Description="类名" %>
///////////////////////////////////////////////////////////////////////////////////////
//文件名:<%=ClassName%>.cs
//说明:一个简单的类架构生成器
//版权所有 @ <%=DateTime.Now.Year%> 客户名称
//历史更新
// <%=DateTime.Now%> <%=Developer%> 零版本
///////////////////////////////////////////////////////////////////////////////////////
using System;
namespace <%=NameSpace%>
{
///<summary>
///测试类
///</summary>
public class <%=ClassName%>
{
///<summary>
///构造器
///</summary>
public <%=ClassName%>()
{
}
~<%=ClassName%>
{
}
}
}
这段模板生成的C#代码如下
//文件名:MyClass.cs
//说明:一个简单的类架构生成器
//版权所有 @ 2005 客户名称
//历史更新
// 2005-5-19 17:39:13 上 午 Heroman 零版本
///////////////////////////////////////////////////////////////////////////////////////
using System;
namespace FunSoft
{
///<summary>
///测试类
///</summary>
public class MyClass
{
///<summary>
///构造器
///</summary>
public MyClass()
评论:
确实让我汗颜.看来ORM我还得好好学学!谢谢你的指点.
FOR Nh兄:
我的BLOG上写的东西,本来是反映自己的看法,大家看了,如果不对,可以指教,是正常的.但是如果语气不当,则有伤和气,进而引发口角,那就不值了.
For CsOver:
写这篇随笔前两个小时我阅读了CodeSmith的QUICK START并做了两个实例.给我的震撼确实很大,因为在我文章开头提到的随笔贴出后,有许多人表示了相同的无奈.好像从一个项目到另一个项目,无论数据库 的存储过程也好,还是基本的一些类,都得从头写来.但是,至少在试用CodeSmith建立了一个Insert存储过程后,我发现,以后写insert, update,select存储过程,基本上勿需再一个一个的来写了.这至少几倍的提高了我的效率.因为这些代码都是重复度非常高的,也是很相近的.可 惜,我没有能将自己所感受到的震撼传达给大家.但是,至少,我想,如果你去试用一下CodeSmith,就算你不屑一顾,可是,它对你的帮助是显而易见 的!
FOr AlleNny:
你想的很有深度呀.不过,这个问题暂时不在我的考虑之列,我是那种别人造出工具来,我就知道用的人呀
For SunRise:
我从来没说我的随笔是真理或者是正确的,所以,说我一派胡言,我也坦然接受.只是我忘了加"本随笔仅所映作者观点"几个字而已
总结:
我在写这篇随笔时,没有去考虑我的观点是否是100%正确或者是否全面的,所以,如果有错误,欢迎大家指正.
我想,中国人跟外国人还有一个区别(从淘宝网总裁同学的采访中学到的):中国人说话很谨慎,只说正确的,不正确的基本上都缩回去了.外国人鼓厉你 说出来,哪怕是错的.他们在表达观点上甚至很粗暴,像吵架一样.外国人说,就算十个人的观点都是错误的,可是,说出来,大家在十个观点的基础上思考,也可 能得出一个正确的结论.
最后,再次声明,争论是正常的.但请勿互相攻击.
虽然我的这篇随笔是漏百出,但是,它至少是反映出我真实的看法.因此我不打算对其更改.
最后,跟FunRise和Nh说一声谢谢.希望二位能够继续深入指点.李敖说他比别人牛的地方是他不光能骂一个人是混蛋,而且能证明这个人就是混蛋.我不反对二位骂我一派糊言,但希望二位做到李敖先生这种境界.
nh
1、你有本事你不用写*.hbm.xml,只写class,你有本事自动映射到数据库,如果你有本事,那你牛,顺便把sample code法上来
"你有本事你不用写*.hbm.xml,只写class,你有本事自动映射到数据库"
可惜的是,Hibernate3.0采用了新的标签化语法,如果愿意完全可以逃离xml配置的制约。
另外,重要的是,Hibernate3.0是基于xml映射的持久化层,不意味着其它O/R mapping工具也是。例如XPO.NET、Gentle.NET,这两种也是非常不错的工具。
另外,个人不太看好NHibernate(虽然在研究它,偶尔也在用它,但相比之下,更喜欢Gentle.NET)....
就CodeSmith而言,用于代码生成是非常强憾的,无论是Gentle.NET还是XPO.NET,我都自己写了代码生成的模板,而NHibernate用的是别人写的模板,感觉都还不错。
Jame兄的:
1.系統分析
2.架構分析
3.架構設計
4.類設計
5.數據庫設計(一般在oo中這一步是極為弱化的,基本上不談)
我有一小点异议:)
数据库设计无论在何时都是重要的,在对象化的设计里,数据库的责任只是减轻,而不是避免了。数据的良好设计关乎系统运行的性能,而且,如果连数据 库的设计都不好的话,类间的联系也不可能建好。玩O/R Mapping的人,应该比普通人更关注数据库才对,这样才能更好地写出具有灵活性架构的软件来。
1、你有本事你不用写*.hbm.xml,只写class,你有本事自动映射到数据库,如果你有本事,那你牛,顺便把sample code法上来
---------------
If you check the news toos in castle project,
they do provide this in class now.
you only need to add attribute to the field
in the class and no hbm.xml hassle any more.
They also have a visual designer to directly
create class with inhertiance mapping to table.
There is video there you can check it out....
They also have a visual designer to directly
create class with inhertiance mapping to table.
仍然需要工具来帮助我们建立class与表的map,并不是某些人说的,不是某些人说的,如果有需要用工具生成代码的话,那设计一定有问题。(这里说的“代码”是广义的代码,不仅仅是可编译的.cs文件)
至于hibernate里直接写property不用写*.hbm.xml,我已经说了,这个只是说是能完成工作,并不表示能完美的解决问题,就象某些人说,hibernate还能生成数据库呢。
无意中看到本贴,说两句废话
>毕竟orm需要你熟练掌握oo的思想,用起来才能顺手
非常同意
但就本主题而言,各位评论都有些跑题——菩提树无非提到了一下 ORM,大家都去说 ORM 去了,呵呵
就 CodeSmith,倒是用了一段时间,省了不少事情。要说震撼呢,5年前就震撼过一次了——当时一位 master 教我用 jsp 来做 Code Generator。其实思路很简单,只要你稍微熟悉 IIS,其实用 ASP 也是很容易实现的。其方法聪明之处在于借助了ASP/JSP/ASPX 这类“模板”CGI语言的语法,避开了大量的 字符串 连接运算,也就避开了运算中的大量的"等的处理。
仔细想想 ASP 的实现机制,其实也就不觉得很震撼了。
JSP/ASPX 的好处在于底层提供的种种功能接口都是开放的,相比 ASP 而言方便了太多。
因而,震撼可能有点说不上。
呵呵,不能光说废话,也说说我的观点。话又要说回到 ORM 和 OOA/D/P 上了。
有朋友提出 CodeSmith 要能有业务对象等等时,其实问题与讨论ORM Tools的功能好坏是一回事。但CodeSmith仅仅是一个代码生成工具,它不解决你的设计模型问题。
准确地说,CodeSmith不关心你采用什么样的O-R mapping方式,而ORM工具未必替你生成代码——因为其核心价值在于提供了一个ER<->Object的模型,至于生成代码的便捷程度是次要的。
因此,如果你有一个好的 ORM 思路/模型,你可以用 CodeSmith 来帮你提高其应用效率。
最后,个人观点:
〉向您请教一个问题,您在开发项目时,是先有类呢,还是先有数据库的表?
很多ORM都是从数据库产生Class,走了捷径。但你的数据是怎么来的呢?因此,也有部分ORM工具是通过 OOA 来得到 ER,同时产生 Class。比如 DeKlarit
对于 ORM,我个人比较倾向后者的做法。但前者也没有错——关键是使用者是先oo呢?还是直接就设计数据结构了。
所以从这个问题可以看出 菩提树 未必像某些朋友所指责的那样对 OO 一无所知。
呵呵,最近的一个项目尝试了一次先 OOA/D,然后用我自己的数据访问模型配合 CodeSmith 来 Build 代码——OOA/D 后,手工建表,之后用 CodeSmith 和自己做的模板 Build 配置文件生成代码。
下一步要改进的就是能把 OOA/D 的设计结果直接 Build 为 Tables/Views,而不是象现在一样中间断开了,呵呵
无论板砖还是鲜花,多多交流总有好处,但不要开骂
^oo^
.net体系我不知道设计的过程,是先设计数据库还是先设计class.但是在我做的大多数j2ee项目里面,我们都是先设计Class,几乎不 设计数据库(很弱的设计,针对于性能问题进行的一些优化步骤,其实叫做数据库调优会更适当).然后由orm工具(比如hibernate)自动创建数据库 表结构.
可能有人会问我代码生成器什么时候用.CodeSmith生成代码的优势在于使用了ChemasExplore,这个东西可以获取到数据库表结构 等信息,这样一来就可以生成基于表结构的很多操作(增加删除查询等等存储过程等).我们J2ee项目里面自己写的代码生成器则是通过类的反射来生成业务操 作(当然在这之前会设计架构,采用什么样的结构).
ORM肯定脱离不开数据库,否则还Mapping什么啊?真正的OO设计是不用考虑数据库的,因为当前的数据库绝大多数都是关系型的,无法满足OOA的要求.绝大多数ORM的工具提供通过类文件,配置文件可以建立数据库.
有人说*.hbm.xml写的很难,类映射文件很麻烦,那为什么不考虑使用CodeSmith或者其他的代码生成器来写呢?
关键在于模型,在思路
我没用 hibernate,倒不是说它不好,呵呵
大部分 ORM 都是从 table/view 产生 Class 代码,但也有不少是从 OO 来建数据结构。
所以说这个问题问得好,恰恰是因为在设计 ORM 过程中我们往往会遇到很多很头疼的很难以决定的因素,而它们往往是先有了数据结构后造成的问题。
但如果是在ooa/d 的同时(之后)就产生了 table/view,再然后为之 build 相应的 dao/dal(包括存储过程等) 是不是会更好一些?
为什么很多人不问这个问题?
因为还是有很多人先设计数据结构,再用各种工具或者不用,编写代码
只是对于他们,我觉得 Typed DataSet 足矣,oo 就别提了——对于他们,OO 往往仅仅体现在继承复用。
可以用 reflection 机制对设计好的 class 产生配置文件,从而经过简单配置之后 build table/view 以及 dal 代码(我现在是这么做的,所以我的系统中每个 object 对应好多 interface,但在开发进行到一定阶段之后,大部分 interface 都可以丢弃了)
也可以从 table/view 产生配置文件,然后 build class 以及 dal 代码
两条路,都没问题。前者似乎更强调先 ooa/d,可后者也可能是先 ooa/d 后创建数据结构,再继续... 当然,有点绕
所以,关键就是设计数据结构之前,是否采用oo的方式进行分析设计?
而不在于用 CodeSmith 或者 ORM 工具是去分析 class 还是分析数据结构。
最近刚好成功地实践了一次:
在设计过程中我先用 together 设计对象和关系,创建大量的 Interface,然后把其中涉及到 biz logic 的东东留下,用 together 等的 refactoring 功能把数据结构部分提取为 model interface
然后用自制的工具分析这些 bl interface 和 model interface,得到一个基本的配置文件,之后再手工修改配置文件(简陋,现在用 XML-Spy 的可视化环境),加入关系。
然后创建数据库(目前也是手工)
之后借助CodeSmith和自己写的模板(原先用VB+ASP做过一个工具,也用了三年多了,但改起来太麻烦)产生 Entity Model class(实现对应 的 model interface),Entity DAO(实现 CURD),产生 Entity Object(继承自 Entity Model,并加入针对关系的Lazy-Loading方法),产生 Entity BL 空类(可以继承自对应的 DAO)和 Typed DataSet。
于是,业务逻辑的实现放在 Entity BL中,而Object的Model之间的关系通过Object的Lazy-Loading方法体现(聚合复用自DAO或BL)。
此时,可以删除 Model Interface,甚至删除大量的不需要的 Interface。
最后得到的大部分 Entity 都会有这么几个文件:
IEntity:Entity Object Interface
Entity: Entity Object Class(继承自EntityMD)
EntityBL: Entity BizLogic Class(可以根据需要继承自EntityDAO或聚合之)
EntityDS: Typed DataSet
EntityCollection: Typed Collection(也可以使用公共的一个
EntityMD: Internal Entity Object Model
EntityDAO: Internal Entity DataAccess Object
非类型化的)
一般而言,重点是 Entity(继承自内部可见的,可以自动build的EntityMD),EntityBL(继承自内部可见的,类型化的DAO),EntityCollection,即E-C-C模式
那些 Interface 一则是为了解决当 EntityObject 从对应的 Model 继承后无法多重继承而用 Interface 保留 oo 之间的关系
二则,初期用于设计 Model,开发过程中用于约束设计结果以及oop编码结果是否符合原先的设计要求。但Model部分一旦可以自动Build,实际上Model Interface就没有存在的必要了。
Entity Object 和 Entity Model 分开, EntityBL 和 Entity DAO 分开,其好处在于Model都可以根据数据结构自动 Build,而不会影响 Entity Object 中的关系或方法。而 DAO 则甚至不受数据结构影响——甚至可以完全做到更换数据库、更换数据访问方式(例如换成存储过程)都无所谓。等用上了泛型,对于DAO、 Collection就轻松了——之前已经用VC/STL验证过这一设计思路。
呵呵,可惜今天忽然发现 CodeSmith 3.0 Beta 过期了,头疼,只好上网搜搜有没有可用的版本
如果不行,还真只能换 MyGeneration 改模板了,或者自己实现 Generator(仔细看看 CodeDOM,应该不难,这一点比java提供的东东方便多了)。
恩,学到了不少的东西,学习ing!