第一章 概论
1.1 软件=程序+软件工程
众所周知,“程序=数据结构+算法”, 然而在实际应用中,这一说法又显得有些空泛。程序,在这里指的是源程序,就是一行行的代码。它们是建立在数据结构上的一些算法。程序还要对数据进行操作,这些数据有些是静态的(例如软件的图标、提示信息),有些是动态的(例如程序生成的随机数字、程序通过网络下载的数据、用户的文字或语音输入等)。但是光有代码和静态数据还是不行,工程师要把它们构建成为机器能懂的可执行代码。构建不仅仅是cc和link命令,一个复杂的软件不但要有合理的软件构架、软件设计与实现,还要有各种文件和数据来描述各个程序文件之间的依赖关系、编译参数、链接参数,等等。这些都是软件构建的过程。
怎么保证软件在修改过程中质量不断提高,至少要维持以前的质量?这是源代码管理的问题——也叫配置管理。我们还有一系列的工具、流程和文档来保证程序的正确性,这些工具(也是软件)、流程应该达到很高的质量,才能保证开发出来的软件的质量。这就是质量保障,具体验证过程叫做软件测试。
软件团队要从需求分析开始,把合适的需求梳理出来,然后逐步展开后续工作。软件团队的人员也会流动,新的成员要尽快读懂已有的程序,了解程序的设计,这叫程序理解。软件在运行过程中还会出现这样那样的问题,也许我们要时不时给软件打一个补丁,或者维护众多的服务,团队的新老成员要一起修复各种各样的问题,这叫软件维护,或者服务运营。这一系列过程就是软件的生命周期,有人得负责软件项目的管理。
一个好的软件,即使功能和同类软件区别不大,但却会让人感到非常好用。这就是软件的用户体验。用户体验和数据结构、算法没有直接关系,但是很多非常成功的软件就赢在这个方面。
软件工程的核心部分为:构建管理、源代码管理、软件设计、软件测试、项目管理。广义上的软件工程也包括用户体验、用户界面设计等。所以一个推论是:软件=程序+软件工程。一个扩展的推论是:软件企业=软件+商业模式。
将软件开发类比于航空产业,软件开发可以分为四个不同的阶段,分别是:练习、尝试、探索、成熟的产业模式。然而无论是软件开发还是航空航天产业,作为一个合格的业内人员,都必须要做到在安全平稳的基础上提高技术水平,不能舍本逐末。
1.2 软件工程是什么
软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上的过程。软件工程包括下列领域:软件需求分析、软件设计、软件构建、软件测试和软件维护。
人们在开发、运营、维护软件的过程中有很多技术、做法、习惯和思想体系。软件工程把这些相关的技术和过程统一到一个体系中,叫“软件开发流程”。软件开发流程的目的是为了提高软件开发、运营、维护的效率,并提高软件的质量、用户满意度、可靠性和软件的可维护性。光有各种流程的思想是不够的,我们还要有一系列的工具来保证这些思想能够在实践中有效率地运作。软件工具有很多:有工程师自行开发的工具,有软件团队独有的工具,也有许多公开的软件工具,例如编译工具、源代码管理工具、源代码编辑工具;也有一些软件工具系统,例如Microsoft Visual Studio、GitHub、Eclipse、ClearCase和ClearQuest,等等。
1.2.1 软件的特殊性
软件是可以运行在计算机及电子设备中的指令和数据的有序集合。软件有各种分类方法,其中一种是:
- 系统软件:操作系统、设备驱动程序、工具软件等、
- 应用软件:用户使用它们来完成工作,从管理核电厂到写文章,或者是通信、游戏、浏览网页、播放视频等
- 恶意软件:软件病毒等
软件和人类制造出来的其他产品相比,有许多共性,也有一些特殊性。它们都是解决某种需求。我们知道许多计算机硬件的能力大致以每两年提高一倍的速度发展,而软件开发的流程却没有这样的提速过程,开发成本也没有下降,为什么?软件开发过程有什么特别的难题?学者们总结了以下五点:
- 复杂性
软件可以说是人类创造的最复杂的系统类型。大型软件(操作系统、办公软件、搜索引擎)有超过百万行的源代码,上万个不同的文件。而软件工程师的肉眼通常一次只能看到30-80行源代码(相当于显示器的一屏),他们的智力、记忆力和常人差不多,在过去的几十年中并没有大的提高。软件的各个模块之间有各种显性或隐性的依赖关系,随着系统的成长和模块的增多,这些关系的数量往往以几何级数的速度增长。而理解运用这些复杂性的人并没有太大的变化。
2.不可见性
软件工程师能直接看见源代码,但是源代码不是软件本身。软件以机器码的形式高速运行,还可能在几个CPU核上同时运行,工程师是“看”不到自己的源代码如何具体地在用户的机器上被执行的。商用软件出现了错误,工程师可以看到程序在出错的一瞬间留下的一些痕迹(错误代号、大致的目标代码位置、错误信息),但是几乎无法完整重现到底程序出现了什么问题。当工程师回过头来看源代码时,它们还是安静地排列在屏幕上。
3.易变性
软件看上去很容易修改,修改软件比修改硬件容易多了。人们自然地期待软件能在下面两种情况下“改变”:a、让软件做新的事情;b、让软件适应新的硬件。但是与此同时,正确地修改软件是一件很困难的事情
4.服从性
软件不能独立存在,它总是要运行在硬件上面,它要服从系统中其他组成部分的要求,它还要服从用户的要求、行业系统的要求(例如银行利率的变化)。
5.非连续性
人们比较容易理解连续的系统:增加输入,就能看到相应输出的增加。但是许多软件系统却没有这样的特性,有时输入上很小的变化,会引起输出上极大的变化。
这些特性的前四个是佛瑞德·布鲁克斯在No Silver Bullet一文中提到的,第五个特性是瓦茨拉夫·拉里奇提到的。这些特性是由软件的本质所决定的,软件还有其他特性:
- 有许多不同的程序设计语言、软件工具和软件开发平台
- 存在许多不同的软件开发流程
- 软件团队中存在许多不同的角色
- 软件既可以存储在磁带上,也可以存储在CD/DVD上
但是这些非本质、临时的特性并不能决定软件工程的本质问题。
1.2.2 软件工程与计算机科学的关系
软件工程中的“工程”二字也大有来历,人们把下面的活动称之为工程:
创造性地运用科学原理,设计和实现建筑、机器、装置或生产过程;或者是在实践中使用一个或多个上述实体;或者是实现这些实体的过程。
根据我们对软件特性及工程这一概念的了解,可以看到,计算机科学中的理论研究部分,大多可以从形式上证明,与数学、离散数学、数理逻辑密切相关;计算机科学中与实践相关的部分,都和数据以及其他学科发生关系;软件工程则和人的行为、现实社会的需求息息相关。软件工程的研究目标(软件的开发、运营和维护)中都有“人”出现,这些“人”可以是项目需求的提供者,可以是软件的开发人员,还可以是软件的用户。这一特征与其他计算机科学的子领域明显不同。其实,在任何科学领域中,都是偏理论的子领域和偏应用的子领域(例如数学与应用数学),当偏应用的领域得到长足发展之后,就会更多地被大家所熟知,甚至成为一门独立的学科,这并不说明相对应的两方面有高低或优劣之分。
计算机科学和软件工程的不同侧重点
计算机科学 | 软件工程 |
发现和研究长期的、客观的真理 |
短裙的实际结果(具体的软件会过时) |
理想化的 | 对各种因素的折中 |
确定性、完美、通用性 | 对不确定性和风险的管理,足够好,具体的应用 |
各个学科独立深入研究,做出成果 | 关注和应用各个相关学科的知识、解决问题 |
理论的统一 | 百花齐放的实践方法 |
强调原创性 | 最好的、成熟的实践方法 |
形式化,追求简明的公式 | 在实践中建立起来的灵感和直觉 |
正确性 | 可靠性 |
计算机理论的进展会帮助软件工程(例如对程序正确性的分析);软件工程的进展(更好的工具,更多的应用领域)会帮助计算机科学家更有效地进行实验和探索。
1.2.3 软件工程的知识领域
软件工程共有15个知识领域(Knowledge Area,KA):
- Software Requirement
- Software Design
- Software Construction
- Software Testing
- Software Maintenance
- Software Configuration Management
- Software Engineering Management
- Software Engineering Process
- Software Engineering Models and Methods
- Software Quality
- Software Engineering Professional Practice
- Software Engineering Economics
- Computing Foundations
- Mathematical Foundations
- Engineering Foundations
需要指出的是,在上面的15个KA中,KA1-12描述了软件工程学科本身的知识领域;KA13-15描述了软件工程三大类基础知识领域:计算基础、数学基础和工程基础。
1.2.4 软件工程的目标——创造“足够好”的软件
什么是好的软件?一些同学认为,所谓好软件,就是软件没有缺陷(Bug),所谓软件工程,就是把软件中的Bug都消灭掉的过程。这的确是抓住了软件工程的一个要素。和软件打交道的专业人士都知道软件有“Bug”,软件团队的很多人都整天和Bug打交道,Bug的多少可以直接衡量一个软件的开发效率、用户满意度、可靠性和可维护性。例如:、
用户满意度:用户在使用时发现了软件的很多问题,影响了用户使用软件的效率。
可靠性:某个软件经常会崩溃,某个操作系统会时不时死机,某个网站往往在最需要的时候登不上去。
软件流程的质量:软件团队和开发流程的问题太多,导致团队成员无法互相协作,按时交付软件。这也可以说是软件团队的Bug。
可维护性:某个软件太难维护了,修复了一个问题,另一个问题又出来了。也没有足够的文档,维护人员表示需要更多的资金和时间来维护这个软件,甚至建议推到重写。
什么是Bug呢?简单地说,软件的行为和用户的期望值不一样,就叫Bug。是否是Bug,取决于用户和开发者的不同角度。软件工程的一个重要任务,就是要决定一个软件在什么时候能“足够好”,可以发布。