1.3 软件工程

1.3.1 软件工程的概念

1968年,在北大西洋公约组织举行的一次学术会议上,人们首次提出了软件工程这个概念。当时,该组织的科学委员们在开会讨论软件的可靠性与软件危机的问题时,提出了“软件工程”的概念,并将其定义为“为了经济地获得可靠的和能在实际机器上高效运行的软件,而建立和使用的健全的工程规则”。这个定义肯定了工程化的思想在软件工程中的重要性,但是并没有提到软件产品的特殊性。

随着40多年的发展,软件工程已经成为一门独立的学科,人们对软件工程也逐渐有了更全面、更科学的认识。

IEEE(Institute of Electrical and Electronics Engineers,电气和电子工程师协会)对软件工程的定义为:(1)将系统化、严格约束的、可量化的方法应用于软件的开发、运行和维护,即将工程化应用于软件。(2)对(1)中所述方法的研究。

具体说来,软件工程是以借鉴传统工程的原则、方法,以提高质量、降低成本为目的,指导计算机软件开发和维护的工程学科。它是一种层次化的技术,如图1-4所示。

48019-00-016-1

图1-4 软件工程层次

软件工程的根基就在于对质量的关注;软件工程的基础是过程层,它定义了一组关键过程区域的框架,使得软件能够被合理和及时地开发。软件工程的方法提供了建造软件在技术上需要“做什么”,它覆盖了一系列的任务,包括需求分析、设计、编程、测试和支持等。软件工程的工具对过程和方法提供了自动的或半自动的支持。而软件工程本身是一个交叉学科,涉及多种学科领域的相关知识,包括工程学、数学、计算机科学、经济学、管理学、心理学等。

软件工程以关注质量为目标,其中过程、方法和工具是软件工程的3个要素。

1.3.2 软件工程研究的内容

软件工程研究的内容主要包括以下两个部分。

(1)软件开发技术。主要研究软件开发方法、软件开发过程、软件开发工具和环境。

(2)软件开发过程管理。主要研究软件工程经济学和软件管理学。

必须强调的是,随着人们对软件系统研究的逐渐深入,软件工程研究的内容也在不断更新和发展。

1.3.3 软件工程的目标和原则

软件工程要达到的基本目标如下。

(1)达到要求的软件功能。

(2)取得较好的软件性能。

(3)开发出高质量的软件。

(4)付出较低的开发成本。

(5)需要较低的维护费用。

(6)能按时完成开发工作,及时交付使用。

为了达到上述目标,软件工程设计、工程支持以及工程管理在软件开发过程中必须遵循一些基本原则。著名软件工程专家B. Boehm综合了有关专家和学者的意见并总结了多年来开发软件的经验,提出了软件工程的7条基本原则。

1. 用分阶段的生命周期计划严格管理

将软件的生命周期划分为多个阶段,对各个阶段实行严格的项目管理。软件开发是一个漫长的过程,人们可以根据软件的特点或目标,把整个软件的开发周期划分为多个阶段,并为每个阶段制定分阶段的计划及验收标准,这样有益于管理整个软件开发过程。在传统的软件工程中,软件开发的生命周期可以划分为可行性研究、需求分析、软件设计、软件实现、软件测试、产品验收和交付等阶段。

2. 坚持进行阶段评审

严格贯彻与实施阶段评审制度可以帮助软件开发人员及时发现错误并将其改正。在软件开发过程中,错误发现得越晚,修复错误要付出的代价就会越大。实施阶段评审,只有在本阶段的工作通过评审后,才能进入下一阶段的工作。

3. 实行严格的产品控制

在软件开发过程中,用户需求很可能在不断地发生变化。有些时候,即使用户需求没有改变,软件开发人员受到经验的限制以及与客户交流不充分的影响,也很难做到一次性获取到全部正确的需求。可见,需求分析的工作应该贯穿到整个软件开发的生命周期。在软件开发的整个过程中,需求的改变是不可避免的。当需求更新时,为了保证软件各个配置项的一致性,实施严格的版本控制是非常必要的。

4. 采用现代程序设计技术

现代的程序设计技术,如面向对象,可以使开发出来的软件产品更易维护和修改,还能缩短开发的时间,并且更符合人们的思维逻辑。

5. 软件工程结果应能清楚地审查

虽然软件产品的可见性比较差,但是它的功能和质量应该能够被准确地审查和度量,这样才有利于有效管理项目。一般软件产品包括可以执行的源代码、一系列相应的文档和资源数据等。

6. 开发小组的人员应该少而精

开发小组成员的人数少有利于组内成员充分交流,这是高效团队管理的重要因素。而高素质的开发小组成员是影响软件产品的质量和开发效率的重要因素。

7. 承认不断改进软件工程实践的必要性

随着计算机科学技术的发展,软件从业人员应该不断地总结经验并且主动学习新的软件技术,只有这样才能不落后于时代。

B. Boehm指出,遵循前6条基本原则,能够实现软件的工程化生产;按照第7条原则,不仅要积极主动地采纳新的软件技术,而且要注意不断总结经验。

1.3.4 软件工程的知识体系

IEEE在2014年发布的《软件工程知识体系指南》中将软件工程知识体系划分为以下15个知识领域。

1. 软件需求

软件需求(Software Requirements)涉及软件需求的获取、分析、规格说明和确认。

2. 软件设计

软件设计(Software Design)定义了一个系统或组件的体系结构、组件、接口和其他特征的过程以及这个过程的结果。

3. 软件构建

软件构建(Software Construction)是指通过编码、验证、单元测试、集成测试和调试的组合,详细地创建可工作的和有意义的软件。

4. 软件测试

软件测试(Software Testing)是为评价、改进产品的质量、标识产品的缺陷和问题而进行的活动。

5. 软件维护

软件维护(Software Maintenance)是指由于一个问题或改进的需要而修改代码和相关文档,进而修正现有的软件产品并保留其完整性的过程。

6. 软件配置管理

软件配置管理(Software Configuration Management)是一个支持性的软件生命周期过程,它是为了系统地控制配置变更,在软件系统的整个生命周期中维持配置的完整性和可追踪性,而标识系统在不同时间点上的配置的学科。

7. 软件工程管理

软件工程管理(Software Engineering Management)活动建立在组织和内部基础结构管理、项目管理、度量程序的计划制定和控制3个层次上。

8. 软件工程过程

软件工程过程(Software Engineering Process)涉及软件生命周期过程本身的定义、实现、评估、管理、变更和改进。

9. 软件工程模型和方法

软件工程模型和方法(Software Engineering Models and Methods)中的软件工程模型特指在软件的生产与使用、退役等各个过程中的参考模型的总称,诸如需求开发模型、架构设计模型等都属于软件工程模型的范畴。软件开发方法主要讨论软件开发的各种方法及其工作模型。

10. 软件质量

软件质量(Software Quality)特征涉及多个方面,保证软件产品的质量是软件工程的重要目标。

11. 软件工程职业实践

软件工程职业实践(Software Engineering Professional Practice)涉及软件工程师应履行其实践承诺,使软件的需求分析、规格说明、设计、开发、测试和维护成为一项有益和受人尊敬的职业,还包括团队精神和沟通技巧等内容。

12. 软件工程经济学

软件工程经济学(Software Engineering Economics)是研究为实现特定功能需求的软件工程项目而提出的在技术方案、生产(开发)过程、产品或服务等方面所做的经济服务与论证、计算与比较的一门系统方法论学科。

13. 计算基础

计算基础(Computing Foundations)涉及解决问题的技巧、抽象、编程基础、编程语言的基础知识、调试工具和技术、数据结构和表示、算法和复杂度、系统的基本概念、计算机的组织结构、编译基础知识、操作系统基础知识、数据库基础知识和数据管理、网络通信基础知识、并行和分布式计算、基本的用户人为因素、基本的开发人员人为因素和安全的软件开发和维护等方面的内容。

14. 数学基础

数学基础(Mathematical Foundations)涉及集合、关系和函数,基本的逻辑、证明技巧、计算的基础知识、图和树、离散概率、有限状态机、语法,数值精度、准确性和错误,数论和代数结构等方面的内容。

15. 工程基础

工程基础(Engineering Foundations)涉及实验方法和实验技术、统计分析、度量、工程设计,建模、模拟和建立原型,标准和影响因素分析等方面的内容。

软件工程知识体系的提出,让软件工程的内容更加清晰,也使其作为一个学科的定义和界限更加分明。

1.3.5 软件工程的发展

随着软件项目的规模和难度逐渐增大,以个人能力为基础的软件开发具有的弊端逐渐体现,随之出现了著名的“软件危机”。1968和1969年,两次里程碑似的“软件工程会议”在德国召开,许多顶尖级的研究员和工程师参加了这次会议,真正意义上的“软件工程”就此诞生。

20世纪70年代,人们开始采用与20世纪60年代的“编码和组装”相反的过程,先做系统需求分析,然后设计,最后编码,并把20世纪50年代硬件工程技术最好的方面和改进的软件方向的技术加以总结,提出了“瀑布模型”。需要指出的是,瀑布模型本身在提出时,是一个支持迭代和反复的模型。然后为了更方便地对软件进行约束,瀑布模型总是被解释为一种纯顺序化的模型,另外对瀑布模型的固定过程的标准解释也加深了这种误解。

另外,E. W. Dijkstra提出了“goto语句是有害的”论点,Bohm和Jacoponi从理论上证明了所有程序都可以转换为3种逻辑:顺序、分支、循环来实现,奠定了结构化编程的基础。随后,很多种结构化软件开发方法被提出,极大地改善了软件质量,提高了软件开发效率。数据结构和算法理论迅速发展,取得了很多重要成就;形式方法和程序证明技术也成为人们关注的发展焦点。

然而随着形式化模型和连续化的瀑布模型带来的问题大幅度增加,对于一个缺乏经验的团体来说,用形式化的方法,软件在可靠性和有用性上要达到要求十分困难。瀑布模型在文档编写时需要消耗很大的精力,而且速度慢,使用起来代价大。

伴随先前20世纪70年代开发的一些“最佳实践”,20世纪80年代开始了一系列工作以处理20世纪70年代遗留的问题,并且开始改进软件工程的生产效率和可测量性。COCOMO模型、CMM模型等被提出,软件体系结构相关研究和技术日益成熟,关系数据库被提出。

在软件工具方面,除了20世纪70年代已经出现的软件需求和设计工具,其他领域一些重要的工具也得到了改进,比如测试工具和配置管理工具。工具集和集成开发支持环境先后出现,最终人们将范围扩展到了计算机辅助软件工程(CASE),软件开发的效率进一步得到提高。

在其他方面也出现了一些潜在的提高软件生产率的方法,诸如专家系统、高级程序语言、面向对象、强大的工作站以及可视化编程等。1986年,Brooks在IFIP发表的著名论文《没有银弹》中对所有的这些方法发表了看法。他提出软件开发面临4个方面的核心挑战:高等级的软件复杂度、一致性、可变性和不可视性。关于如何解决这些挑战,他严重质疑了将技术说成是软件解决方案的“银弹”的观点。Brooks的解决这些核心挑战的候选方案包括:良好的设计者、快速原型、演化开发和通过复用降低工作量。

20世纪90年代,面向对象方法的强劲势头得以持续。这些方法通过设计模式、软件体系结构和体系结构描述语言以及UML技术的发展得到了加强。同时,Internet的继续扩展和WWW的出现同时增强了面向对象的方法以及市场竞争环境下软件的危险性。

开发者对增加软件竞争力以及缩减软件推向市场时间的需求,引发了从顺序的瀑布模型向其他模型的转变潮流,这类模型应该强调并行的工程性的需求、设计和编码,产品和过程以及软件和系统。软件复用成为软件开发中的重要内容,开源文化初露头角,可用性以及人机交互也成为软件开发的重要指标。

20世纪90年代末,出现了许多敏捷方法,如自适应软件开发、水晶项目开发、动态系统开发、极限编程、特征驱动开发、Scrum等。这些主要的敏捷方法的创始人在2001年齐聚一堂并发表了敏捷开发宣言。

在21世纪,对快速应用开发追求的趋势仍在继续,在信息技术、组织、竞争对策以及环境等方面的变革步伐也正在加快。云计算、大数据、物联网、人工智能和机器学习、移动互联网、三维打印、可穿戴式技术、虚拟现实、增强现实、社交媒体、无人驾驶汽车和飞机等技术不断涌现。这种快速的变革步伐引发了软件开发领域越来越多的困难和挫折,更多的软件开发过程、方法和工具也相继出现,软件工程在持续的机遇与挑战中不断发展。“大规模计算”“自治和生化计算机”“模型驱动体系结构”“构件化软件开发”等新领域都可能成为接下来软件工程发展的主要方向。