概括地说,软件工程是指导计算机软件开发和维护的一门工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。
人们曾经给软件工程下过许多定义,下面给出两个典型的定义。
1968 年在第一届NATO会议上曾经给出了软件工程的一个早期定义:“软件工程就是为了经济地获得可靠的且能在实际机器上有效地运行的软件,而建立和使用完善的工程原理。”这个定义不仅指出了软件工程的目标是经济地开发出高质量的软件,而且强调了软件工程是一门工程学科,它应该建立并使用完善的工程原理。
1993年IEEE进一步给出了一个更全面更具体的定义:“软件工程是:① 把系统的、规范的、可度量的途径应用于软件开发、运行和维护过程,也就是把工程应用于软件;② 研究①中提到的途径。”
虽然软件工程的不同定义使用了不同词句,强调的重点也有差异,但是,人们普遍认为软件工程具有下述的本质特性。
1.软件工程关注于大型程序的构造
“大”与“小”的分界线并不十分清晰。通常把一个人在较短时间内写出的程序称为小型程序,而把多人合作用时半年以上才写出的程序称为大型程序。传统的程序设计技术和工具是支持小型程序设计的,不能简单地把这些技术和工具用于开发大型程序。
事实上,在此处使用术语“程序”并不十分恰当,现在的软件开发项目通常构造出包含若干个相关程序的“系统”。
2.软件工程的中心课题是控制复杂性
通常,软件所解决的问题十分复杂.以致不能把问题作为一个整体通盘考虑。人们不得不把问题分解,使得分解出的每个部分是可理解的,而且各部分之间保持简单的通信关系。用这种方法并不能降低问题的整体复杂性,但是却可使它变成可以管理的。注意,许多软件的复杂性主要不是由问题的内在复杂性造成的,而是由必须处理的大量细节造成的。
3.软件经常变化
绝大多数软件都模拟了现实世界的某部分,例如,处理读者对图书馆提出的需求或跟踪银行内钱的流通过程。现实世界在不断变化.软件为了不被很快淘汰,必须随着所模拟的现实世界一起变化。因此,在软件系统交付使用后仍然需要耗费成本,而且在开发过程中必须考虑软件将来可能的变化。
4.开发软件的效率非常重要
目前,社会对新应用系统的需求超过了人力资源所能提供的限度,软件供不应求的现象日益严重。因此,软件工程的一个重要课题就是,寻求开发与维护软件的更好更有效的方法和工具。
5.和谐地合作是开发软件的关键
软件处理的问题十分庞大,必须多人协同工作才能解决这类问题。为了有效地合作,必须明确地规定每个人的责任和相互通信的方法。事实上仅有上述规定还不够,每个人还必须严格地按规定行事。为了迫使大家遵守规定,应该运用标准和规程。通常,可以用工具来支持这此标准和规程。总之,纪律是成功地完成软件开发项目的一个关键。
6.软件必须有效地支持它的用户
开发软件的目的是支持用户的工作。软件提供的功能应该能有效地协助用户完成他们的工作。如果用户对软件系统不满意,可以弃用该系统,或者立即提出新的需求。因此,仅仅用正确的方法构造系统还不够,还必须构造出正确的系统。
有效地支持用户意味着必须仔细地研究用户,以确定适当的功能需求、可用性要求及其他质量要求(例如,可靠性、响应时间等)。有效地支持用户还意味着,软件开发不仅应该提交软件产品,而且应该写出用户手时和培训材料,此外,还必须注意建立使用新系统的环境。例如,一个新的图书馆自动化系统将影响图书馆的工作流程,因此应该适当地培训用户.使他们习惯于新的工作流程。
7.在软件工程领域中是由具有一种文化背景的人替具有另一种文化背景的人创造产品
这个特性与前两个特性紧密相关。软件工程师是诸如Java程序设计、软件体系结构、测试或统一建模语言(UML)等方面的专家,他们通常并不是图书馆管理、耽空控制或银行事务等领域的专家,但是他们却不得不为这些领域开发应用系统。缺乏应用领域的相关知识,是软件开发项目出现问题的常见原因。
软件工程师不仅缺乏应用领域的实际知识,他们还缺乏该领域的文化知识。例如,软件开发者通过访谈、阅读书面文件等方法了解到用户组织的“正式”工作流程.然后用软件实现了这个工作流程。但是,决定软件系统成功与否的关被问题是.用户组织是否真正遵守这个工作流程。对于局外人来说,这个问题更难回答。
自从1968年在联邦德国召开的国际会议上正式提出并使用了“软件工程”这个术语以来,研究软件工程的专家学者们陆续提出了100多条关于软件工程的准则或“信条”。著名的软件工程专家B.W.Boehm综合这些学者们的意见并总结了TRW公司多年开发软件的经验,于1983年在一篇论文中提出了软件工程的7条基本原理。他认为这7条原理是确保软件产品质量和开发效率的原理的最小集合。这7条原理是互相独立的,其中任意6条原理的组合都不能代替另一条原理,因此,它们是缺一不可的最小集合。然而这7条原理又是相当完备的,人们虽然不能用数学方法严格证明它们是一个完备的集合,但是,可以证明在此之前己经提出的100多条软科工程原理都可以由这7条原理的任意组合蕴含或派生。
下面简要介绍软件工程的7条基本原理。
1.用分阶段的生命周期计划严格管理
有人经统计发现,在不成功的软件项目中有一半左右是由于计划不周造成的,可见把建立完善的计划作为第一条基本原理是吸取了前人的教训而提出来的。
在软件开发与维护的漫长的生命周期中,需要完成许多性质各异的几作。这条基本原理意味着,应该把软件生命周期划分成若干个阶段,并相应地制定出切实可行的计划,然后严格按照计划对软件的开发与维护工作进行管理。
不同层次的管理人员都必须严格按照计划各尽其职地管理软件开发与维护工作,绝不能受客户或上级人员的影响而擅自背离预定计划。
2.坚持进行阶段评审
当时己经认识到,软件的质量保证工作不能等到编码阶段结束之后再进行。这样说至少有两个理由:第一,大部分错误是在编码之前造成的,例如,根据Boehm等人的统计,设计错误占软件错误的63%,编码错误仅占37%;第二,错误发现与改正得越晚,所需付出的代价也越高(参见图1.1)。因此,在每个阶段都进行严格的评审,以便尽早发现在软件开发过程中所犯的错误.是条必须遵循的重要原则。
3.实行严格的产品控制
在软件开发过程中不应随意改变需求,因为改变一项需求往往需要付出较高的代价。但是,在软件开发过程中改变需求又是难免的,只能依靠科学的产品控制技术来顺应这种要求。也就是说,当改变需求时,为了保持软件各个配置成分的一致性,必须实行严格的产品控制,其中主要是实行基准配置管理。所谓基准配置又称为基线配置,它们是经过阶段评审后的软件配置成分(各个阶段产生的文档或程序代码)。基准配置管理也称为变动控制:一切有关修改软件的建议,特别是涉及到对基准配置的修改建议,都必须按照严格的规程进行评审,获得批准以后才能实施修改。绝对不能谁想修改软件(包括尚在开发过程中的软件),就随意进行修改。
4.采用现代程序设计技术
从提出软件工程的概念开始,人们一直把主要精力用于研究各种新的程序设计技术,并进一步研究各种先进的软件开发与维护技术。实践表明,采用先进的技术不仅可以提高软件开发和维护的效率,而且可以提高软件产品的质量。
5.结果应能清楚地审查
软件产品不同于一般的物理产品,它是看不见摸不着的逻辑产品。轶件开发人员(或开发小组)的工作进展情况可见性差,难以准确度量,从而使得软件产品的开发过程比一般产品的开发过程更难于评价和管理。为了提高软件开发过程的可见性,更好地进行管理,应该根据软件开发项目的总目标及完成期限,规定开发组织的责任和产品标准,从而使得所得到的结果能够清楚地审查。
6.开发小组的人员应该少而精
这条基本原理的含义是,软件开发小组的组成人员的素质应该好,而人数则不宜过多。开发小组人员的素质和数量是影响软件产品质量和开发效率的重要因素。素质高的人员的开发效率比素质低的人员的开发效率可能高几倍至几十倍,而且素质高的人员所开发的软件中的错误明显少于素质低的人员所开发的软件中的错误。此外,随着开发小组人员数目的增加,因为交流情况讨论问题而造成的通信开销也急剧增加。当开发小组人员数为N时,可能的通信路径有N(N-1)/ 2条,可见随着人数N的增大,通信开销将急剧增加。因此,组成少而精的开发小组是软件工程的一条基本原理。
7.承认不断改进软件工程实践的必要性
遵循上述6条基本原理,就能够按照当代软件工程基本原理实现软件的工程化生产,但是,仅有上述6条原理并不能保证软件开发与维护的过程能赶上时代前进的步伐,能跟上技术的不断进步。因此,Boehm提出应把承认不断改进软件工程实践的必要性作为软件工程的第7条基本原理。按照这条原理,不仅要积极主动地采纳新的软件技术,而且要注意不断总结经验,例如,收集进度和资源耗费数据,收集出错类型和问题报告数据等。这些数据不仅可以用来评价新的软件技术的效果,而且可以用来指明必须着重开发的软件工具和应该优先研究的技术。
前面己经讲过,软件工程包括技术和管理两方面的内容,是技术与管理紧密结合所形成的工程学科。
所谓管理就是通过计划、组织和控制等一系列活动,合理地配置和使用各种资源,以达到既定目标的过程。本书第13章将讨论软件项目管理问题。
通常把在软件生命周期全过程中使用的一整套技术方法的集合称为方法学(methodology),也称为范型(paradigm)。在软件工程领域中,这两个术语的含义基本相同。
软件工程方法学包含3个要素:方法、工具和过程。其中,方法是完成软件开发的各项任务的技术方法,回答“怎样做”的问题;工具是为运用方法而提供的自动的或半自动的软科工程支撑环境;过程是为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。
目前使用得最广泛的软件工程方法学,分别是传统方法学和面向对象方法学。
1.传统方法学
传统方法学也称为生命周期方法学或结构化范型。它采用结构化技术(结构化分析、结构化设计和结构化实现)来完成软件开发的各项任务,并使用适当的软件工具或软件工程环境来支持结构化技术的运用。这种方法学把软件生命周期的全过程依次划分为若干个阶段,然后顺序地完成每个阶段的任务。采用这种方法学开发软件的时候,从对问题的抽象逻辑分析开始,一个阶段一个阶段地进行开发。前一个阶段任务的完成是开始进行后一个阶段工作的前提和基础,而后一阶段任务的完成通常是使前一阶段提出的解法更进一步具体化,加进了更多的实现细节。每一个阶段的开始和结束都有严格标准,对于任何两个相邻的阶段而言,前一阶段的结束标准就是后一阶段的开始标准。在每一个阶段结束之前都必须进行正式严格的技术审查和管理复审,从技术和管理两方面对这个阶段的开发成果进行检查,通过之后这个阶段才算结束;如果没通过检查,则必须进行必要的返工,而且返工后还要再经过审查。审查的一条主要标准就是每个阶段都应该交出“最新式的”(即和所开发的软件完全一致的)高质量的文档资料,从而保证在软件开发工程结束时有一个完整准确的软件配置交付使用。文档是通信的工具.它们清楚准确地说明了到这个时候为止,关于该项工程己经知道了什么,同时奠定了下一步工作的基础。此外,文档也起备忘录的作用,如果文档不完整,那么一定是某些工作忘记做了,在进入生命周期的下一个阶段之前,必须补足这些遗漏的细节。
把软件生命周期划分成若干个阶段,每个阶段的任务相对独立,而且比较简单,便于不同人员分工协作,从而降低了整个软件开发工程的困难程度;在软件生命周期的每个阶段都采用科学的管理技术和良好的技术方法,而且在每个阶段结束之前都从技术和管理两个角度进行严格的审查,合格之后才开始下一阶段的工作,这就使软件开发工程的全过程以一种有条不紊的方式进行,保证了软件的质量,特别是提高了软件的可维护性。总之,采用生命周期方法学可以大大提高软件开发的成功率,软件开发的生产率也能明显提高。
目前,传统方法学仍然是人们在开发软件时使用得十分广泛的软件工程方法学。这种方法学历史悠久,为广大软件工程师所熟悉,而且在开发某些类型的软件时也比较有效,因此,在相当长一段时期内这种方法学还会有生命力。此外,如果没有完全理解传统方法学,也就不能深入理解这种方法学与面向对象方法学的差别以及面向对象方法学为何优于传统方法学。因此,本书不仅讲述面向对象方法学,也讲述传统方法学。
2.面向对象方法学
当软件规模庞大,或者对软件的需求是模糊的或会随时间而变化的时候,使用传统方法学开发软件往往不成功,此外,使用传统方法学开发出的软件,维护起来仍然很困难。
结构化范型只能获得有限成功的一个重要原因是,这种技术要么面向行为(即对数据的操作),要么面向数据,还没有既面向数据又面向行为的结构化技术。众所周知,软件系统本质上是信息处理系统。离开了操作便无法更改数据,而脱离了数据的操作是毫无意义的。数据和对数据的处理原本是密切相关的,把数据和操作人为地分离成两个独立的部分,自然会增加软件开发与维护的难度。与传统方法相反,面向对象方法把数据和行为看成同等重要的,它是一种以数据为主线,把数据和对数据的操作紧密地结合起来的方法。
概括地说,面向对象方法学具有下述4个要点。
(1)把对象(object)作为融合了数据及在数据上的操作行为的统一的软件构件。面向对象程序是由对象组成的,程序中任何元素都是对象,复杂对象由比较简单的对象组合而成。也就是说,用对象分解取代了传统方法的功能分解。
(2)把所有对象都划分成类(class)。每个类都定义了一组数据和一组操作,类是对具有相同数据和相同操作的一组相似对象的定义。数据用于表示对象的静态属性,是对象的状态信息,而施加于数据之上的操作用于实现对象的动态行为。
(3)按照父类(或称为基类)与子类(或称为派生类)的关系,把若干个相关类组成一个层次结构的系统(也称为类等级)。在类等级中.下层派生类自动拥有上层基类中定义的数据和操作,这种现象称为继承。
(4)对象彼此间仅能通过发送消息互相联系。对象与传统数据有本质区别,它不是被动地等待外界对它施加操作,相反,它是数据处理的主体,必须向它发消息请求它执行它的某个操作以处理它的数据,而不能从外界直接对它的数据进行处理。也就是说,对象的所有私有信息都被封装在该对象内,不能从外界直接访问,这就是通常所说的封装性。
面向对象方法学的出发点和基本原则,是尽量模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界解决问题的方法与过程,从而使描述问题的问题空间(也称为问题域)与实现解法的解空间(也称为求解域)在结构上尽可能一致。
传统方法学强调自顶向下顺序地完成软件开发的各阶段任务。事实上,人类认识客观世界解决现实问题的过程,是一个渐进的过程。人的认识需要在继承已有的有关知识的基础上,经过多次反复才能逐步深化。在人的认识深化过程中,既包括了从一般到特殊的演绎思维过程,也包括了从特殊到一般的归纳思维过程。
用面向对象方法学开发软件的过程,是一个主动地多次反复迭代的演化过程。面向对象方法在概念和表示方法上的一致性,保证了在各项开发活动之间的平滑(即无缝)过渡。面向对象方法普遍进行的对象分类过程,支持从特殊到一般的归纳思维过程;通过建立类等级而获得的继承性,支持从一般到特殊的演绎思维过程。
正确地运用面向对象方法学开发软件,则最终的软件产品由许多较小的、基本上独立的对象组成,每个对象相当于一个微型程序,而且大多数对象都与现实世界中的实体相对应,因此,降低了软件产品的复杂性,提高了软件的可理解性,简化了软件的开发和维护工作。对象是相对独立的实体,容易在以后的软件产品中重复使用,因此,面向对象范型的另一个重要优点是促进了软件重用。面向对象方法特有的继承性和多态性,进一步提高了面向对象软件的可重用性。