「Software Engineering-1」Overview & Software Analysis

Comprehensive analysis contributes to efficient software development

Posted by Culaccino on January 12, 2021

软件工程导论其实是我个人非常喜欢的一门专业课,它不仅仅是小白学习软件开发的入门指导,也是开发者在分析、设计、实现、测试、维护,然后不断往复的迭代循环中,将对软件开发的想法先验,变为一层层的经验后验,再抽象为软件工程这一集技术与管理于一体的学问、哲学。

这门课中实在有太多内容让我深感共鸣,小到对面向对象这一编程思想的感悟,大到对身边软件兴衰历史的思考,哪怕是回顾自己在数据结构、数据库、操作系统等课上做课题设计的过程,也能找到些许软件开发的影子。但由于各种不可抗力原因(别骂了别骂了),我这学期平日里没能好好学习这门课orz。我将软工的复习整理按照软件生命周期中的三个阶段,分为「定义(分析)」、「开发」、「维护」三章,我会尽可能把重点内容突出,但也会加很多自己的感悟在里面,所以很多表述会和书里的不一样,等之后空下来了应该会再细细啃一啃这本书。

1. 软件工程概述

软件危机

起因

  • 目前许多的软件专业人员忽视软件需求分析的重要性,对用户要求没有完整准确的认识就匆忙着手编写程序。主要体现在:①用户自身需求不明确;②用户需求在描述时存在遗漏、二义性,甚至错误;③开发过程中用户会有新的需求;④开发者对用户需求的理解产生偏差。
  • 软件开发规模变大,使得在中后期的维护代价大幅上升。软件的生命周期中,在前期引入变动时涉及的面较少,故而维护成本较低;而在中后期时,软件配置的许多成分已经完成,引入变动所涉及的逻辑、工程变更量巨大,使得付出的代价剧增。

消除途径

  • 技术上:应该推广使用在实践中总结出来的开发软件的成功技术方法,并研究更好更有效的方法;同时也要开发和使用更好的软件工具,改善软件工程支撑环境,提高软件开发效率。
  • 管理上:需要对计算机软件有正确的认识,软件并非一个程序,而是一个完整的配置,不是某种个体劳动的神秘技巧,而是一种组织良好、管理严密、各类人员协同配合、共同完成的工程项目。

软件工程

基本原理

①用分阶段的生命周期计划严格管理 ②坚持进行阶段评审 ③实行严格的产品控制 ④采用现代程序设计技术 ⑤结果应该能清楚地审查 ⑥开发小组的人员应该少而精 ⑦承认不断改进软件工程实践的必要性

方法学

  1. 传统方法学

    ​ 即生命周期方法学/结构化范型。该方法采用结构化(结构化分析、设计、实现)来完成开发任务,其将软件生命周期的全过程依次划分为若干个阶段,然后顺序完成每个阶段的任务。每个阶段的开始和结束都有严格的标准,结束前必须进行严格的技术审查和管理审查,需要提交高质量文档(通信工具)。

    ​ 这是一种将问题大而化小的解决思路,若将软件的整个生命周期视为一个”流程“,则该方法其实是一种「面向过程」的方法,只是该过程时间较长,且每一阶段间的衔接非常严格,以降低开发的出错率和维护代价。

  2. 面向对象方法学

    ​ 认为世界万物皆对象,将数据和行为看成同等重要,有「封装」、「继承」、「多态」三大特性。多态涉及到方法在编译时的动态选择,封装和继承主要体现在类与对象上,主要体现在:①面向对象程序由对象构成,程序中任何元素都是对象; ②对象是数据和行为(方法)的集合体,即对象既可以包括体现其属性的数据,也可以有体现其“功能”/“方法论”的行为(函数);③对象都可以划分为类,即抽象的「类」可以生成具体的「对象」实例;④存在父类(基类)与子类(派生类)的关系,类之间可以继承。

    ​ 面向对象方法学的出发点和基本准则尽可能地模拟了人类习惯的思维方式,软件中每个对象都是一个功能体,是个微小的程序,各司其职,又能互相配合,达到理想的效果。从而使描述问题的问题空间(问题域)与实现解法的解空间(求解域)在结构上尽可能一致。

我很喜欢书里的这一段话:

传统方法学强调自顶向下顺序地完成软件开发的各阶段任务,但人类认识客观世界解决现实问题的过程,是个渐进(螺旋上升)的过程。人的认识需要在继承已有的有关知识的基础上,经过多次反复才能逐步深化。在人的认识深化过程中,既包括了从一般到特殊的演绎思维过程,也包括从特殊到一半的归纳思维过程。

而面向对象方法学开发软件的过程,是一个主动地多次反复迭代的演化过程。面向对象方法在概念和表示方法上的一致性,保证了在各项开发活动之间的平滑过渡。面向对象方法普遍进行的对象分类过程,支持从特殊到一般的归纳思维过程;通过建立类等级而获得的继承性,支持从一般到特殊的演绎思维过程。

软件生命周期

总体:软件定义、软件开发、运行维护

  1. 软件定义:问题定义、可行性研究、需求分析
  2. 软件开发:总体设计、详细设计、编码和单元测试,综合测试
  3. 运行维护:软件维护

软件模型-瀑布模型

瀑布模型:唯一被广泛采用的生命周期模型。

  • 阶段的顺序性和依赖性:①阶段间完全串行,②上一阶段的文档输出即为下一阶段的文档输入
  • 推迟实现观点:设置”系统分析“和”系统设计“两个阶段,主要用于考虑逻辑模型,尽可能推迟物理实现
  • 质量保证观点:文档驱动,每个阶段都必须由相应的文档,并要经过严格审查。使系统维护变得容易一些。

现实中,由于有很多错误在文档检查中是难以发现的,只有在实际实践时才会得到问题反馈,故而现实中的瀑布模型有”反馈带“,发现问题后精确定位到各个相应的阶段,然后依旧以”需求分析-规格说明-设计-编码-综合测试“这一流程下来。

但瀑布模型成也文档,败也文档。用户在拿到具体软件前没办法拿到软件样品,只能通过文档来认识软件,但要求用户不经过实践就提出完整准确的需求,在许多情况下是不切实际的,这就导致用户需求分析往往会出现差错,进一步导致维护的困难。

2. 可行性研究

可行性研究概述

用于确定问题是否值得去解决,判断系统完成后带来的效益是否大到值得投资开发这个系统的程度。即可行性研究是在较高层次上以较抽象的方式进行的系统分析和设计的过程。

具体流程:

  • 复查系统规模和目标:澄清、分析问题定义
  • 研究目前正在使用的系统:注意分析系统的可用性、费用等方面,并分析可改进处
  • 导出新系统的高层逻辑模型:现有物理系统->现有系统逻辑模型->目标系统的逻辑模型->改造新的物理系统
  • 进一步定义问题:以数据流图&数据字典作为基础,明确新系统必须做什么。
  • 导出和评价供选择的解法:提供若干个较高层次的物理解法,从技术的角度选择出最后可能的物理系统。操作可行选择:根据使用部门处理事务的原则和习惯。经济可行选择:估计余下的每个可能的系统开发成本和运行费用。
  • 推荐行动方针:选择出综合得分最高的方案作为实施方针,并做好详细的成本/效益分析。
  • 草拟开发计划
  • 书写文档提交审查

数据流图&数据字典

数据流图描绘信息流和数据从输入移动到输出的过程中所经受的变换,不涉及物理部件,仅描绘数据在软件中的流动和被处理的逻辑过程。根据需求陈述进行数据流图建模等样例见作业。

数据字典是对数据流图中所有元素的定义的集合,用于解释、提供描述信息。

数据字典和数据流图共同构成系统的逻辑模型。

成本/效益分析

货币的时间价值计算:

\[F=P(1+i)^n\]

其中,i为年利率,P为原始资金,F为n年后的总资金 。

3. 需求分析

需求分析任务

  • 确定对系统的综合要求

    • 功能需求
    • 性能需求
    • 可靠性和可用性需求
    • 出错处理需求
    • 接口需求:描述应用系统与它的环境通信的格式
    • 约束
    • 逆向需求:说明软件系统不应该做什么
    • 将来可能提出的要求:保证软件具有扩充性
  • 分析系统的数据要求

    ​ 大规模的数据具有许多基本的数据元素,系统所采用的数据结构体现了元素间的逻辑关系。通常数据字典可以准确定义逻辑关系,但仍需借助图形工具将其形象化。

  • 导出系统的逻辑模型

  • 修正系统开发计划

与用户沟通获取需求

面向数据流自顶向下求精

不同于可行性分析阶段,需求分析阶段需要把数据流和数据存储定义到元素级。 系统中数据一般来自于外部输入、或系统中间过程的生成量,而外部输入的数据即代表用户的需求。开发者需要根据数据流图追根溯源,找到系统中数据的来源,对于找不到的来源的数据,要请教用户和其他有关人员,并细化数据流图,将新划分出的数据元素记录至数据字典,并将算法记录在IPO图(用于记录算法的图形工具)中。

随着分析过程的进展,经过提问和解答的反复循环,分析员即可深入具体定义目标系统,最终得到对系统数据和功能要求的满意了解。

数据分析&建模

实体-联系图(ER图)

在数据库建模中常用,ER图用于秒回数据对象之间的关系,用于建立数据模型。

数据对象:由一组属性来定义的实体。对应面向对象方法中的”类“,区别在于无封装的方法。 属性:数据对象的性质。当一个或多个属性能够唯一确定某一数据对象的其中一个实例时,该属性(组)被称为”标识符“。每个数据对象必须有标识符。 联系:数据对象彼此之间的关系。有一对一、一对多、多对多三种联系。联系也能有属性。

数据规范化

  1. 第一范式:每个属性值必须是原子值。
  2. 第二范式:满足第一范式,且每个非关键字属性都由整个关键字决定。
  3. 第三范式:满足第二范式,且一个非关键字仅依赖于整个关键字,而不能依赖于另一个非关键字。

状态转换图

状态:初态、中间状态、终态。 事件:引起系统做动作/状态转移的控制信息 符号:初态实心圆,终态同心圆,中间状态用圆角矩阵表示(必须有状态的名称,剩余的变量取值和活动可加可不加,活动表:(参数表)/动作表达式),箭头上加上事件:事件名(参数表)。 具体可参考下图:

验证软件需求

需要从一致性、完整性、现实性、有效性四个方面进行验证。

  • 一致性

    利用形式化的需求陈述语言来写软件需求规格说明书,即可用软件工具验证需求的一致性。

  • 现实性

    参考以往的开发经验,分析现有的软硬件技术,辅以仿真/性能模拟技术,分析需求的现实性。

  • 完整性和有效性

    需要与用户密切合作,以确定系统的需求实现是否完备。可以先做一个原型系统,请用户试用一段时间,让用户认识到自己实际需要什么,在此基础上再写正式的规格说明书。