关于Kanas.Net框架的一些背景

我出生于一个非计算机相关专业的科班,所以软件行业来说,我根本就是低学历的。从86年开始在一台512K内存,5M硬盘的IBM PC上写第一个Hello World汇编语言程序的时候,就决定改行从事这个行业。但是真正专业从事这个行业却是93年以后的事情,之前的一切都属于业余级。但是好象我用的编程工具一直是Borland公司提供的,从Turbo ASMTurbo CTurbo Pascal,而且我一直都认为在面向对象方面,Borland是领跑者,而Microsoft是后来者,你可以看到,Visual Basic直到版本6都是基于对象的,而Turbo Pascal到版本5就全面支持面向对象了。感觉自己最重要的一次提升发生在1995年的夏天,我在使用Turbo Pascal 5.0的时候第一次读懂了TView这个东西,领悟了面向对象的实质。不过我觉得每个人的提升轨迹都不是可以和别人重叠的,例如我觉得我的悟发生在我对VML(虚拟方法表)和实例结构的汇编级理解。

陆陆续续做了一些项目,包括DOS下的一些项目和基于Windows 3.1的项目。96年,用Delphi做了一个比较大的项目,那时候感觉Delphi是个真正了不起的工具。但是随着项目越做越多,就越觉得很受VCL的局限。因为DelphiVCL架构特别是数据感知控件,不得不让我将一些业务逻辑分散在存贮过程和UI中。不仅不方便维护,而且令复杂度与开发工作量成为几何级数关系而不是算术级数关系。

 

99年底开始,我开始一个80多万金额项目的开发,Team成员多达9个,我是该项目的总负责人。基于我对Windows 32架构的深入了解,我打算吸收其中的一些思想,将整个系统架构做成插件式,插件坞由我来完成,这个部分完全封装了对数据的访问,相比业务的多样变化来说相对固定。全部的业务逻辑都封装在业务层,而将业务层对界面层的访问封装成有限的14种,实现了业务层与界面的彻底解耦。除了公共模块外,模块间也是充分解耦的。那时候没有机会拜读GOF或者Martin Flowler这些大师们的著作,这些架构完成根据业务需要来自行设计的。这个架构我定名为CXS(Client-Xml-Server)架构:应用服务器初始化时按配置加载插件(其实就是一大堆用于处理业务逻辑的服务端dll),然后打开Socket服务器(那时候还不会处理完成端口)监听来自客户端的XML申请包,并返回一个XML包。客户端收到的XML直接创建业务对象,向界面发出各种指令,界面接受用户的输入,直接生成各种XML申请包。与http协议不同的是,因为有自己的客户端,所以服务器是可以向客户端“推”数据的,而不是象http一样只能由客户端“拉”。

 

在那个项目上,这个架构的应用没有取得完全的成功,不能象预期的那样减少维护和开发工作量。真正最让我满意的是在另外一个中型项目上。2002年,那时候刚离婚,又处于失业状态,比较有时间充分考虑CXS中的一些问题。九月底正好有个朋友让我帮忙接下这个项目,于是,就有机会应用这个新框架。实话讲, Delphi下,开发这样的框架难度非常大。为了将内存泄漏控制到0,必须花费太多的精力顾及实例间的关系,必须恰当地处理“什么时候构造”和“什么时候析构”这两个问题。

 

后来,在Delphi下有了非常专业的、商业化的、结合UML模型的数据持久方案,例如Bold,加上自己势单力薄,于是就没有再将这个架构再延伸下去。2003年,我转到asp.net下做项目开发,发现Microsoft并没有提供类似Bold这样的框架。那时候我已经通过Robert了解了Hibernate的一些思想和解决方案。Borland也有一个源自于BoldECO,只是ECO不是线程安全的,不能应用于asp.net(这个问题直到ECO II才解决),但是很多思想是非常值得我学习的。那时候也在网上找了很多很好的框架,但是我觉得这些框架都不能令我满意。例如DeKlarit虽然提供了非常好的IDE插件工具来建立模型,但是仍然不能实现很好的应用逻辑与应用平台的独立。

 

于是决定自己借用在CXS中的经验写一个。当时公司有一个项目所有的业务逻辑全部写在一些存贮过程中。写这些存贮过程的开发人员离职以后,这些存贮过程无法被维护,为此已经严重影响了公司的声誉。这更坚定了我写这个框架的决心。本来在.net写一些框架就比在Delphi下简单,在写的过程中又有了XPOGrove作为参考,所以进度还过得去。差不多两个月的时间,Kanas.Net 1.0诞生。因为迫于当时的项目压力,第一个版本非常粗糙,几乎无法见人。在紧接着三个项目中才有机会来彻底重构一下。这样就有了1.11.2版。这三个版本都支持SQL ServerOracleODBCOLE DB四种数据访问引擎。从第一个版本开始就初步达到了我的预期,整个项目中没有一处直接调用数据库功能,而我在项目中只负责编写一些业务逻辑,完全不用关心界面了。

 

去年年底,遇到一个侧重OLAP的项目,其中的OLTP部分采用XML文档作为数据持久载体。我忽然觉得,ECO的设计真的是望尘莫及呀!从第一个版本就支持以XML方式持久化,而我总是受到一些不良的影响,将持久化与数据库划等号(这不能全怪我,ECO是一个全世界少有的精英团队开发的,考虑的比我全面100倍都是正常的)。这才开始构思1.3版。一直以来我的架构驱动就与ECO不同,我不会考虑什么主流技术或者市场推广价值,也不会考虑功能需要多大的覆盖,我只能在我自己的开发能力与我的项目需求之间寻求一种平衡。所以,我好象都是先有了业务层或者表现层的需要,才给公共框架层设计这个功能。

 

由于每个项目中的业务逻辑部分都是我自己完成的,我发现我的主要工作都是寻找关系,而且主要打交道的方式都是通过包装层来完成的。我可以不关心界面层。我写完业务层,给界面层提交一份调用接口就可以了,我可以开始对每一个业务逻辑的实现进行单元测试,界面开发者也根据领域对象和用例说明知道该在页面中部署一些什么样的元素了。任何一个业务上的难点,我都可以很轻松地寻求到一个解决方案。例如,客户要求对用户的管理这一块做灵活一些,有可能用户管理在另外一个系统中完成(是的,用户正在进行EAI,可能正在调试自己的Portal应用)。但是我不可能把客户的Portal迁移到我自己的开发环境中做测试,所以只能设计一些接口,到客户真正实施Portal的时候再把API拿过来重新写一个实现,我这里大局上不受任何影响。而这个接口是通过一种极其简单的方式来影响到我成千上万的需要使用用户标识的每一个地方。这个方法就是,用户相关的业务对象就是一个接口,接口所实现的UserID就是我数据库中需要保存的值。这里虽然没有了外键(是的,数据库模型中无法描述对接口的引用),但我只需要重新实现一下用户映射器(外键可能是ReferenceMapperAttribute而用户就是UserMapperAttribute)

 

Kanas.Net我自己还是比较满意的。通过这个框架,中小型项目的开发过程就是:开始做需求分析、用例分析、数据库建模。业务开发人员获得这些成果,通过工具将数据库模型变成Kanas.Net领域模型,并生成领域对象的源码。然后根据用例分析手工完成每一个Action(例如增加或者取消一个订单)或者Service(例如根据某个条件来生成一个DataView)。业务开发人员可以完全不关心其它的细节,他甚至可以不知道这个项目是用WebForm实现还是用WinForm或者根本是用一个Windows Service来实现。但是他必须知道这个系统的每一个用户需求的细节,并必须保证每个Action或者Service的结果是正确无误的。

 

但是很可能事实并不是这样。记得在1.2版推给同事用以后,有一个一直支持我且参与过Kanas.Net框架研发,并深得我信任的同事对我说,“这个项目如果不用Kanas.Net作平台我就参与”,我当时有一种地狱般的感觉。我开始努力寻找Kanas.Net不受欢迎的致命缺陷。其一,象用户信息这样的全局数据都是初始化时一次性加载的。在调试时IIS经常会保留上次的初始化标识,不能自如地清空对象空间,有时甚至必须停止IIS服务才能正常调试。其二,用于检索数据的约束子机制过于复杂,很多概念非常难于理解。往往这个时候我才理解为什么Hibernate引入一个别别扭扭的HQL来,也许我自己觉得别扭的往往别人觉得很亲切。其三,对于包装层的东西,太难于理解,扑朔迷离的。在Kanas.Net中所有的域对象代码都是自动生成的,根本无法关注域对象所应有的行为,包括一些收集关联者的行为。于是我设计了一个包装层,将每个事务中的对象重新包装,以增强领域对象层的功能。但是这个层的太复杂,普通开发者难于接受。

 

Kanas.Net 1.3版中,所有我能够发现的问题我都会尽量避免。我希望Kanas.NetCXS是完全不同的一个命运。虽然这样的产品层出不穷,但是我仍然对自己的产品充满钟爱。天下厨师永远做不完天下的菜肴。谁都愿意品尝自己亲手制作的菜肴,不论是鲜美无比还是难以下咽。目前这个框架的最后一次重构正在进行,希望月底能够如期发布。

posted @ 2005-07-13 17:51  双鱼座  阅读(4581)  评论(23编辑  收藏  举报