软件是计算机系统与硬件相互依存的另一部分,它包括程序、数据及其相关文档的完整集合.
软件=程序+数据+文档
程序=算法+数据结构
程序设计阶段 ——50-60年代
程序系统阶段 ——60-70年代
软件工程阶段 ——70年代以后
在计算机软件开发和维护过程中所遇到的一系列严重问题
例1:2018年3月20日凌晨,亚利桑那州坦佩市(Tempe, Arizona)一辆正在进行自动驾驶测试的UBER测试车撞到一名女子,并且该女子在送往医院后就不治身亡,这也成为自动驾驶汽车全球首例致行人死亡事故。事发时,Uber的无人车传感器已经探测到这位正在横穿马路的行人,但自动驾驶软件没有在当下采取避让措施。上述案例体现了软件危机的哪种具体表现?
正确答案(C)
- A、软件维护困难
- B、软件工期拖延、成本超支
- C、软件质量难以保证
例2:System/360是IBM在1964年4月7日推出的划时代的大型电脑,这一系列是世界上首个指令集可兼容计算机。IBM360系统一共写出了100万行源程序,但发行的每一新版本都是上一版1000个错误的修正。这体现了软件危机的哪种具体表现?
正确答案(A)
- A、软件维护困难
- B、软件开发工期拖延、成本超支
- C、软件质量难以保证
- D、软件需求经常变化
例3:软件危机的产生原因之一是误认为软件开发就是写程序并设法使之运行
正确答案(A)
- A、√
- B、×
例4:(多选题)《荀子·劝学》中说:“假舆马者,非利足也,而致千里;假舟楫者,非能水也,而绝江河。君子生非异也,善假于物也。”,如何理解这句话?
正确答案(ABC)
- A、在软件开发和维护的每个阶段都有许多繁琐重复的工作需要做,在适当的软件工具辅助下,可以把这类工作做得既快又好。
- B、软件工程支撑环境是把各个阶段使用的软件工具有机地集合成一个整体,支持软件开发的全过程,可以提高软件开发的效率和质量。
- C、应对软件危机,就要鸠工庀材,善假于物,应该开发和使用更好的软件工具。
- D、利用软件工具可以解决软件危机中的一切问题。
定义:把软件生命周期全过程中使用的一整套技术方法的集合称为方法学,也称为泛型
方法:怎莫作
工具:运行方法所提供的软件工程支撑环境
过程:为获得高质量软件所需要的一系列任务框架
速记:结构化、阶段
速记:数据、对象、层次结构、类
下图展示的是哪种软件过程模型?( )
正确答案(B)
- A、快速原型模型
- B、瀑布模型
目的:用最小的代价在最小的时间内确认问题是否能够解决
实质:系统分析和设计过程的大大压缩和简化,在较高层次上以较为抽象的方式进行系统的分析和设计过程。
过程:
优点:随着结构的逐步精细,对数据结构的描绘也越来越详细
优点:简略描绘系统的主要算法
验证软件需求:
结构化设计:结构化设计(Structured Design, SD),是一种面向数据流的设计方法,目的在于确定软件的结构。
模块及模块化思想:
系统的模块数目增加,每个模块的规模减小,开发单个模块的成本减小,但是,随着模块数目增加,设计模块间接口的工作量增也加。
采用模块化原理可以使软件结构更加清晰,更加易于阅读和理解
逐步求精中每一层中的模块都是对系统抽象层次的一次精化
信息隐藏与局部化
耦合(Coupling)是指不同模块之间相互依赖程度的度量。
如果模块间必须存在耦合,就尽量使用数据耦合、少用控制耦合、限制公共耦合的范围以及坚决避免使用内容耦合。
内聚(Cohesion)是指一个模块之内各成分之间相互依赖程度的度量。
启发式是根据设计准则,从长期的软件开发实践中,总结出来的规则。它既不是设计目标,也不是设计时应普遍遵循的的原理。
设计出软件的初步结构以后,应该审查分析这个结构,通过模块分解或合并,力求降低耦合提高内聚。例如,多个模块公有的一个子功能可以独立成一个模块,由这些模块调用;有时可以通过分解或合并模块以减少控制信息的传递及对全程数据的引用,并且降低接口的复杂程度。
过大不易理解;太小则接口开销过大。
经验表明,一个模块的规模最好能写在一页纸内(通常不超过60行语句)。
深度:表示软件结构中控制的层数。
深度能粗略地标志一个系统的大小和复杂程度,深度和程序长度之间有粗略的对应关系
宽度:表示软件结构中控制的总跨度。
宽度是同一个层次上的模块总数的最大值,宽度越大系统越复杂;对宽度影响最大的因素是模块的扇出。
扇出:表示一个模块直接控制(调用)的模块数目扇出为3-4,上限扇出为5-9。
扇入:表示有多少个上级模块直接调用该模块扇入越大则共享该模块的上级模块数目越多。
模块的控制域:这个模块本身以及所有直接或间接从属于它的模块的集合。
模块的作用域:受该模块内一个判定影响的所有模块的集合。
在一个设计得很好的系统中,所有受判定影响的模块应该都从属于做出判定的那个模块,最好局限于做出判定的那个模块本身及它的直属下级模块。
模块接口复杂是软件发生错误的一个主要原因。应该仔细设计模块接口,使得信息传递简单并且和模块的功能一致。接口复杂或不一致(即看起来传递的数据之间没有联系),是紧耦合或低内聚的征兆,应该重新分析这个模块的独立性。接口复杂可能表明模块的独立性差。
这条启发式规则警告软件工程师不要使模块间出现内容耦合。当从顶部进入模块并且从底部退出来时,软件是比较容易理解的,因此也是比较容易维护的。
模块的功能应该能够预测,但也要防止模块功能过分局限。
判定树(Decision Tree)是一种描述加工的图形工具,适合描述问题处理中具有多个判断,而且每个决策与若干条件有关。使用判定树进行描述时,应该从问题的文字描述中分清哪些是判定条件,哪些是判定的决策,根据描述材料中的联结词找出判定条件的从属关系、并列关系、选择关系,根据它们构造判定树。
在网上商城系统中,管理员可以查看具体库存情况。详细描述如下:
- 若库存量小于等于0,则按缺货处理;否则,若库存量小于等于库存下限,则按下限报警处理;
- 若库存量大于库存下限,而又小于等于储备定额,则按订货处理;
- 若库存量大于库存下限,小于库存上线,而又大于储备定额,则按正常处理;
- 若库存量大于等于库存上线,而又大于储备定额,则按上限报警处理。
商城管理员根据用户欠款时间长短和现有库存情况处理用户订货的方案。
- 对于欠款时间小于等于30天的客户,若其需求量小于库存量,则立即发货;若库存量不足,则按库存发货,进货后再补发。
- 对于欠款时间大于30天且小于等于100天的客户,若其需求量小于库存量,则通知其先付款再发货;若库存量不足,则不发货。
- 对于欠款时间大于100天的客户,通知其先付欠款再议。
PAD是Problem Analysis Diagram的缩写,它是日本日立公司提出,由程序流程图演化来的,用结构化程序设计思想表现程序逻辑结构的图形工具。
用户在完成登陆后,可以进入到购物界面。在购物界面中,用户可以挑选商品,并且将商品加入到购物车中。之后用户可以选择是否停止购物,选择是会返回购物界面;选择否会进入确认订单页面。至此新建订单操作完成。
该模块的程序流程图如下:
N-S图,也被称为盒图或 NS 图(Nassi Shneiderman图),是结构化编程中的一种可视化建模。
用户进入用户登陆界面后,系统会提示用户曾经是否注册过账号。
- 若未注册过账号,则需进行新用户注册,之后再进行登陆操作;
- 若注册过账号,则直接填写完用户密码即可。之后点击登录按钮,通过密码审核即登录成功,否则重新执行用户登录操作。
- 登陆成功后,即进入购物界面,在购物界面中,用户可以选择关键字检索、分类商品、最新商品、推荐商品功能。
该模块的程序流程图如下:
性能要求:
如果所开发的软件的对性能有很高的要求,或者计算开销较大,那么最好使用静态的、可编译的语言,如C#,Java等。
用户的要求。
如果是用户来负责维护将来开发出来的软件,则用户一般要求使用他们熟悉的语言编写程序。
软件的运行平台。
软件的运行平台往往限制了编程语言的选择,如果目标运行平台不支持你想要的语言,那么你就不能使用它,如在嵌入式编程中选择51单片机,则不能使用Python语言。
程序员的知识。
在科学合理的原则下,我们最好选择开发人员熟悉的编程语言。如果开发人员对某一种语言比较熟悉,就可以很好地预测开发时间、开发过程等内容,避免大的未知变数,提高开发效率。
软件的可移植性要求。
如果将来开发的软件要在不同系统平台运行,就要使用可移植性好的语言,如Java、Golang等。
软件的应用领域。
各种语言都有自己的适用范围,通用设计语言并不是适用于所有领域,如嵌入式平台、IOS平台。有许多特定的领域有自己的专用语言。比如:财务分析、文本解析、科学计算、实时领域、服务器、人工智能等。使用领域的专用语言可以减少很多工作量,提高编程效率。
G.Myers给出了关于测试的一些规则,这些规则也可以看作是测试的目标或定义。
测试目标决定了测试方案的设计:
基本准则:
(1)黑盒测试(Black-box Testing)
已经知道了产品应该具有的功能,通过测试检验是否每个功能都能正常使用。
黑盒测试又称功能测试,把程序看作一个黑盒子,完全不考虑程序的内部结构和处理过程。
在程序接口进行的测试,它只检查程序功能是否能按照规格说明书的规定正常使用,程序是否能适当地接收输入数据并产生正确的输出信息,程序运行过程中能否保持外部信息的完整性。
(2)白盒测试(White-box Testing)
知道产品的内部工作过程,通过测试来检验产品内部动作是否按照规格说明书的规定正常进行。
白盒测试又称为结构测试,测试者完全知道程序的结构和处理算法。这种方法按照程序内部的逻辑测试程序,检测程序中的主要执行通路是否都能按预定要求正确工作。
黑盒测试是从用户观点的测试,白盒测试是从开发人员观点的测试。
(1)单元测试(Unit Testing)
在设计得好的软件系统中,每个模块完成一个清晰定义的子功能,而且这个子功能和同级其他模块的功能之间没有相互依赖关系。因此,有可能把每个模块作为一个单独的实体来测试,而且通常比较容易设计检验模块正确性的测试方案。
目的:保证每个模块作为一个单元能正确运行。
所发现的错误:往往是编码和详细设计的错误。
(2)子系统测试(Subsystem Testing)
把经过单元测试的模块放在一起形成一个子系统来测试。
测试过程中的主要问题:模块相互间的协调和通信。
测试重点:模块的接口。
(3)系统测试(System Testing)
把经过测试的子系统装配成一个完整的系统来测试。’
’
测试目的:
a.发现设计和编码的错误。
b.验证系统确实能提供需求说明书中指定的功能。
c.系统的动态特性符合预定要求。
子系统测试、系统测试,通常称为集成测试。
(4)验收测试(Acceptance Testing)
把软件系统作为单一的实体进行测试。
测试内容与系统测试基本类似,但它是在用户积极参与下进行的,而且可能主要使用实际数据(系统将来要处理的信息)进行测试,发现的往往是系统需求说明书中的错误。测试目的:验证系统确实能够满足用户的需要。
(5)平行运行(Parallel Operation)
同时运行新开发出来的系统和将被它取代的旧系统,以便比较新旧两个系统的处理结果。
这样做的具体目的有如下几点:
a.可以在准生产环境中运行新系统而又不冒风险;
b.用户能有一段熟悉新系统的时间;
c.可以验证用户指南和使用手册之类的文档;
d.能够以准生产模式对新系统进行全负荷测试,可以用测试结果验证性能指标。
在软件已经交付使用之后,为了改正错误或满足新的需要而修改软件的过程。
软件可维护性是:维护人员理解、改正和改进软件的难易程度。
一个软件的可维护性,主要由五个因素决定:
决定软件可维护性的最终因素是软件设计阶段所采用的方法,以及软件文档资料的好坏。提高软件的可维护性是软件工程的一个重要目标。
软件再工程(Re-engineering), 再工程不仅能从已有的程序中重新获得设计信息,而且还能使用这些信息改建或重构现有的系统。
都直接影响软件的可修改性。
决定软件可维护性的最终因素是软件设计阶段所采用的方法,以及软件文档资料的好坏。提高软件的可维护性是软件工程的一个重要目标。
软件再工程(Re-engineering), 再工程不仅能从已有的程序中重新获得设计信息,而且还能使用这些信息改建或重构现有的系统。
逆向工程(Reverse Engineering),用于软件的起始建造阶段,而Re-engineering用于软件后续的修改阶段。