盘点企业软件开发技术(连载)
-
本连载试图调查和研究企业软件开发所要求的各种中间件技术,包括ORM、分布式事务处理、工作流、报表、应用集成等技术。
在此基础上研究OpenERP作为一个企业应用开发平台,如何实现,以及多大程度上实现了上述中间件技术。
在研究这个问题之前,先澄清下什么是企业软件开发。笔者理解的企业软件是,主要对企业业务对象进行加工处理的软件。企业业务对象是诸如员工、部门、客户、产品、库存、订单、会计分录等东西,对这些业务对象进行收集、加工、传输、统计分析,这就是企业软件的主要内容。还有一些软件,如字处理软件、CAD设计软件、辅助开发软件、网络管理软件、飞机模拟驾驶软件、导弹飞行控制软件,虽然这些软件也可能在企业应用,有些在企业甚至应用的非常广泛,但它们处理的是别的领域的信息对象,而不是企业经营管理范畴的业务对象,这里不将它们归于企业软件开发范畴。 -
ORM,Object-Relation Mapping,即对象关系映射。ORM解决什么问题,为什么会产生ORM技术,ORM通常怎么实现?
这些问题的答案,俺慢慢道来。先说说面向对象思想的产生。上世纪90年代以来,面向对象软件开发方法在全世界范围迅速推广开来。在企业软件开发领域,面向对象开发方法迅速推广是非常自然的。前面说过,企业软件开发针对的是各种企业业务对象,在面向对象以前的开发实践中,面对一个待开发的企业软件,人们通常是先分析诸如客户、订单等业务对象(以前还没有对象的概念,一般叫数据对象),并通过E-R图揭示这些数据对象之间的关系。然后,再分析对这些数据对象进行加工处理的过程或函数。这就是面向过程的开发方法,因为那时候,软件开发人员的主要精力是放在数据加工处理的过程或函数上。
这个开发方法有一个明显的问题,那就是,被处理的数据和对数据进行处理的代码相分离,是“两张皮”,这会导致代码非常难于维护。每一个修改代码的人,必须清楚所有数据结构;每一个修改数据结构的人,必须清楚所有代码。否则,任何一点改动,都可能导致别处的代码出错。当软件系统不大,只有几个人开发时,这个问题影响不算大。但是,如果是几十人、几百人开发的大系统时,这个问题会导致项目进行不下去。因为在一个大的团队中,要让每一个人或每一个小组都非常清楚别的人和小组的数据结构和代码,而且互相配合、互不影响的编写、修改代码,这在沟通上、管理上是一件不可能的事情!这就是所谓“软件规模化”的问题。
为了解决“软件规模化”问题,人们认识到,需要将数据和代码“局部化”,就是说,每个人或者每个小组负责的模块,它的数据和代码尽量不要和别的人和别的模块发生关系。这样的话,大型软件的开发就能够像搭积木一样,一个模块一个模块的叠加而成,这就解决了“软件规模化”的问题。这样就产生了面向对象的核心思想,即“封装性”和“接口化”。前者解决数据和代码“局部化”的问题,后者规范模块间的相互影响问题。
面向对象开发方法推广以后,ORM技术的产生是顺理成章的事情。为什么是“顺理成章的事情”,且听下回分解。 -
ORM技术的最早研究历史,可以追溯到60年代末。不过,直到90年代末,面向对象开发方法大范围推广后,ORM技术才进入实用阶段。在面向对象开发方法中,软件人员的着眼点集中在业务对象上。软件设计人员定义了对象,使用Class图揭示对象间的关系。但是,如何将对象保存到数据库呢?即要解决对象的持久化、对象的恢复、对象的查询问题。这几个问题,对应着数据库操作的Insert、Update、Select。在90年代,人们通常是为对象编写DBHelper的Class,DBHelper负责将对象保存到数据库,从数据库查询并读出记录,恢复对象。DBHelper解决的是对象到数据表的映射问题,即对象映射到数据表,对象的属性映射到数据表的字段,这个映射是双向的。
有没有办法简化这个映射过程的开发呢?甚至完全自动化的完成这个映射过程呢?这就是ORM要解决的问题。软件人员希望,只要定义好对象,就能够自动创建数据表,自动将对象的属性和数据表的字段一一对应,自动生成对象的保存、恢复、查询的基本代码。概念上讲,这个自动映射过程应该是完全可能的。但是,早期的面向对象编程语言不支持对象动态特性。就是说,在程序代码中,不能操作对象的名称和属性字段,也就是不能操作对象的“元数据”。这使得自动映射过程有点复杂,人们通常要编写XML文件,告诉ORM系统,对象的属性和数据表的字段如何一一对应。这就是为什么Java5.0以前的EJB中,以及早期的Hibernate中,需要定义复杂的XML映射文件的缘故。Java语言直到1.5版,后来叫5.0版中,才支持动态语言特性。
关于对象属性到数据库字段的映射,还有一个问题,那就是对象属性的数据类型到数据库字段的数据类型的映射。对象属性的数据类型一般是编程语言的数据类型,而数据库也有它自己的数据类型,两者间需要建立映射关系。如果ORM只支持一种数据库,这个映射关系可以硬编码在ORM的实现代码中。目前的OpenERP(5.x版)正是这样做的,因此OpenERP只能支持PostgreSQL一种数据库。如果要支持多种数据库,通常的做法是,编写XML的数据类型映射文件,将语言的数据类型映射到不同的数据库的字段类型。Hibernate等ORM正是这样实现的。
Python语言很早就支持动态特性,因此,在Python中实现的ORM不需要定义复杂的XML映射文件。只要定义好对象,Python版的ORM就能够自动取得对象的名称、对象的属性,根据这些信息,自动为对象创建对应的数据表,并在对象属性和数据表字段间自动建立映射关系。而且,ORM还可以自动生成对象保存、恢复、查询需要的Insert、Update、Select等基本的SQL语句。但是,对于复杂的查询,ORM还没那么聪明,不能自动生成Select语句,因此还是要自己写复杂的查询条件。
ORM自动生成的对象保存、恢复等代码,通常只是简单的将所有属性都保存,或者将所有字段都读出来。如果为了性能的考虑,希望只保存修改过的字段,或者只读出感兴趣的字段,需要重载对象的保存、恢复等ORM自动生成的方法,改用自己的SQL语句操作数据库。另外,一般的说,ORM系统通常会过多的保存对象,或者过多的加载对象。就是说,它往往会保存或加载一些其实是不必要的对象,这当然会降低系统整体性能。为了尽可能减少性能的降低,ORM的实现中通常会采用一些Object Cache、Lazy Loading等技术,这增加了ORM实现的复杂性。不过,大多数情况,ORM的性能不会成为问题。少数对性能要求严格的情况,需要认真考虑性能优化,甚至不得不弃用ORM。
关于ORM,还有个复杂些的问题。对于简单的对象属性,映射到数据表字段是很简单的。但还有些关系字段,即数据库中的one2many、many2one、many2many等关系字段的处理,在任何ORM技术实现中,这些关系字段的映射都有些复杂。
OpenERP实现了自己的ORM,总体来说,实现的还不错。理解了ORM,就能明白为什么OpenERP的对象定义中找不到插入、更新、查询、删除等SQL语句,也不需要自己定义数据表。关于OpenERP的对象的更详细的说明,可以参考“OpenERP对象定义详解”:http://shine-it.net/index.php/topic,2159.0.html -
什么是工作流技术?为什么要工作流技术?工作流技术解决什么问题?工作流技术一般怎么实现?
这些问题,待俺老肖喝杯茶,慢慢道来。
工作流技术,英文是Workflow。前面说过,企业软件主要是对企业业务对象进行处理。企业业务活动中,有个非常重要的概念,即业务对象,如客户、订单等。此外,还有个很重要的概念,那就是“业务过程”。例如销售订单的处理,通常的业务过程是:报价 --> 达成初步协议 --> 内部审批通过 --> 成交 --> 发货 --> 收款 --> 结束。这是顺利成交的过程,实际中,在过程的每一个步骤都可能分叉,出现丢单、理赔等情况。因此,实际的业务过程往往比较复杂。伴随着业务过程的是业务对象的流动,例如上述业务过程中,从报价到成交,主要流动的是销售订单,发货阶段,会引发出库单、发货单的流动,收款阶段,会有发票、财务凭证的流动。
在软件中如何处理业务过程呢?为了说明这个问题,我们看一个简单点的业务过程,即请假过程:员工提出请假申请,主管批准,或者否决,过程结束。很显然,在这个过程中流动的业务对象是“请假单”。如果要编写一个处理请假问题的软件,我想,每个软件人员都会想到,首先要定义一个“请假单”的对象。很好,这个没错!怎么处理申请、批准或否决的业务过程呢?一种做法是,给请假单对象添加三个方法,分别是“申请”、“批准”、“否决”。当用户按下“申请”按钮时,系统调用“申请”方法。当主管按下“批准”或“否决”按钮时,系统相应的调用“批准”或“否决”方法。为了实现这三个方法,通常,我们需要在请假单对象中增加一个“状态”的字段,每个方法的调用,都会引起“状态”的变化。
这个请假处理软件的实现办法好不好呢?如果我们只是编写一个请假处理软件,这没什么问题。但是,企业中类似请假的流程很多,例如,报销的申请,报修的申请,订单的处理,生产工单的处理,等等。类似功能做多了以后,人们发现,有一些“共性”的东西,可以提取出来,以更好的方式来实现那些功能。
这些“共性”的东西是什么呢?人们发现,是“流程信息”!例如请假过程的处理,实际上有两类重要信息,一个是“请假单”,即业务对象,还一个是“流程信息”,即谁,什么时间,做了什么处理,业务对象的状态发生了什么变化。不同的业务过程,处理的业务对象各不相同,但过程中处理的“流程信息”非常相似。是否可以把流程信息分离出来呢?前面的请假软件的实现,实际上把“请假单信息”的处理,“流程信息”的处理,都混在了请假单对象的方法中。如果把“流程信息”的处理分离出来,从软件开发人员的角度看,有两个好处,一是可以简化请假过程的实现,二是,“流程信息”的处理代码可以应用在所有业务过程的处理中。 -
把“流程信息”的处理从业务对象代码中分离出来,从企业信息化的角度看,有比简化软件开发大得多的价值!一是,业务流程更具“柔性”;二是,可以更容易的监控和分析业务流程的执行过程。
先说说业务流程的“柔性”问题。比之业务对象的变更,业务流程更经常变更。例如前面的请假案例,笔者曾经碰到一个公司。刚开始,员工请假只要直接主管批准即可。后来老总发现,有些主管利用请假审批的职权笼络“小圈子”,于是规定,3天以上的请假直接主管批准之后,还必须老总批准。还有一个公司,他们有些主管经常在外,因而不能及时批准请假申请,于是他们规定,申请提出后三天仍没处理的,系统自动批准通过。像这样的流程变更,实际上是企业管理政策的改变。为了及时适应企业内外部环境的变化,取得更大的竞争力,企业不得不经常调整经营管理政策。企业政策的变化,要求信息管理人员快速修改软件系统,支持企业新政策的执行。对于大多数企业而言,信息系统管理人员和信息系统开发人员是不同的团队,更多的情况是,信息系统开发人员不是本公司的。因此,站在企业的角度,理想情况是,业务流程的变更,不需要软件开发人员的支持,信息管理人员就能够应对。如果一定要开发人员支持,那么信息系统对开发人员的依赖越小越好。如果流程信息和业务对象代码混在一起,流程变更就很复杂,必须要开发人员修改代码。这就使得企业信息系统不能快速支持,甚至完全不能支持企业政策的变化,从而影响企业竞争力。这样的软件系统缺乏“柔性”!
再说说业务流程的监控和分析。企业的业务流程很多,可以说成千上万。而企业的业务流程往往是非常低效的!例如报修,可能实际维修时间5分钟都不到,但从报修提出,到维修人员响应,在很多企业,要一个礼拜是很正常的。有一个案例是,某企业的职工宿舍锁坏了,申请报修,后勤科接到报修案子后,要买一把锁,买锁要一级一级,直到副总审批,而副总恰好出差去了。就这么个流程,后勤科直到十天后才来修。而这十天中,职工宿舍早被偷了。企业的执行力,企业的竞争力,很大程度上取决于业务流程的执行效率和执行质量。如何提高流程效率和质量?从信息系统的角度看,一方面要通过信息系统监控具体的流程执行状况,看看哪个环节拖延时间长,出错情况多。另一方面,还需要分析一段时间、一定范围的全体流程的执行信息,找出流程低效、低质量的“系统性原因”,而后,对流程进行系统性改造。这就是所谓BPR,业务流程再造。因此,从信息系统的角度说,工作流技术是BPR的基础技术手段。
把“流程信息”的处理从业务对象代码中分离出来,简化业务对象的开发,增加业务流程处理的柔性,集中监控管理企业业务流程,这就是工作流技术要解决的问题。 -
写到这里插一句,当分析整理了若干个中间件技术后,忽然悟道,其实所有的中间件技术都是,将企业软件开发中发现的某一类“共性问题”,抽象出来、分离出来,形成一个新的中间件技术!这个新技术形成的过程通常是,某些专家在实践中发现某一类“共性问题”后,发表了一些论文。而后一些大的软件厂商,如IBM、Sun等,它们发现这个技术有利可图,于是几个厂商联合起来,制定一个技术规范。这个规范的主要内容一般包括,该中间件技术解决什么问题,有哪些组成部分,提供什么接口。之后,各软件厂商都遵循这个技术规范,推出自己的中间件产品。
工作流技术是怎么处理“流程信息”呢?目前一般的做法都是,使用XML文件定义工作流程。工作流程定义文件通常包括“节点”和“迁移”,节点对应工作流程中的步骤,迁移表示节点间的跳转。节点上可以执行某些“动作”,迁移可以带有某些“条件”。当工作流系统接收到跳转信号,系统检查迁移条件,如果条件符合,跳转到下一节点。跳转到新节点后,如果节点定义了动作,系统立即执行该节点的动作。在XML的工作流程定义文件中,“动作”和“条件”通常都是嵌入在XML中的程序代码(以对象或方法的形式出现)。工作流系统的核心组成部分是工作流引擎。工作流引擎负责加载XML工作流定义文件,接收信号,检查迁移条件,迁移,执行节点动作,并且完整记录工作流程的执行日志。执行日志包括,哪个流程,什么时间,接收到什么信号,进行了什么跳转,跳到了哪个节点,执行了什么节点动作等信息。
关于工作流定义文件,以及工作流引擎的更详细信息,参考工作流管理联盟(WfMC)的有关标准。WfMC成立于1993年,是一个由涉及工作流和业务流程管理的推广人员、开发工程师、顾问、分析师、大学和研究团体的全球性组织。该组织创建并完善了工作流的相关标准,开拓了相关市场,是唯一的致力于工作流标准化的专业组织。该组织推出了工作流XML(Wf-XML)和XML过程定义语言(XPDL) ,现在有超过80种有名的解决方案中使用了这两种语言来存储和交换过程模型。 XML过程定义语言(XPDL)是一个过程设计格式,用来存储可视化设计图和设计中的所有时间属性和产品属性。 -
工作流技术的产品化有两种形式,一种是中间件技术,一种是业务流程管理软件包。先说说作为中间件的工作流技术,这种工作流技术一般集成在开发平台中,主要供软件开发人员使用,其目的是简化业务对象的开发。这种形式的工作流技术,它对外主要公布一些流程处理的API,程序开发人员通过API的调用,编写业务过程的支持软件。具体例子如J2EE的开源版实现--JBoss,它集成了工作流开发平台JBPM模块。又如OpenERP,它也实现了自己的工作流开发模块。软件包形式的工作流技术,它以独立软件产品销售,主要供企业信息化人员使用,其目的是业务流程集中管理,即BPM,BPR是BPM的一部分。作为软件产品的工作流技术,通常它带有友好的用户界面。例如,通常有一个图形化界面的业务流程绘制工具,这个工具可以让不懂编程的业务人员绘制流程,然后自动生成XML的流程定义文件。又如,通常还有一个用户友好的流程监控工具和流程分析工具,这个工具可以监控企业中所有正在执行的流程的执行状况。例如,可以跟踪某一张订单当前处理到哪一步,当前订单步骤的处理人是谁。可以分析哪一个订单步骤丢单最多。作为软件产品的工作流技术,它也提供开发接口,即API。
OpenERP的架构中实现了自己的工作流模块,当然,它实现的是作为中间件的工作流技术。OpenERP的工作流模块,可以使用XML定义流程文件,他也提供了流程处理的API,还带有一个较为简陋的图形化界面的流程绘制工具。不足之处是,OpenERP的XML流程定义文件不兼容于WfMC标准,是完全自己搞的一套。其二是,OpenERP的工作流没有错误处理机制。就是说如果在流程执行过程中出现程序或数据异常,它不能捕获异常进行适当的补救性处理。其三是,OpenERP的流程执行状况的监控机制不够完善。这些缺陷,使得OpenERP只能适用于中小型企业。在大型企业中,错误处理机制的缺失,监控机制的不完善,会导致严重后果,造成极大损失!