你所在的位置:
科技干部学院
>>
软件工程系
>>
文章精选
软件工程的演进
软件工程的七条基本原理
软件生存周期法
软件管理
软件危机、软件工程
面向对象的软件开发
面向对象软件工程方法
面向对象方法综述
微软公司软件开发模式
校企合作培养软件工程
海外的软件开发
软件业的春天来到
中国信息产业已成为国民经济第一支柱
为何给“软件硕士”松绑
软 件 工 程 的 演 进
中国计算机世界出版服务公司版权所有
----应用和可行性技术的发展促进了软件工程的不断进步
本文重点论述了在过去30年里软件开发的关键技术和方法。
----在各种各样的应用领域,无论是财务管理、医院管理还是航空领域和核武器研制,软件都是一项很关键的技术。这些需求各异的不同领域内应用的发展,推动着软件从小的批处理程序向大的具有多媒体功能的实时程序演进。为了适应不同应用领域的要求,软件的可行性技术在硬件、通讯、操作系统、编译器、数据库、编程语言、用户接口等方面有了巨大的提高。反过来,这些提高也使得应用更加先进。
---例如:在VLSI和多媒体技术领域的提高产生了速度更快、体积更小的计算机,大大拓宽了软件应用的领域。另一方面,数据库和用户接口的增强产生了更为交互的、合作的开发环境。这些变化不仅对软件技术和工具,也对软件的开发过程产生了广泛而深远的影响。在本篇中,我们将简要回顾组成软件工程的诸多子学科是如何发展的。
软件开发过程
----人们将软件开发分成时间短且便于管理的不同阶段,从而系统地开发软件,并将其作为一个评估、比较及提高软件开发效率的机制。此外,这些过程还对开发所采用的技术和工具、人员培训、整体项目计划和安排作出建议。一些软件开发过程,如WinstonRoyce的瀑布模型,将开发过程分成几个明确的阶段--需求分析、设计、编码和测试,每个阶段都有特定的目标并反复操作。----在不能充分理解规范说明中的问题或问题域时,则采用原型过程--它可被组合在需求分析阶段--来开发系统模型用以测试需求的可行性、适用性和正确性。实例应用包括人工智能(AI)和图形用户接口。
----BarryBoehm的螺旋模型将瀑布模型和原型结合起来。在螺旋模型中,需求分析、设计和编码是循环操作的,每个循环中需求都发生了变化。螺旋模型例证了软件开发的重复和发展特性。一些公司采用了螺旋模型变体,但是强调在每个开发阶段(中间检查点)产生一个工作原型以减少在开发周期结束时的系统测试压力。软件开发的进步.
----随着应用的发展和应用领域复杂程度的不断加深,软件开发过程也在自然而然地不断进步。例如:采用面向对象的开发过程,结合模块化、抽象和重用的概念,促进大规模的编程。
----以组合(原样复用现存组件)、继承(专门或扩展地复用组件)、设计组件(在下期"软件模式:设计实用程序"中描述的设计模式和结构)以及编码(软件包和模块)为基础,将复用纳入了软件开发过程。
----实时和并发系统领域对软件开发过程的发展也作出了贡献。因为这些系统中的过程强调形式的、严格验证的需求,其中结合了软件的行为和功能观点,所以将安全和可靠性过程也纳入到软件的开发周期中。
----对软件开发过程更深一步的影响是来自调节和证明机构为确保重复性和可预测性而施加的种种限制。软件生产率和质量的主要标准包括ISO9000标准和软件工程研究所的功能成熟模型。----各种各样的CASE工具能自动实现软件开发的部分过程,如代码生成、第四代语言、需求模型、形式说明和检验、可视化编程以及配置管理。发展的另一个动力是基于知识的开发,它的过程采用正确性保留变换将需求转换为代码。
----软件开发过程在观测结果上也经历了一些变化,例如:当今一些有经验的开发人员愿意将时间更多地花在需求和设计阶段而不是在转换源代码上,因为这种方法看起来比直接转换和调试代码更为有效。IBM最初由HarlanMills提出的超净室(Cleanroom)过程,将这种方法纳入开发过程,即让开发人员在没有编译器的情况下编写代码,促使他们在编译和调试之前就仔细地检查代码。在每个阶段都有独立的小组负责完成以检验为基础的检查。这些实施小组和规范说明小组是两班人马,这也使得规范说明小组能提交出相对正确、完整和一致的规范说明。
软件模式:设计实用程序
----模式是指在上下文中问题的求解方案。
----模式是一门新的软件工程问题解决学科。它起源于面向对象范畴。模式存在于许多学科中,包括文字编程(literateprogramming),最著名的要数ChristopherAlexander在城市规划和建筑上所做的工作了。
----一般地说,模式范畴的目标是建立一个文字体系支持软件设计和开发。为了用文字说明并支持合理的设计,对文字的关注要多于技术。尽管软件模式这一概念是由于《设计模式》一书的出版而为众人所知的,然而它早已被用于各个领域,诸如开发管理和过程、展览和教学以及软件结构。书中所述的是:在软件范畴内主要是为软件结构和设计使用模式。
----以下是一个用于Lucent电信产品5ESS交换系统的模式。
----名称:试验所有硬件组件。
----问题:容错系统的控制复杂算法能以许多不同的方式来配置它的子系统,因此存在多种可能的方式。一旦有一个子系统出现错误,如何选出一种可行的配置呢?
----上下文:处理复杂算法有几个双重子系统,包括:一个CPU、静态和动态存储器以及若干总线,备份系统能增加系统的可靠性。在5ESS中,这些子系统的16种可能的配置(在4ESS中是64 种)能实现双倍的节约。每种这样的配置称为配置状态。
----动力:你想要捕捉并修改一个单一的、独立的错误。你还想捕捉到在隔离状态不易检测到的、由于模块间相互作用而产生的错误。你有时必须捕捉到多重并行错误。CPU不能安排子系统的配置,因为它自己也有可能出错。机器应该在无人工干预的情况下自动恢复;许多可靠性系统的失败是由于操作员的错误造成的而不是主系统的错误。我们只想在出现最深层的问题时才用到专家。
----解决方案:在硬件上加入被称之为配置计数器的16位状态计数器。用一张表在计数器和所配置的状态之间建立一个映射关系。5ESS交换系统先试验所有的0侧单元(完全失败组),然后再试验所有的1侧单元(其余的失败组)寻找一个独立的错误。当重新启动失败时,状态增量并且系统再次启动。随后的计数状态寻找由系统模块间相互作用而引起的多重并行失败。
----结果上下文:由于潜在的诊断任务引出了错误,有时在重新启动的过程中检测不到错误。"FoolMeOnce"模式解决了这个问题。有时试了所有的计数器状态也不够。参见"Don't TrustAnyone"模式和"模拟计时器(AnalogTimer)"模式。
----原理:本设计是基于硬件模块设计的失败率(每兆失败次数)。这种模式消除了第一代程序开发人员在存储程序控制交换系统描述中所需的极度谨慎。
----这是一个好的模式:
----它解决了问题:该模式找到了解决方案,而不仅仅是抽象的原理或策略。
----它是一个得到证实的概念:该模式找到了有实际记录的解决方案,而不是理论或猜想。
----它所描述的解决方案并不是显而易见的。许多问题解决技术(如软件设计风范或方法)试图直接从某种理论中得到解决方案。最好的模式是间接地产生问题解决方案--一种处理设计中最难问题的合适的方法。
----它描述了一种关系:模式不仅仅是描述模块,更重要的是描述深层系统结构和机理。
----它重视人(减少人员干预):所有软件的宗旨都应给人带来舒适和高质量的生活。最好的模式应考虑美学与实用的结合。
----模式语言定义了一套模式和规则,将它们结合成一种体系结构方式。模式语言描述了软件的主要框架或相关系统。今天,模式学科受到了广泛的支持,包括小型会议、已成立的软件工程会议上的一系列活动以及快速发展的文献体系等的支持。
协作开发
----大型项目的开发几乎都是一种集体行为,由工程师和专家们协作完成。支持协作的软件工程和开发的工具叫做计算机支持协作工作应用软件或群件。群件应用包括:头脑风暴法、设计决策制定、战略计划、问题求解、竞争消除和软件审查,它使位于不同地方的人员在软件开发过程中能够协同制造、管理和共享信息。
----传统的开发过程主要从软件开发人员的观点出发,而忽略了最终用户的观点。由于软件逐渐变得容易使用,可将最终用户所属领域的知识与分析人员的技术知识结合起来实现有效的软件系统。多媒体和交互技术为用户和分析人员提供了有效的交流渠道。
----由于软件市场的不断发展,软件应用程序必须适应新的平台、环境以及不断变化的需要。也就是说,快速开发过程将会不断出现,主要基于下列因素:
----可维护性--软件必须是可快速更改的或可扩展的,以包含新特征。
----生产率--软件产品必须能被快速地开发出来以适应变化的市场和缩短开发周期。
----可重用性--通过重用现有的软件,可节省开发时间和劳动。
----可靠性--测试过程和测试也会受到更短的生产时间的影响。
---
-
安全--用于嵌入式,满足安全性需要的系统及其消费品。需求工程
----需求工程是详细描述用户需求的过程,并作为在系统开发过程中采用的分析组件。该描述指导软件设计、实施和测试。如果不及早检测出需求文档中的错误,则会增加开发的开销。
----需求工程的目标之一是决定建造系统的可行性和开销。原型和仿真不仅能帮助开发人员设计初级产品,还能使他们更好地理解用户的需求。特别是当用户的计算机知识有限而专业知识很强时,如内科医生与心脏医疗设备,原型不仅能有效地决定用户接口,还能决定产品的特性。
----其他需求工具,如支持需求模型并实现仿真的仿真软件包,可被用户和分析员用来理解问题以及问题的解决方案。为了在需求分析阶段支持一致性和完备性检查,工具的支持是非常有用的,如包含可跟踪性信息的交互参考表。但这样的工具只能对需求进行某种机械检查,而人工检查仍然起着重要作用。
----需求语言和工具多年来也在不断发展以支持变化的应用需求。自然语言说明是最早的需求形式,至今仍被广泛采用。数据量丰富的商业应用,如银行业,则产生了诸如结构化分析、数据流图这样的说明形式。控制含量高的应用,如电话业,产生了诸如有限态机器和位置--迁移图这样的说明形式。
----尽管早期的分析技术集中在输入输出转化、信息模型和控制方面,而面向对象的分析则通过对象之间的各种关系来强调应用域模型和数据方面的特征。
----安全性重要应用的增多导致了大量形式说明和验证技术的发展。形式软件说明拥有定义完备的语义,可用数学方法对其进行分析。尤其是能够采用一致性和完备性技术识别潜在的说明问题,主要用于失败代价巨大的应用中。
----随着需求工程的成熟,诸如情况说明生成、观点消解(viewpointresolution)、分解、多层说明检查、审查等技术以及用户参与的增加占据了新的重要位置。识别用户需求和分析结果之间的不一致和不完备,对于消除早期开发存在的问题十分重要。原型和仿真不仅可用于用户接口设计和性能研究,还可用于可行性和开销估算。
软件设计
----软件设计是一个创造性过程,它描述了软件需求是如何得以实现的。在早期的系统化软件设计方案中,EdYourdon的结构化设计强调自顶向下的过程分解以识别和定义功能模块和它们的相互作用。MichaelJackson的方法则强调从输入到输出的数据转换以及设计影响这种转换的功能。
----现代方法是面向对象的设计,采用松散耦合和高内聚力组件设计系统。抽象、封装和重用对面向对象的设计来说都很必要。其设计分类如下:
----高级:包括系统结构、组件设计、接口设计;
----低级:包括算法设计和数据结构设计。
----高级设计强调分解和功能的分配,将需求项目和设计组件对应起来,而低级设计通常包括代码。
体系结构
----根据系统的不同需要,在高层设计中采用的软件体系结构也不相同。例如:采用调用- 返回模式的过程设计是一种常用的体系结构。其他体系结构包括事件驱动--将独立的系统特征映射到外部的激励;分层--将系统功能分布在不同的层上,每一层都为上一层提供一个预定义的功能;数据流模式或工具组合结构(如Unix的管道)--组件拥有定义好的I/O数据接口格式;信息系统中心库(Repository)或黑板--共享信息存放在中心库中;客户-服务器--服务分布在位于不同地理位置的不同服务器上;状态机--其系统行为是以带有与每种状态有关的一套操作状态集为特征的。
----采用一种新的方法将软件设计记录下来使其成为模式。设计模式是框架,软件工程师可以通过它与他人交流设计决策的实施和构建,这样就促进了设计特性(designqualities)的使用,如可重复性(在多个上下文中使用一个设计过程)、可理解性(通过合适的文档资料进行设计的交流)以及可适应性(修改和扩展设计都很方便)。
----整个体系结构和程序设计都可被重用。随着对象技术的成熟,开发中设计阶段的重用范围大大增加。专业领域设计模式和框架也会将设计问题的解决方案予以记录,以便将来重用。编程语言
----最早的程序,是用机器代码编写的。开发、理解和调试既困难又费时间。而且,代码是不可移植的。接着是用汇编语言编写程序,然后是高级语言如Fortran、Cobol、Pascal、Ada、Algol 和C,最近又出现了像Smalltalk这样的面向对象的编程语言。这种发展对于具备可理解性和可维护性的抽象化和模块化概念给予了不断地支持。
----结构化的编程概念对编程语言产生了极大的影响。EdsgerDijkstra建议限制GOTO语句的使用。因此,对于结构化的程序,现代的编程语言支持三种控制结构(顺序、选择和迭代)。模块化概念通过将程序开发任务分成较小的、易于管理的模块,在很大程度上降低了程序的复杂度。
----影响语言发展的概念还有数据和行为的封装。该概念是在模拟语言67中被采用的。从那时起,它就被看作是软件开发中的关键概念。许多现代的面向对象的编程语言,如Smalltalk也支持它。
----信息隐藏限制程序只能访问相关数据。编程语言中块结构的使用,对限制程序中标识符使用的范围是很有用的。封装、信息隐藏和块结构是现代编程语言不可缺少的特征。----为了降低不断上升的软件开发费用,对现有组件和系统的重用和扩展是倍受关注的解决方案。重用性使得软件公司在开发新的应用程序时能够合理利用他们现有的应用程序,从而减少开销和劳动强度,尤其是在开发系列产品时。面向对象的语言也支持带有继承(接口和实现都可被继承)和参数化的重用。
----对编程语言的影响还包括GUIs和Internet。以前,由于编程人员必须编写文本代码来实现接口以及接口行为,因此开发GUI代码很困难。现在,诸如VisualBasic和VisualC++的可视化编程语言大大降低了GUI的开发强度。
----Internet作为一个支持GUI设计、网络通信和其他程序开发的集成环境平台,对编程语言也产生了影响。例如,Java就是为Internet软件开发而研制出的一种集成编程语言环境。
----由于用低级机器代码和汇编语言开发软件存在种种不足,促使新的语言概念不断涌现。70年代出现了简单易用的Pascal、Algo语言以及组合语言结构的C和Ada语言。80年代和90年代初,为GUI设计而研制的可视化编程语言例证了编程语言简单和灵活平衡的必要性。Java的研制,消除了诸如指针和重载的特征,也显示了保持编程语言简练同时仍能提供强大的语言结构以便实现不同任务的必要性。
测试
----通过软件测试、软件审查、可靠性模型、容错、形式说明和验证以及仿真可以实现软件的可靠性。目标要求严格的系统总是要求广泛深入地测试,以确保系统的正常运转。----测试过程化程序的传统技术包括:数据流测试、结构测试、代码执行、随机测试、变化测试,基于可靠性模型的测试以及功能测试。对面向对象的测试--如方法和消息排序--已逐步变得流行起来。
回归(regression)
----遗留代码使软件工程的焦点发生了变化,人们不再仅仅考虑开发,同时还要考虑维护。其结果之一就是回归测试,许多公司为此花费了大量资金。一些需要解决的相关问题是测试实例选择、测试实例相关性以及测试实例重新确认。
----软件开发商通常由于过早地发布"足够好"的软件而遭到批评。这正是软件可靠性模型所要解决的。随着GUI的日益流行,需要采用新的测试技术,如捕捉和重放。测试整个系统要比测试单个组件困难。多数测试技术并不对整体测试,而只是将重点放在单元和模块测试上。
审查
----软件审查技术,最早由MichaelFagan于1976年提出,它经历了许多变化同时被广泛地采用。一些审查只针对系统开发特定阶段,而另一些审查则将在前一开发阶段产生的信息用到下一阶段。基于验证的审查需要一个严格的检查过程,并采用谓词演算和程序验证技术来指导审查。审查不仅仅局限于代码,它已扩展到需求、设计和测试。为了确保系统的可靠性,可以重复进行审查。在检测软件开发各个阶段的故障方面,N次审查技术已尽显其作用。
----组测试(Grouptesting)可识别出现故障的组件。这种技术通过将正常运作的组件和新的组件结合的方法来测试新的组件是否有故障。它可被用来测试大型程序。
----测试实例的选择性重用能成功地减少测试的开销和工作量,并使测试时间从几个月缩短至几周。
----采用高级抽象概念编写测试实例时,可以用到面向对象技术。测试实例可通过抽象概念和相应代码之间的映射关系来生成。----自从RobertFloyd提出了软件的形式验证技术,诸如断言、代码执行、前置和后置条件等技术已被用于对安全性要求很高的系统中。
----尽管拥有各种工具,测试的开销和工作量仍然很大。因此,应该将测试嵌入整个软件开发周期中,包括需求检查、设计检查、代码审查、单元测试、多阶段组合测试、功能测试、验收测试和现场测试。应当明确定义每一阶段的目标及其所需工具,并确立与每阶段有关的责任和操作步骤。测试的这些不同阶段可以同时进行。在开发周期的每个阶段,错误和修改跟踪也很重要。
可靠性和安全
----软件系统的故障和缺陷都是由于开发过程中的人为错误造成的。因此,人们在系统中加入了检查故障并从故障中恢复的机制。冗余是实现软件容错的主要技术。传统的软件容错技术包括重试(再次执行指令,暂时的失败可能会被查出)、恢复块(由BrianRandell提出,一旦系统检查出主软件例程的失败,可采用备份的软件例程)、N版本编程法以及三重模块冗余。这些技术依靠失败检测和适度降级,有时是系统重新配置来实现。
----与这些可靠性机制相关的日常开销相当可观。例如:恢复块方案增加了系统的大小及开发工作量,同时需要验收测试以检查该版本是否按说明要求运行。N版本编程法则需要一个表决机制。这些在软件中增加的部分通常是很重要的,因为在执行备份例程时,出现故障的软件已运行在备用模式,它已不能再次承受失败。
----日常开销数目庞大也可能会使这些技术并不适于某些应用。商业、医疗和军事系统对软件的各项指标的重视程度有不同的优先次序。它们对待软件冒险(hazard)、冒险严重度(hazard severity)、组件危急度(componentcriticality)及任务持续时间的态度也是不同的。这种不同使得它们实现可靠性和安全性的方法也截然不同。例如:军舰上的应用对体积、重量和能源消耗的重视程度最低,其次是开销,最重视的是安全性和可靠性;而用于移植的医疗设备最重视的不仅是安全,还有体积、重量和能源消耗,最不重视的是开销。强调体积会限制容错技术的应用。
----可靠性模型通常是从开发者的观点(面向失败的)而不是从用户的观点出发的。用户的观点是:当失败出现时,我能得到多少服务。面向服务的失败分析模型比面向失败的模型更能满足用户的要求。
----尽管一旦了解系统结构和组件的可靠性,就可以预测硬件的可靠性,但在软件中却行不通。例如,硬件会磨损而软件不会,软件经常在变而硬件相对稳定。需要采用软件积木式组件── 经过严格测试可被组合在一起形成一个可靠系统的组件,来精确预测软件的可靠性。
软件的维护
----由于程序复杂且庞大,维护遗留程序的开销是巨大的。各种软件维护研究项目,如ESPRITⅡREDO,都试图解决软件维护和二次工程化问题。研究人员将这些技术标识为:易发故障代码段标识、预防性维护技术、配置控制、可跟踪性、程序分片及扩展、变量分类、相关性分析、图形调用生成、实体-联系图(E-R图)生成、涟波效应分析以及路径分析。然而,软件维护不可能完全自动进行。多数研究人员和实践者都采用一种半自动方式,必要时,还需要专业人员来处理。实践中的软件维护
----当前的软件维护包括程序理解、往返工程、增加最终用户的参与、二次工程化、对象识别、配置管理、版本控制和测试工具的集成以及回归测试。其中,程序理解从广义上讲可被分成两类:基于控制的软件理解技术和以数据为中心的方法。
----一些软件公司采用基于维护的软件开发形式,通过修改现存的源代码来开发软件。这种方式常见于编译器和操作系统的开发中。对代码所做的修改首先反映在用户文档中,然后通过审查或回归测试进行确认。这种方法得到了正向工程工具的支持。如编译器、跟踪器和配置管理系统。
----由于反向工程工具能帮助编程者理解现存代码,它们对这种基于维护的软件开发过程也有促进作用。这使得往返(既包括正向、又包括反向)工程工具在支持配置管理、版本控制、测试和回归测试方面显得格外重要。软件工程的发展趋势
----二次化工程是软件维护中不可缺少的部分,目前的趋势主要是针对数据集合或遗留的数据库系统进行二次化工程。过去的软件通常采用旧的数据库技术,如VSAM(虚拟存储访问法)或分层数据库管理系统。从这些技术向关系型或面向对象的数据库管理系统过渡是当前研究的主题。
----另外,最终用户能为软件维护提供有价值的信息。他们能识别系统的重要部分以及系统在性能和特征方面的发展方式。
----还有一个重要的趋势是将过程代码转化为与其等同的面向对象的代码。通过检查Fortran程序中的公共块或Cobol程序中的文件部分可以识别对象。面向对象的类不仅包括数据还包括方法定义,但识别与类有关的方法要比识别数据难得多。而且,必须检查方法间的相互作用,以减少面向对象代码中的复杂消息传递。
----毫无疑问,Internet及相关技术必将改变软件维护的方式。总有一天,软件维护会以分布和协作的方式进行。而软件的互操作性也会变得更易实现。
----软件维护不会因为软件技术的提高而消失。即使能根据设计说明书自动生成代码,说明书也需维护,即使面向对象开发带来了增强的可重用性和可靠性,软件仍旧会变化。
----软件工程在过去的30年里发生了巨大的变化。尽管软件应用和它的可行性技术都在发展,软件工程的主要议题仍然是相对稳定的。
----★在不同的开发过程中,创建和分析一个完整、一致的需求说明的最佳方式是什么?
----★创建一个强大的、可维护的设计的最佳策略是什么?
----★对于大型复杂的面向对象的软件工程来说,最佳的测试策略是什么?
----★快速产生出具有最高可靠性的代码的最佳途径是什么?
----解决上述问题并非易事。硬件技术已成熟到工程师们几乎每次都能采用完全一样的方法去实现其可靠的设计,而软件技术还未达到这种成熟程度。作为一个工程准则,软件工程技术必须做到易于使用和有效实用。随着遵循规定的过程和相关技术的软件开发组不断快速地开发出可靠的、可重用的功能强大的软件,整个软件工程将会不断成熟起来。