软件工程概述

当我学到这个跟我专业名字一模一样的课程时,我的心情真是很复杂:
一方面不知不觉已经学到了我专业的本命课程,这个大一时看课程计划觉得无比重要的课,倍感岁月不饶人;
另一方面,当我们学完这学期再审视这门课,又觉得它像Apple的一句广告:“说简单,也高深”。
说它简单,觉得它在一开始复习时恍惚有种背政治的感觉,比起烧脑的程序设计和巧妙计算来说真的很轻松;
说它高深,是因为如果让所有就业的软件工程毕业生投票自己最后悔没好好学的课,它一定是champion。

当你抱着一颗佛系的心看这些知识时,你会觉得它那么教条;但当你真的准备干点大事,带着挚友们开发个软件时,你会觉得它说的是那么针针见血:
如果你是负责人,你如何知道你需要什么招什么样的人来组成一个开发团队?你就是有了合适的团队你靠什么告诉客户你会花多长时间多少钱去完成这个项目才让他们放心把项目交给你?你就是拿到了项目你怎么让客户客观理性准确无误地告诉你他们的需求是什么?你就是得到了明确无疑的需求你怎么确定为了实现这个你该怎么设计这些功能?你就是得到了一份巧夺天工的设计你怎么保证你的程序员们能高效合作地把这些设计准确实现出来?你就是有了一批勤恳踏实的程序员写完了这些代码你怎么保证它们功能上没有错误?你就是所有功能都完美实现了你怎么保证它们合在一起还能干活?你就是把功能们合在一起天衣无缝你怎么交付给客户使用这个系统?你就是让客户心甘情愿地收下了这个系统你怎么保证用户用起来出了意外怎么维护?你就是维护好了这个系统你怎么迭代增量开发下一个系统让团队不会沦为临时工?……

总之,软件工程是整个专业的脉络,它的重要性随着你越来越接触到软件开发的核心而愈发凸显。

软件工程概述

这一章介绍软件工程的发展历程,其所使用的技术及工具;如何分析问题以及寻求解决方案;软件开发人员们取得的进展以及需要努力的方向;软件开发的涉及人员及Wasserman规范将实践融为一体的八个概念。

章节框架:

什么是软件工程

软件工程涉及的就是”软件开发的规范”,在规范里面体现出内在的思想与软件工程之规律。

问题求解

  • 分析(analysis):将问题分解成可以理解并能够处理的若干小部分,确定问题的本质含义。
  • 合成(synthesis):将每个小问题的解决方案组合成一个大的结构,合成解决方案。工具(tool):用更好的方式完成某事情的设备或自动化系统。
  • 过程(produce):把工具和技术结合起来,共同生产特定产品。
  • 范型(paradigm):构造软件的特定方法、途径或哲学(如面向对象开发的模式、结构化开发的模式、基于过程开发的模式、某种订制开发的模式)。

软件工程师的角色是什么

以计算机科学理论和计算机功能为基础,通过对要解决问题的本质的了解,采用相应的工具和技术,实现设计方案,推出高质量的软件产品。(将计算机作为问题求解的工具)

软件工程(SE)的定义、方法、作用

  • SE:在将有关软件开发与应用的概念科学体系化的基础上,研究如何有计划、有效率、经济地开发和利用能在计算机上正确运行的软件理论和技术工程的方法学,以及一些开发和维护软件的方法、过程、原则等。它是一个系统工程,既有对技术问题的综合分析,也有对开发过程和参与者的管理。
  • SE 的方法:面向对象模式,结构化模式,基于过程的模式等。
  • SE的作用:付出较低的开发成本,达到要求的软件功能,取得较好的软件性能,开发的软件易于移植,需要较低的维护费用,能按时完成开发工作,及时交付使用。

开发模式

软件开发的全部过程,活动和任务的结构框架,它能直观的表达软件开发全过程,明确要完成的主要活动,任务和开发策略。

软件工程取得了哪些进展

故障,错误和失效各自的含义(含举例)及它们之间的联系

  • 错误(error):是在软件开发过程中人为产生的错误(需求说明中的错误,代码中的错误)。
  • 故障(fault):软件功能实现过程中产生的问题,是错误导致的结果,是软件中一个错误的表现(一个错误可能产生多个故障,静态存在)。
  • 失效(failure):系统违背了它应有的行为(在系统交付前或交付后被发现,动态存在)。
  • 联系:人为原因导致程序[错误];该[错误]编译到系统中导致系统[故障];用户使用该系统时,因[故障]导致[失效]。故障是系统内部视图,从开发者的角度看待问题;失效是系统外部视图,从用户角度看到的问题。而且并不是所有的故障会导致失效,只要不执行故障代码,或者不进入某个特定状态,那么故障就不会使代码失效。

零缺陷软件

由于市场压力促使软件开发人员快速交付产品,零故障无法实现。

关于 bug

改正(fixing)有时比重写(rewriting)整个系统要困难。

错误修正的越晚,付出的代价越大。

复审(review)十分重要,是正式团队的行为规范;自己检查能只能找出开发阶段故障的1/5,同行评审能够揭示其余 4/5 的故障。

什么是好的软件

从三个方面考虑软件的质量:产品的质量、生产该产品的过程的质量以及在产品将使用的商业环境背景下的质量。

产品(product)的质量

用户:从失效的数目和类型等外部特性进行评价,如果软件具有足够的功能,并且易于学习和使用;或者虽然难以学习和使用,但是由于功能值得这些付出,用户就断定软件是高质量的。

开发者:从故障的数目和类型等内部特征来作为产品质量的依据。

过程(process)的质量

有很多过程都会影响到最终的产品质量,只要有活动出了差错,产品的质量就会受到影响;开发和维护过程的质量与产品的质量是同等重要的。

几个量化模型:CMM、ISO 9000、SPICE(了解)

商业(business)环境背景下的质量

  • 技术价值与商业价值的联系与区别:

    技术价值:技术指标(速度,正确的运行时间,维护成本等)。

    商业价值:机构对软件是否与其战略利益相吻合的一种价值评估。误区:技术质量不会自动转化为商业价值。

  • 目标:

    将技术价值和商业价值统一起来,改进过程所带来的商业价值。

软件工程涉及的人员

  • 客户(customer):为将要开发的软件系统支付费用的公司、组织或个人。

  • 开发者(developer):为客户构建软件系统的公司、组织或个人。

  • 用户(user):实际使用系统的人。

    有时,他们可能是同一个人或同一组人。

系统的开发方法

要开发一个项目,必须知道系统包含哪些对象或活动。

系统(system):实体、活动、关系、系统边界的集合。

软件系统的系统要素(组成)(对象(实体)+ 活动 +关系 + 系统边界)

活动和对象

活动(activity):活动是发生在系统中的某些事情,通常描述为由某个触发器引发的事件,活动通过改变某一特性把一个事物转变成另一个事物。

对象(object)或实体(entity):活动中涉及的元素称为对象或实体(如记录数据的对象)。

关系和系统边界

关系(relationship):对实体和活动间数据项及动作相互关系的描述。

系统边界(system boundary):用于描述系统中包含什么,不包含什么。

相互联系的系统

内容概述:几乎不存在与其他系统没有关联的系统,因此刻画系统边界十分重要,很容易了解什么在系统内部、什么不在以及什么超出了边界。系统可能存在于另一个系统中。边界定义的详细正确,那么根据较小的部分构建较大的系统是相对容易的。开发可以由内而外,但设计最好得由大到小,这就带来了难度。

增量式开发方法:包含一系列阶段,其中每一个阶段都使前面的系统不受当前系统约束的限制。系统逐渐地从旧的软件和硬件中脱离开,直到它体现出新系统的设计。

工程化的方法

大型软件开发过程中的工程化途径与方法

构建系统

现代软件工程大致包含的几个阶段及各个阶段文档:

  1. 需求分析:包括问题定义、可行性研究、需求分析【《SRS》即《软件需求规格说明书》】与复审(所有人)。
  2. 系统设计:包括用户界面的设计【《SAD》即《软件系统结构图》:如何制作软件】与复审(开发者与客户)。
  3. 程序设计:包括模块功能算法与数据描述设计【相关文档】与复审(开发者)。
  4. 程序实现:包括编程与 debug【源代码和注释】与复审(开发者、码农)。
  5. 单元测试:模块功能测试与性能测试【测试报告】与复审(测试团队)。
  6. 集成测试:按照结构图进行测试【测试报告】与复审(测试团队)。
  7. 系统测试:按《SRS》对系统总体功能进行测试与复审(开发者与客户)。
  8. 系统提交:交付产品【用户手册和操作手册】与复审。
  9. 系统维修:修改软件的过程,为改错或满足新需求【维修报告】与复审(维修团队)。

注:圆括号中的为测试人员,方括号为生成的文档。

额外说明(了解):以上阶段只是大致的划分,软件团队实际执行时比这要复杂,还有若干辅助性过程和阶段,而有些阶段实际是相互重叠、相互影响的。

开发团队的成员

需求分析人员、设计人员、程序员、测试人员、培训人员、维护人员、资料管理人员、配置管理人员。

软件工程各阶段各自的工作:(了解)

  • 需求设计(分析员、客户):将客户想要的分解为离散需求。
  • 系统设计(分析员、设计员):生成系统层描述(系统要做什么)。程序设计(设计员、程序员):实现指定需求的代码。
  • 程序实现(程序员):编代码。
  • 单元测试(程序员、测试员):发现各种错误。集成测试(测试团队):检查系统功能。
  • 系统测试(测试员、客户、培训员):根据《SRS》检查要求。系统交付(培训员):培训用户。
  • 系统维修(维修团队):寻找故障,根据客户需求变化,对系统作出修改。
  • 资料管理(资料管理员):维持一个软件的不同版本之间各种文档的对应关系,包括需求规格说明、设计描述、程序文档、培训手册、测试数据进度等。
  • 配置管理(配置管理员):维护需求、设计、实现和测试之间的对应关系。
  • 软件架构师:属于高级程序员,侧重开发过程和模式的选择和论证(在国内和分析员差不多,其工作重点与分析员有所不同,但就开发来说,其工作似乎更重要些,而分析员的工作更偏重于市场与用户需求)。

软件工程发生了多大的变化

变化的本质

早期程序:线性输入,输出为字母数字,系统设计方式分为两种:转换(transformation):将输入转换为输出;事务(transaction):由输入决定哪个功能将被执行。因此瀑布模型开发方式可行。

当今程序:多系统运行,跨平台运行,基础功能:网络控制,安全性,用户界面表示和处理,以及数据或对象管理等。相较于早期变化巨大,瀑布模型不适用。

使现代软件工程实践发生变化的七个关键因素

  1. 商用产品投入市场时间的紧迫性

  2. 计算技术在经济中的转变:更低的硬件成本,更高的开发、维护成本

  3. 功能强大的桌面计算的可用性

  4. 广泛的局域网和广域网

  5. 面向对象技术的采用及其有效性

  6. 使用窗口、图标、菜单和指示器的图形用户界面

  7. 软件开发瀑布模型的不可预测性

说明(了解):瀑布模型沿袭了传统系统工程的大规模批发制造的理念,假定生产活动为线性,这与现代软件的生产方式相矛盾。不再是有足够的灵活性和适应性来满足并行开发或并行运行这样的商业软件需求,因此不可预测。

结论(了解):对一个系统进行划分,以便并行地开发其子系统,需要一个与瀑布模型有很大不同的开发模型。

软件工程的 Wasserman 规范(或基本概念)

  1. 抽象:基于某种层次归纳水平的问题描述。它使我们将注意力集中在问题的关键方面而非细节。

  2. 分析、设计方法和符号描述系统:

    使用标准表示来对程序进行描述。利于交流,利于建模并检查其完整性和一致性,利于对需求和设计部件进行重用。

  3. 用户界面原型化(prototyping):

    建立系统的小型版,
    通常具有有限的关键功能,以利于用户评价和选择,证明设计或方法的可行性。

  4. 软件体系结构:

    定义一组体系结构单元及其相互关系集来描述软件系统。单元分解的方法

    (以下了解)

    • 基于功能的模块化分解: 基于指派到模块的功能。
    • 基于数据的分解: 基于外部数据结构。
    • 面向事件的分解:基于系统必须处理的事件。
    • 由外到内的分解:基于系统用户的输入。
    • 面向对象的设计:基于标识的对象的类以及它们之间的相互关系。
  5. 软件过程:软件开发活动中的各种组织及规范方法。

    (以下了解)

    因应用类型和组织文化之间的巨大差异,故难以对软件过程本身进行预先指定,也就是说:使过程本身规范化是不可能的.软件过程不可能以抽象和模块化的方式作为软件工程的基础。

  6. 重用或复用(reuse):重复采用以前开发的软件系统中具有共性的部件,用到新的开发项目中去 (注: 这里的重用绝不仅仅是源代码的重用)。

  7. 测度或度量(measurement):通用的评价方法和体系,有助于使过程和产品的特定特性更加可见,包括量化描述系统、量化审核系统。

  8. 工具和集成环境:通过框架比较软件工程环境提供的服务,以决定其好坏。工具:由于厂商很少针对整个开发生命周期,因此对于工具的比较集中于小的活动集,例如测试或设计。

    (以下了解)

    工具集成中必须处理的五个问题:(by Wasserman)

    平台集成、表示继承、过程集成、数据集成、控制集成。

总结:以上八个概念将软件工程作为一门科学学科,也是本书的八个线索。

章末案例思考

什么是软件危机?它有哪些典型表现?为什么会出现软件危机?

​ 软件危机:落后的软件生产方式无法满足迅速增长的计算机软件需求,从而导致软件开发与维护过程中出现一系列严重问题的现象。

​ 典型表现:

  1. 对软件开发成本和进度的估计常常很不准确。

  2. 用户对”已完成”软件系统不满意的现象经常发生。

  3. 软件产品的质量往往靠不住。

  4. 软件常常是不可维护的。

  5. 软件通常没有适当的文档资料。

  6. 软件成本在计算机系统总成本中所占的比例逐年上升。

  7. 软件开发生产率提高的速度,远跟不上计算机应用迅速普及深入的趋势。

出现的原因:一方面与软件本身的特点有关,另一方面也和软件开发与维护的方法不正确有关。

  1. 软件缺乏”可见性”,管理和控制软件开发过程相当困难。
  2. 软件规模庞大,而且程序复杂性将随着程序规模的增加而呈指数上升。
  3. 开发时期引入错误,导致软件维护通常意味着改正或修改原来的设计,客观上使得软件较难维护。
  4. 软件专业人员对软件开发和维护中或多或少地采用了错误的方法和技术。

典型例题

答案:A