软件工程总结(下)

本文深入探讨了软件设计的各个环节,包括目标设定、过程概述、模块内聚与耦合、面向对象设计原则,以及结构化设计和测试方法。涵盖了白盒与黑盒测试、设计模式和系统功能结构图。还介绍了软件测试的目标、原则和常见测试类型,以及软件维护和项目管理的关键内容。
摘要由CSDN通过智能技术生成

六、软件设计

1、目标

  • 根据软件需求分析的结果,设想并设计软件,即根据“目标系统”的逻辑模型确定“目标系统”的物理模型,概括地描述系统如何实现用户所提出来的功能和性能等方面的需求
  • 软件设计是软件开发的基础和依据,是软件工程过程中的技术核心。
  • 软件设计的最终目标是要取得最佳方案(Best Solution,主观)。
    • “最佳”是指在所有候选方案中,就节省开发费用,降低资源消耗,缩短开发时间的条件,选择具有较高的生产率、较高的可靠性和可维护性的方案。

2、软件设计过程

软件设计是一个把软件需求变换成包含软件功能模型、数据模型以及行为模型的过程,分为概要设计和详细设计。

  • 系统结构设计:定义了软件系统各主要元素(主要指功能模块)之间的关系,其中包括软件的模块接口设计;
  • 数据设计:将软件各模块所需要处理的数据以及系统需要长久保存的数据进行数据结构和数据存储的设计;
  • 过程设计:主要是确定各功能模块内部结构的详细定义,包括模块主要算法逻辑和局部数据结构的定义。

概要设计

概要设计:只需描绘出可直接反映功能、数据、行为需求的软件总体框架。

动态结构设计
  • 用例实现过程设计,针对用例对应的 SSD 中的每个系统事件,运用 UML 的顺序图 / 协作图给出符合该系统事件定义的操作契约的内容;
  • 如果软件对象具有多种不同的职责(主要考虑对应于不同的用例)的情况下,需要运用状态图对该软件对象进行状态迁移的设计。
静态结构设计
  • 对所有用例或者子系统级别的用例的交互图进行归纳,运用 UML 的类图给出系统的静态结构。

详细设计

详细设计:即过程设计,通过对软件结构进行细化,得到各功能模块的详细数据结构和算法,使得功能模块在细节上非常接近于源程序的软件设计模型。

3、软件设计模型

由两个部分构成:

  • 动态结构设计:以某种方式表示功能响应客户请求时处理数据的过程或条件,用于进一步解释软件结构中各功能之间是如何协调工作的机制。

  • 静态结构设计:由软件的功能结构和数据结构组成,展示软件系统能够满足所有需求的框架结构。

4、模块内聚性

信息隐藏:每个模块的实现细节对于其他模块来说是隐藏的。就是说,模块中所包含的信息(包括数据和过程)不允许其他不需要这些信息的模块使用。

内聚是模块功能强度的度量,一个模块内部各元素之间的联系越紧密,则它的内聚性就越高,相对地,它与其他模块之间的耦合性就会减低,而模块独立性就越强。

  • 巧合内聚
  • 逻辑内聚
  • 时间内聚(经典内聚)
  • 过程内聚
  • 通信内聚
  • 信息内聚
  • 功能内聚
image-20210622153718606

5、模块耦合性

耦合性:是模块之间的相对独立性(互相连接的紧密程度)的度量。

  • 内容耦合
  • 公共耦合
  • 外部耦合
  • 控制耦合
  • 标记耦合
  • 数据耦合
  • 非直接耦合
image-20210622201011173

降低耦合性的方法:

  1. 模块间多传递数据信息,尽量减少和避免传送控制信息。
  2. 降低模块接口的复杂性。
  3. 减少接口信息传送数量。
  4. 以系统调用方式(或 call 方式)代替直接引用。
  5. 传送信息的结构尽量简单(或以数据耦合代替标记耦合)。
  6. 把模块的通信信息放在缓冲区中。

6、面向对象的设计原则

单一职责(Single Responsibility)

定义:针对类,应该只有一个引起它变化的原因,“职责”定义为变化的原因

  • 如果有其他原因去改变一个类,那么这个类就具有其他的职责。类具有多个职责,等于这些职责具有耦合关系。
  • 为了提高类的内聚度,应将对象的不同职责分离至两个或多个类中,确保引起该类变化的原因只有一个。

image-20210618214537027

image-20210618214643826

开闭原则(Open Closed)

软件实体(类、模块、函数)可以扩展,但不能修改。

  • 对于扩展是开放的(Open 4 extension),需求改变时,对实体进行扩展。
  • 对于更改是封闭的(Closed 4 modification),需求改变时,禁止对原来的代码进行修改。
  • 实现 OCP 的关键是使用抽象,识别不同类之间的共性和变化点,利用封装对变化点进行处理

image-20210618215845113

image-20210618215850273

里氏替换原则(Liskov Substitution)

子类应当可以替换父类并出现在父类能够出现的任何地方

image-20210618214731211

依赖倒置原则(Dependency Inversion)

高层模块不应依赖于低层模块,二者都应依赖于抽象;抽象不应依赖于实现细节,细节应该依赖于抽象

  • 程序中所有的依赖关系应该终止于抽象类或者接口
  • 每个较高层次都为它所需要的服务声明一个抽象接口,较低的层次实现了这些抽象接口,每个高层类都通过该抽象接口使用下一层的服务

image-20210618214945621

image-20210618214940611

接口隔离原则(Interface Segregation)

采用多个与特定客户类的接口 比 采用一个通用的涵盖多个业务方法的接口要好

  • 如果一个服务器类为多个客户类提供不同的服务,则服务器类应该为每一个客户类创建特定的业务接口,而不要为所有客户类提供统一的业务接口,除非这些客户类请求的服务相同

image-20210618215155114

组合/聚合复用(Composite/Aggregation Reuse)

在一个新对象里面使用一些已有对象,使之成为新对象的一部分;新对象通过向已有对象委托(delegate)一部分责任而达到复用已有对象的目的。

image-20210618220202839

image-20210618220220050

迪米特法则(Law of Demeter)

  • 最少知识原则:一个对象应当可能少的了解其它对象。
  • 只与你直接的朋友们通信,不要跟“陌生人”说话。
  • 符合以下特征的属于朋友:
    • 当前对象本身(this);
    • 以参量形式传入到当前对象方法中的对象;
    • 当前对象的实例变量直接引用的对象;
    • 当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友;
    • 当前对象所创建的对象。

7、软件设计基础

  • 自顶向下,逐步细化
  • 系统控制结构
  • 结构划分和结构图
  • 数据结构
  • 软件过程

七、面向对象设计

1、综述

image-20210620075354155

关键步骤

  • 确定系统的软件基础架构;
  • 发现对象(发现软件类):根据需求和选择的架构和模式确定系统由哪些对象构成;
  • 确定对象属性:明确该对象应该具有的特征属性;
  • 确定对象行为:明确对象应具有的功能和职责;
  • 确定对象之间的关系:根据系统顺序图及操作契约以及选择的架构和模式明确系统是如何相互协作完成功能需求的交互过程。

2、软件的层次化结构

  1. 用户界面层:(用例)系统功能的各种界面表现形式。
  2. 控制器层:用于协调、控制其他类共同完成用例规定的功能或行为。
  3. 业务逻辑层:实现用例要求的各种系统级功能。
  4. 持久化层:用于保存需要持久化存储的数据对象。
  5. 系统层:为应用提供操作系统相关的功能,通过把特定于操作系统的特性包装起来,使软件与操作系统分离,增加应用的可移植性。

image-20210619195211725

模块层次化好处:增加软件的健壮性,易于扩展和维护;增加软件的可移植性。

3、类职责分配(Grasp)模式

设计类的来源有两部分:

  • 核心逻辑由领域模型中的概念类转换而来

  • 另一部分则是为实现而新增的一些类,如负责对象持久化的类、负责通信的类。

核心思想:每一个设计类都有明确的职责

  • 自己干自己的事:
    • 对象要了解自己私有的封装数据;
    • 了解相关联的对象;
    • 了解能够派生或者计算的事物。
  • 自己干自己能干的事:
    • 对象自身要能执行一些行为,如创建一个对象或者进行计算;
    • 对象要能启动其他对象中的动作;
    • 对象要能控制或协调其他对象中的活动。
  • 自己只干自己的事(职责的内聚)

面向对象的设计模式

  • 对象的职责通过调用对象的方法来实现。将职责分配给一个对象还是多个对象,是分配给一个方法还是多个方法要受到职责粒度的影响。
  • 面向对象设计最关键的活动是正确地给对象分配职责。
  • 模式是面向对象软件的设计经验,是可重用的设计思想,它描述了在特定环境中反复出现的一类设计问题,并提供经过实践检验的解决这类问题的通用模式。
  • 模式定义了一组相互协作的类,包括类的职责和类之间的交互方式。

控制器(Controller)模式

问题来源:第一个接收系统事件的软件对象是什么?哪个软件对象负责接收和处理一个系统输入事件?

解决方案:把接收和处理系统事件的职责分配给位于控制器层的对象

  • 它代表整个系统(系统简单且不复杂),称为外观(facade)控制器

  • 它代表一个发生系统事件的用例场景,这个类通常命名为 “<用例名>控制器”,称为用例控制器或者会话控制器

  • 在相同的用例场景中使用同一个控制器类处理所有的系统事件;

  • 一次会话是与一个参与者进行交谈的一个实例。

指导原则
  • 当一个系统不具有“太多”的系统事件,或者用户接口不可能将事件消息重定向到其他控制器时,选择外观控制器是合适的。这时,外观控制器相当于一个应用的封面,隔离了用户接口和应用逻辑。
  • 如果外观控制器由于职责过多而变得“臃肿”的时候,应该选择用例控制器。
    • 如果选择了用例控制器,那么每一个用例都有一个不同的控制类,而且只有一个,以便维护用例的状态。用例控制器可以实现有一定执行顺序的系统操作。
  • 不论是外观控制器还是用例控制器,它们只是接收系统事件消息,并没有实现系统操作的职责,系统操作应该委托给领域对象处理

创建者(Creator)模式

问题来源:哪个对象应该负责产生类的实例?(操作契约中对象实例的创建

如果符合下面的一个或者多个条件,则可将创建类A实例的职责分配给类B(B创建A)。

  • B聚合(aggregate)或包含(contain)对象A;

  • B记录(record)对象A;

  • B密切使用对象A;

  • B拥有创建对象A所需要的初始化数据(B是创建对象A的信息专家)。

创建者模式体现了低耦合的设计思想,是对迪米特法则的具体运用。

信息专家(Information Expert)模式

给对象分配职责的通用原则:将职责分配给拥有履行职责所必需信息的类,即信息专家。换言之,对象具有处理自己拥有信息的职责或能力。

根据信息专家模式,应该找到拥有履行职责所必须的信息的类,选取类的方法:

  • 如果在设计模型中存在相关的类,先到设计模型中查看;

  • 如果在设计模型中不存在相关的类,则到领域模型中查看,试着应用或扩展领域模型,得出相应的设计类。

职责的实现(即功能)需要信息,而信息往往分布在不同的对象中,一个任务可能需要多个对象(信息专家)协作来完成。

八、结构化软件设计

1、系统功能结构图

基本结构

四种模块

  • 传入模块 :从下属模块取得数据,经过某些处理,再将其传送给上级模块。

  • 传出模块 :从上级模块获得数据,进行某些处理,再将其传送给下属模块。

  • 变换模块 :即加工模块。它从上级模块取得数据,进行处理,转换成其它形式,再传送回上级模块。

  • 协调模块 :对所有下属模块进行协调和管理的模块。

image-20210618222245456

变换型结构

变换型数据处理问题的工作过程大致分为三步:

  • 取得数据

  • 变换数据

  • 给出数据

image-20210619101006167

image-20210619101027088

事务型结构

存在某一个数据流处理节点,引发一个或多个相同的处理,并将处理结果返回给该节点,则该数据流就叫做事务,该节点称为事务z处理中心(核心工作是调度)。内部结构一致就是事务,否则就是变换。

image-20210619101209501

事务是最小的工作单元,不论成功与否都作为一个整体进行工作。

image-20210619101322029

变换-事务混合型结构

在具体的应用中一般以变换型为主,事务型为辅的方式进行软件结构设计

image-20210619102411107

image-20210619102546185

确定系统边界

中心变换:多股数据流汇集的地方往往是系统的中心变换部分(还需要根据上下文确定该加工是否表示功能需求)。

逻辑输入:可以从数据流图上的物理输入开始,一步一步向系统中间移动,一直到数据流不再被看作是系统的输入为止,则其前一个数据流就是系统的逻辑输入。

  • 可以认为逻辑输入就是离物理输入端最远的,且仍被看作是系统输入的数据流。

逻辑输出:从物理输出端开始,一步一步地向系统中间移动,就可以找到离物理输出端最远,且仍被看作是系统输出的数据流。

2、变换映射

由流图推导出的系统初始结构图如下

image-20210619101729050

3、事务映射

对于下图,以 I 为中心或以 O 为中心,都是事务型结构。

image-20210619102024050

image-20210619102044811

4、详细设计

从软件开发的工程化观点来看,在编制程序以前,需要对所采用算法的逻辑关系进行分析,设计出全部必要的过程细节,并给予清晰的表达,使之成为编码的依据,这就是详细设计的任务。

程序流程图

为使用流程图描述结构化程序,必须限制流程图只能使用下面给出的五种基本控制结构:

image-20210619103138167

N-S图

也叫盒图

image-20210619103406305

PAD图

  • Problem Analysis Diagram
  • 设置了五种基本控制结构的图式,并允许递归使用。

image-20210619103526442

判定表

  • 当算法中包含多重嵌套的条件选择时,用程序流程图、N-S 图或 PAD 都不易清楚地描述。然而,判定表却能清晰地表达复杂的条件组合与应做动作之间的对应关系。
  • 判定表要求不能存在多分支判断,必须是两分支的判断

image-20210619103723944

image-20210619103842668

“T”表示该条件取值为真,“F”表示该条件取值为假,空白表示这个条件无论取何值对动作的选择不产生影响。

“Y”表示要做这个动作,空白表示不做这个动作。

九、软件测试

定义:以最少的时间和人力,系统地找出软件中潜在的各种错误和缺陷,并证明软件的功能和性能与需求说明相符合

1、软件测试的目的和原则

目的

从用户的角度:通过软件测试暴露软件中的错误和缺陷,以考虑是否可接受该软件产品。

从软件开发者的角度:希望测试成为表明软件产品中不存在错误,验证该软件已正确地实现了用户的要求,确立人们对软件质量的信心。

原则

  • 应当把“尽早地和不断地进行软件测试”作为软件开发者的座右铭。

  • 测试用例应由测试输入数据和对应的预期输出结果这两部分组成。

  • 程序员应避免检查自己的程序。

  • 在设计测试用例时,应当包括合理的输入条件和不合理的输入条件。

  • 充分注意测试中的群集现象:经验表明,测试后程序中残存的错误数目与该程序中已发现的错误数目成正比。

  • 严格执行测试计划,排除测试随意性。应当对每一个测试结果做全面检查。

  • 妥善保存测试计划,测试用例,出错统计和最终分析报告,为维护提供方便。

软件测试对象

软件开发各阶段所得到的文档,包括需求规格说明、概要设计规格说明、详细设计规格说明以及源程序,都应成为软件测试的对象。

流程

image-20210619105132345

软件配置:软件需求规格说明、软件设计规格说明、源代码等;

测试配置:测试计划、测试用例、测试程序等;

测试工具:测试数据自动生成程序、静态分析程序、动态分析程序、测试结果分析程序、以及驱动测试的测试数据库等等;

测试结果分析:比较实测结果与预期结果,评价错误是否发生以及错误的级别和严重性。

排错(调试):对已经发现的错误进行错误定位和确定出错性质,并改正错误,同时修改相关的文档。

修正后的文档再测试:直到通过测试为止;

利用可靠性分析,评价软件质量:

  • 软件的质量和可靠性达到可接受的程度

  • 是否所做的测试不足以发现严重的错误

如果测试发现不了错误,只能说明测试配置考虑得不够细致充分,错误仍然潜伏在软件中。

软件测试与各阶段关系

image-20210619105108501

image-20210619105114834

2、测试方法

白盒测试

将测试对象看做一个透明的盒子,允许利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致,又称为结构测试或逻辑驱动测试。

白盒测试主要应用于单元测试,是检查程序逻辑错误的主要方法。

逻辑覆盖
  • 语句覆盖:使得每一个可执行语句至少执行一次。

  • 判定覆盖:使得程序中每个判断的取真分支和取假分支至少经历一次,又称为分支覆盖。

  • 条件覆盖:使得程序中每个判断的每个条件的可能取值至少执行一次。

  • 判定-条件覆盖:使得判断中每个条件的所有可能取值至少执行一次,同时每个判断的所有可能判断结果取值至少执行一次。

  • 条件组合覆盖:使得每个判断的所有可能的条件取值组合至少执行一次。

  • 路径覆盖:设计足够的测试用例,覆盖程序中所有可能的路径。

程序控制流图

控制流图是对程序流程图进行简化后得到的一种图示方式,可以更加突出地表示程序控制流的结构。一个典型的控制流图结构如下图:

image-20210619212715914

控制流图包含三种元素:

  • 结点:圆圈表示单条或多条语句
  • 边:带箭头的线条,表示控制流的方向
  • 区域:边和结点圈定的范围

控制流图中 5 种典型的控制流符号如下图:

image-20210619212936467

使用基本路径测试方法设计测试用例的步骤如下:

  1. 根据程序代码或程序流程图导出程序的控制流图。

image-20210619213123470

  1. 计算控制流图的环路复杂度 V(G)

    三种计算环路复杂度的方法:

    • 第一种:等于控制流图中的区域数,包括封闭区域和开放区域;
    • 第二种:设 E 为控制流图的边数,N 为图的结点数,则定义环路复杂性为 V(G)=E-N+2;
    • 第三种:若设 P 为控制流图中的判定结点数,则有 V(G)=P+1。
  2. 确定基本路径集。

  3. 以每条基本路径为依据设计测试用例。

举例

image-20210619213747003

黑盒测试

这种方法完全不考虑程序内部的逻辑结构和内部特性,只依据程序的需求规格说明书和概要设计说明,检查程序的功能是否符合它的功能说明,又称为功能测试或数据驱动测试。

有以下三种常用方法:

等价类划分

黑盒测试方法不能选用穷举方式,为此通过寻找具有代表意义的数据进行替代其它同类型的数据,称为等价类。

并合理地假定:测试某等价类的代表值就等价于对这一类其它值的测试。

  • 划分等价类
    • 有效等价类:是指对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合。
    • 无效等价类:是指对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。
  • 选取测试用例
    • 为每一个等价类规定一个唯一编号;
    • 设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;
    • 设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止。

划分方式

  1. 按区间划分 [x, y]
  2. 数值集合
  3. 布尔值
  4. 数值划分
  5. 限制条件 / 规则
  6. 确定测试用例,每个唯一编号
举例

image-20210619142907597

image-20210619142922539

image-20210619142933337

边界值分析

使用边界值分析方法设计测试用例,首先应确定边界情况。应当选取正好等于,刚刚大于,或刚刚小于边界的值做为测试数据,而不是选取等价类中的典型值或任意值做为测试数据。

因果图

目的是减少测试用例的数目

  • 分析(需求)软件规格说明描述中,哪些是原因(输入或状态),哪些是结果(输出或动作),并给每个原因和结果赋予一个唯一的标识符。

  • 分析(需求)软件规格说明中的语义,找出原因与原因之间,原因与结果之间的关系,根据这些关系,画出因果图。

  • 由于语法或环境限制,有些原因与原因之间,原因与结果之间的组合情况不可能出现。为表明这些特殊情况,在因果图上用一些记号标明约束或限制条件。

  • 把因果图转换成判定表,并根据因果图中的制约关系对判定表进行化简,去掉不可能存在的组合情况。

  • 简化后的判定表中的每一列就是一种有效的条件组合,对应一个测试用例

通常在因果图中用 Ci 表示原因,用 Ei 表示结果,各结点表示状态。

  • “0” 表示某状态不出现
  • “1” 表示某状态出现

image-20210619143737473

image-20210619143745056

举例

image-20210619144040346

image-20210619144107261

image-20210619144205427

转换判定表:

image-20210619144227516

3、软件测试基本类型

单元测试:编码阶段运用白盒测试方法,对已实现的最小单位代码进行正确性检查;

集成测试:编码阶段在单元测试的基础上,运用黑盒测试方法检查被测单元的接口问题,并检查代码集成后各功能的完整性;

确认测试:开发后期,针对系统级的软件验证所实现的功能和性能是否与用户的要求一致;

系统测试:在开发环境或实际运行环境中,以系统需求分析规格说明书作为验收标准,对软硬件系统进行的一系列集成和确认测试;

验收测试:在实际运行环境中,试运行一段时间后所进行的测试活动,确认系统功能和性能符合生产要求。验收通过后交付给用户使用。

十、剩余章节

1、软件维护

定义

在软件已经交付使用之后,为了改正错误或满足新的需要而修改软件的过程,即在软件运行-维护阶段对软件产品所进行的一切改动。

分类

改正性维护:改正在系统运行过程中发现的一些潜在程序错误或设计缺陷

适应性维护:为了适应在软件使用过程中数据环境发生变化或处理环境发生变化而进行的软件修改

完善性维护:为满足用户的其他要求,就需要修改软件并把这些要求纳入到软件之中,称为完善性维护

预防性维护:为了提高软件的可维护性、可靠性等而事先进行的软件改动

软件维护的活动

建立维护机构,给出软件维护的工作管理流程,为每一个维护申请规定标准的处理步骤

image-20210619145411947

修改请求 --> 分类与鉴别 --> 分析 --> 设计 --> 实现 --> 系统测试 --> 验收测试 --> 交付

2、软件项目管理

定义

项目:是一项为了创造某一唯一的产品或服务的时限性工作。具有以下特征:

  • 需要由人来完成;
  • 受到有限资源的限制;
  • 需要计划、执行和控制。

软件项目:是一种成果体现为软件产品的项目。其特有的特征表现为:

  • 软件产品是无形的;
  • 软件产品没有标准的软件过程 ;
  • 大型软件项目开发常常是 “一次性的”。

项目管理过程

项目管理就是为了满足甚至超越项目干系人员对项目的需求和期望的一些活动,并将理论知识、技能、工具和技巧应用到项目的活动中。

包含以下九个知识领域:

  1. 综合管理:将项目管理各种必要要素综合为整体的过程和活动,并在项目管理过程组范围内识别、定义、组合、统一并协调。

  2. 范围管理:界定为了确保成功地完成项目所需要做的工作,也是仅仅被要求做的工作。

  3. 时间管理:阐述确保项目按时完成所需的各项过程。

  4. 成本管理:阐述了确保项目按照规定预算完成需要进行的费用规划、估算、预算的各项过程。

  5. 质量管理:阐述了确保项目达到其既定质量要求所需实施的各项过程。

  6. 人力资源管理:阐述了组织和管理项目团队的各个过程。

  7. 沟通管理:阐述了为确保项目信息及时而恰当地提取、收集、传输、存储和最终处置而需要实施的一系列过程。

  8. 风险管理:阐述了与项目风险管理有关的过程。

  9. 采购管理:阐述了采购或取得产品、服务或成果,以及合同管理所需的各过程。

软件项目管理过程如下:

启动软件项目 --> 制定项目计划 --> 项目计划的执行 --> 项目的控制 --> 项目结束

上半部分传送门:
https://blog.csdn.net/qq_43791817/article/details/116189749

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值