计算机软件开发的进展研究
1引言
当前,计算机技术的迅速更新、软件处理对象如企业业务过程的不断变化以及软件开发竞争的日趋激烈已经使传统的从源代码级开发软件系统的方法面临越来越大的挑战。利用传统开发方法开发的大多数系统所使用的是在开发初始时所能得到的技术,面向的是当时所需处理的问题,要使这些软件系统适应处理对象如业务过程的变化以及计算机技术的进步是一件非常复杂的工作,往往必须对原有系统在代码上进行重大修改,这种修改代价较高并且也有一定的风险,从而造成软件的可扩充性Scalabiltiy)较差。在开发过程中,为减少软件开发费用、缩短软件开发周期,保持开发者的技术水平变得越来越重要,因为只有这样才能达到一个较高的开发效率,使得项目按时完成。而在传统的开发方法中,由于开发不同的软件时常需要不同的开发工具,这使得开发者必须不断学习新的开发工具,原有的技巧以及已具备的经验难以被再次利用。当今的软件开发经常需要利用现有成果,开发时可能要集成不同的系统、新的应用、标准的软件包以及已在业务开展中使用了的与任务有关的现有数据与系统,通过集成可以减少不必要的工作量,提高软件的可用性,加快开发进度。但是传统的代码开发方法主要着眼于从无到有的构造,对软件集成Integration)的支持不够,大量的开发时间被投入到底层编程中,这种编程不仅耗时而且可能是重复劳动,从长远看还会造成代码难于维护。
随着软件构件技术的成熟,大量的构件作为现成的商品在软件市场出现,基于构件的软件开发CBSD:Component-basedSoftwareDevelopment)也作为一种新的工业化的软件开发方法被提了出来。该方法是对以前传统开发方法的一种改变,它使得软件开发从代码开发转移到对已测试、已使用的,并且在内部互操作的构件的集成是软件重用的一种实例。通过加强系统的灵活性以及可维护性,CBSD可以被用来减少软件的开发费用、快速的集成系统以及减少与支持升级大型系统相关的维护费用,从而使软件开发者处于有利的竞争地位。该方法的基础是基于这样的假设:大型软件系统的某些部分会不断重现;系统的公用部分应当编写一次而不是多次;公共系统应通过重用被集成而不是一而再,再而三的重写,它体现了FredBrooks所支持的购买而不构造”的开发思想。在CBSD中的构件主要是指可以通过商业手段获取的构件CommercialOff-the-shellComponent),主要是遵循已有的C0M/DC0M、C0GBA以及JAVABEALS构件标准的构件、开发者可以加以剪裁的应用框架以及已被其他应用集成或扩展的独立软件系统。当今世界上许多研宄机构如美国的卡耐基梅隆大学、加拿大的国立研宄委员会NationalResearchCouncil)都在积极对CBSD展开研究,该文将对这一领域的研究成果、进展加以综述。
2CBSD的主要活动
CBSD的开展主要是通过集成已存在的构件来进行的,这与传统的开发方法有着明显的不同,在后者中,系统集成通常是实现工作的结束部分,而在CBSD中,构件集成是构造系统的核心内容。因此,在决定获取、重用甚至构造构件时,可集成性是所需考虑的关键因素。
CBSD由4个主要活动组成:构件的评选、构件的适配、构件的组装以及系统的演化。
2.1构件的评选
构件的评选是一个从市场上的一批相互竞争的构件中加以选择的过程,该过程要求在众多侯选者中选出最适合在该软件环境中使用的构件。在安全性要求较高的应用中,构件的选择可以扩充到包括对创建与维护构件的开发过程的选择,但这样也会减少使用现有构件的一些好处。
一个适合使用的构件可能本身就是一个复杂的软件,为了有效地使用该构件,必须深入了解它。但较好地了解一个构件并不是一件容易的事情。首先构件的文档可能不全或者错误。即使构件的提供者有意识作好文档,一个复杂的软件是不可能在文档中被完全并且正确说明的。即使不完全的文档可能也是庞大的,除了非常有经验的使用者,其他人将很难理解;其次构件的接口可能非常复杂。许多构件有上百个API调用,即使编制这些构件的人都很难知道每个API调用的行为或者特殊调用序列的结果;最后在构件中存在错误。所有这些问题都对了解构件造成困难。
构件的评选有两个阶段:发现与评价。在发现阶段,要判别构件的特性。这些特性包括构件的功能提供什么样的服务)、构件界面的其他方面如使用的标准)以及其他难以分离出的质量特点如构件的可靠性,可预测性以及可用性。在一些情况下,在发现构件时也应该考虑构件的非技术特性,如提供者的市场占有率、以前的业绩以及构件开发组织的过程成熟度。发现构件是一个艰难的无法精确定义的过程,所需的信息很难量化,有时也难以得到。
构件的评价是一种决策。评价构件用来支持作出编制还是购买、买A还是买B以及使用特征A还是使用特征B的决定。当前已经存在了一些相对成熟的评价技术,如ISO的通用标准以及IEEE的特定域的构件评价技术,但就构件评价本身来说是不确定的,这主要是由于使用难以互相比较的标准、不明确的系统期望、不精确的评价方法以及构件的快速修改,这意味着构件评价带有一定的错误。确定构件的适应性是构件评价的目标,构件对系统百分之百的适应是不大可能的,一般都存在一定的权衡,而构件对系统的不适应程度由不适应的类型、修补不适应的费用以及不适应性所导致的风险所决定。对于每一个评价活动,由于存在各自不同类型的决定、系统环境评价过程都是有针对性的,对开发者有用的应该是一种系统的方法,该方法能够在众多可变的因素中加以选择以说明有用的评价标准。
2.2构件的适配
由于每个构件在编制时针对的是满足不同需求的,并且是基于上下文的不同假设,在应用到一个新系统时构件常常必须被改写。构件必须被改写的前提是保证构件间的冲突最小。对构件内部结构的理解程度决定了对构件适应的不同方法*2+:
1)白盒子法。用户可以获得构件的源码,这样可以通过改写构件以使构件能与其他构件进行互操作。这种方法可以对构件的特性进行非常细致的控制,不过由于需要修改源码,从长远看可能会导致严重的维护和升级的问题,使得基于构件开发的许多优点被丢失。
2)黑盒子法。只能得到构件的二进制可执行形式,构件没有提供扩展机制或API。
3)灰盒子法。在这种情况下,构件的源码是不可更改的,但构件提供了它自身的扩展机制或可编程的接口API。
对构件自身的扩展机制加以调用的方式一般称之为构件的剪裁ComponentTailoring),它指构件的使用者以构件提供者所提供的方式来增强构件的功能,包括脚本Script)、插件Plug-in)的使用和继承inheritance)三种方式。却本方式是指构件在某些特定事件下执行某一特定的脚本过程,早期的脚本是由简单的宏语言来编写的,在当前许多新的应用中脚本描述能力已经越来越高级,用户可以使用完善的编程语言和解释器来编写脚本如VBA、tcl以及Perl。插件是指在一个封闭应用中注册的构件,当应用需要该插件功能时会对插件执行一个回调Callback)。继承允许构件内部的某一特定部分被修改和限定,当前的面向对象标准允许构件被开发者使用,尽管使用者只能得到构件的二进制代码,继承的使用要求深入了解构件结构,在通常情况下仅仅被专业开发者所使用。对构件可编程接口的调用一般会涉及到在构件周围编写一个屏蔽构件工作区以及延伸的包容器Wrapper)以提供对构件接口的更高级抽象。把构件包容起来有很多好处:可以使构件遵循标准,如在已有系统上的COGBA包容器;为某一范围的构件提供一个标准接口;增加或隐藏)构件的功能;为构件提供一个单一的访问接口;尽管该集成者无法控制构件,构件的包容器能给构件的集成者一种直观的感觉。构件的集成者可以控制和访问包容器。
2.3构件的组装
构件的组装较易发生错误,需要一定量的编码,并且难以调试和测试,此外,构件还较易发生变化,商业构件经常面临频繁的升级。这些升级所增加的功能或消除的问题不一定是用户所希望的,在上一版本的关键功能可能在后续的版本中被删去了,在这种情况下,用户可能会希望在系统新的发布版本中使用由其他供应商提供的同类型构件。
为了处理在搭建系统时所遇到的问题,集成构件的体系结构应该有以下一些特点:
1)构件可插拔。系统的体系结构必须允许构件的替换,这种替换包括更新为构件的新版本和将构件替换为由其他供应商所提供的同类型构件。
2)构件间松散耦合。构件间的耦合必须尽可能的小,耦合可能包括功能耦合如过程调用以及其他类型的依赖如资源竞争或结构上的假设。体系结构必须允许构件间的隔离。
3)隐藏不必要的功能。为了使自己的构件区别于其他人提供的构件,构件供应商给他的构件加上过多功能,这对构件的组装不利,系统结构设计者可能因此希望去掉这些功能,系统的体系结构必须提供对功能隐藏的支持。
4)调试与测试。由于在开发过程中构件基本上是以灰/黑盒子的形式来使用的,所以不可能对构件内部加以调试和测试。软件的体系结构无法克服这一问题,但是它可以包括在运行时对构件的行为加以监控及验证的能力,并且可以防止构件的错误扩展到系统的其他部分。
在由构件开发软件系统时,可以使用以下几种体系结构类型:
1)数据库结构。在该结构中对所有操作数据的集中控制是系统在构件间共享信息的关键。
2)黑板模型。构件间的数据共享是随意的,涉及降低系统的开销水平。
3)消息总线。构件有各自不同的数据存储,这些局部数据通过变化消息来加以协调。
4)消息请求代理0)B)协调,0)*技术提供了与语言无关的接口定义和对象定位与激发的机制。
组装构件时,在许多时候必须编写一些粘接代码GlueCode),这些代码可以通过必须的数据转换等手段来消除构件间接口不兼容的问题,使底层构件的功能按需激发,从而提供把不同的构件结合在一起的功能。不仅如此,通过捕获异常,粘接代码还能为系统提供统一的异常处理机制。
2.4系统的演化
系统是不断改变的;系统中的构件也是不断变化的。系统与其构件的演化对系统的维护造成了多种影响。在把新版本的构件加入到系统时需要做许多工作,对于一个由多个构件组成的系统,每个构件都有其自身的升级安排,把每个构件的每一个新版本加入到系统中代价非常高昂,造成这种困难的原因是因为在构件的新版本中,构件的行为、界面、前提、性能以及错误的消除都可能发生变化;在旧版本的构件上进行的定制、扩展以及相关工作必须施加到新构件上。
在基于构件的系统中没有在机械系统中定义的‘一致”的概念,在机械系统中各个部件完美结合而在软件系统中各构件的结合是在一定的限度之内的。一种处理系统演化的方法是假发生,系统可能依赖于已不再使用或已被升级的特殊平台;也可能在新版本中需要去除错误。集成新版本的构件需要作出较大的努力。首先,新版本的构件必须被评价以确定在旧版本上作了什么改变;其次,新构件必须被集成到系统中。这可能包括添加或移去构件的工作区,增加新的扩充以考虑构件新的行为,升级文档和培训过程等等;最后,系统必须被测试和确认。
3使用CBSD的优缺点
作为一种新的软件开发方法,CBSD具有自身的特点,这些特点把它与传统的代码开发方法区分开来。使用CBSD可以给软件开发带来以下好处构件的开发者可以使用最适合的开发工具而不必学习新的语言和工具,这样就允许企业可以利用已有的技术;当使用预先创建及测试的构件时,在组装过程中应用的开发者可以关注业务问题而不用担心技术以及外部设施等问题,减少了系统完成时间。
在市场上出现的构件大多经过市场的检验而变的比较成熟,对这些构件的使用可以使系统比在使用自己编制的构件的情况下更可靠、设计更合理。
由于系统的开发基于组装过程,构件能被较容易的替换为更便宜、有更多附加值、使用更好技术并且具有类似功能的构件。这样使得系统的灵活性更好,开发者也不会过分依赖于某个供应商。
CBSD可以降低软件开发费用,由于构件的供应商开发及维护构件是针对多个用户的,那么使用该构件的软件在该构件部分的开发及维护费用被多个用户分担。
虽然CBSD有许多优点,但也存在不少缺点,这些缺点给软件开发带来一定的风险。
首先开发者无法得到构件的源码,也就无法通过修改源码来改变构件的功能,这就意味着分析、调试以及测试构件必须完全以黑盒子的形式进行。不仅如此,在许多时候,完整并且正确的特性说明也是拿不到的。虽然构件的提供商提供了功能描述但是对于那些想掌握构件更详细的特性以及所需资源的开发者来说,这种说明往往难以满足需要。构件集成者也可能会使用未被构件提供商所预见的构件使用方式。
其次,构件的使用者无法控制构件的升级。构件的使用者仅仅是构件提供商许多客户中的一个,虽然从总体来说,构件的升级是由客户来驱动的,但单个客户不可能有对构件升级的全部控制权。
再次,在构件集成时,所选用的构件之间可能不匹配或者是作为单独应用设计的构件与软件的其他部分不易交互。构件之间的不匹配可以由许多原因导致,如数据模型、功能不匹配、资源冲突、过程模型等等。在有些时候这种不匹配在开发阶段的后期才会暴露出来。
4CBSD开发时建议遵循的原则
通过对大量基于构件软件开发过程的分析,可以得到一套有助于利用构件成功开发软件的原则43,|。这些原则从经验中来,遵循这些原则,可以简化开发及系统演化的工作。
1)包容所有的构件
系统中所有的构件都应该有包容器把它们给包容起来。提出这一原则的理由在于包容器提供了系统开发者对构件界面以及构件间交互的唯一机制,并且使系统的其他构件不受该构件改变的影响。此外,系统中所有提供重要功能而由手工编写的部分应与对待构件相似的方式对待,也应该用包容器包起来,这样当以后如果出现同样功能的构件时,开发者可以较容易地把手工编写部分改成构件。
2)粘接代码独立于构件
粘接代码应该独立于与其粘接的构件,在构件替换时不必改写,构件的替换被构件的包容和剪裁独立所隐藏,粘接代码与构件的交互是通过包容器间接进行的。粘接代码所提供的功能不应该依赖于所访问的特定构件,诸如异常处理、控制流等服务的升级应独立于多粘接的构件,这样当构件升级或修改时,粘接代码可以保持不变。通过提供构件周围用来隔绝的包容器粘接代码可以使用标准方法访问构件。
3)检验构件的版本一致性
构件以新版本发布的形式快速升级,系统通常与使用构件的哪一个版本运行有关系,一个特殊的构件被升级到一个新版本经常意味着包容器以及其他构件也要被升级。
系统的开发者无论如何都需要保证当前构件的配置版本一致,理想的版本检查是自动进行的,版本验证可以在创建、安装或运行时进行,这与构件的连接时间有关。Perl和使用Ac?tiveX构件的VisualBasic都有对版本验证的支持。在Perl中,构件开发者在每个发布的软件模块中加入一个版本号,构件使用者在连接该模块时必须说明所需的版本,在运行时系统会检查所连的模块的版本是否等于或高于所需版本。ActiveX构件对构件及接口都有一个版本号,构件的版本号是由开发者确定的,它被安装程序使用来决定已安装的构件是否应该被新版本的构件所替换。接口的版本号是在编译时自动分配的,它用来记录一个构件接口的不同版本的一致性。在运行时,当一个VisualBasic程序连接到ActiveX构件时,一个验证构件所暴露的接口是否是VisualBasic程序所预期接口的检查会自动进行。如果版本不一致的话,系统集成者可以捕获异常。
4)在包容及粘接中加入断言
在许多情况下为了确认运行时的断言在包容及粘接中所进行的高层次检查是非常有用的。这些断言可以仅仅是验证参数值或类型,也可以更为复杂,断言数据值之间的关系或所需要事件的临时顺序。这种运行时的检查主要位于包容器及粘接代码中,通过在构件间添加断言并且在断言违背时发出异常,错误能很快被发现并且从系统中分离出来。
5)使用开放的标准
使用遵循开放标准的构件能使不同供应商的构件间较容易地替换,而选择遵循特殊标准的构件会给系统的可移植性以及用不同来源的构件配置系统时带来问题。如果使用不开放的标准,系统开发者会过分依赖某一特定的供应商,即使有其他供应商提供相同功能并且性能或费用上更可取的构件,开发者也无法采用。
6)—致的体系结构类型
通常开发者无法控制构件内部的结构以及构件的演化与维护,他们所能决定的是系统体系结构及体系结构类型。通过定义在系统整个生命周期内都可维护的灵活的体系结构并且保证构件都遵循这一结构能使在系统中添加构件较易进行,系统内的服务也能按照需要剪裁和修改。如果在开发过程中过早地束缚于一个特殊的体系结构,会使构件的集成变得困难,构件的完全利用也不太可能实现。
5小结
基于构件的软件开发已经越来越广泛地应用于包括企业信息系统在内的多个领域的软件生产中,并且成功地开发出许多系统,但在对安全性要求苛刻的系统中,使用该方法风险仍然太大。为了方便该方法的开展,当前出现了不少开发工具如compuware公司的Uniface、SuperNova公司的Visualconcepts,这些工具在构件组装、部署等方面提供了许多支持,使得基于构件的开发能更加有效地进行。
作者:何国斌,马世龙(北京航空航天大学计算机系北京100083)
上一篇:促进计算机软件开发发展的举措