系统设计
处理流程设计
- 流程表示工具
- 程序流程图(Program Flow Diagram,PFD)用一些图框表示各种操作,它独立于任何一种程序设计语言,比较直观、清晰,易于学习掌握。任何复杂的程序流程图都应该由顺序、选择和循环组合或嵌套而成。
-
- IPO图也是流程描述工具,用来描述构成软件系统的每个模块的输入、输出和数据加工。
-
- N-S图容易表示嵌套和层次关系,并具有强烈的结构化特征。但是当问题很复杂时,N-S图可能很大,因此不适合于复杂程序的设计。
-
- 问题分析图(PAD)是一种支持结构化程序设计的图形工具。PAD具有清晰的逻辑结果、标准化的图形等优点,更重要的是,它引导设计人员使用结构化程序设计方法,从而提高程序的质量。
- 业务流程重组BPR
BPR是对企业的业务流程进行根本性的再思考和彻底性的再设计,从而获得可以用诸如成本、质量、服务和速度等方面的业绩来衡量的显著性的成就。BPR设计原则、系统规划和步骤如下图所示:
- 业务流程管理BPM
BPM是一种以规范化的构造端到端的卓越业务流程为中心,以持续的提高组织业务绩效为目的的系统化方法。
BPM和BPR管理思想最根本的不同就在于流程管理并不要求对所有流程进行再造。构造卓越的业务流程并不是流程再造,而是根据现有流程的具体情况,对流程进行规范化的设计
流程管理包含三个层次:规范流程、优化流程和再造流程。
系统设计
- 系统设计主要目的:为系统制定蓝图,在各种技术和实施方法种权衡利弊,精心设计,合理地使用各种资源,最终勾画出新系统的详细设计方法。
- 系统设计方法:结构化设计方法,面向对象设计方法。
- 系统设计的主要内容:概要设计、详细设计。
- 概要设计基本任务:又称为系统总体结构设计,是将系统的功能需求分配给软件模块,确定每个模块的功能和调用关系,形成软件的模块结构图,即系统结构图。
- 详细设计的基本任务:模块内详细算法设计、模块内数据结构设计、数据库的物理设计、其他设计(代码、输入/输出格式、用户界面)编写详细设计说明书、评审。
- 系统设计基本原则
- 抽象化
- 自顶向下,逐步求精
- 信息屏蔽
- 模块独立(高内聚、低耦合)。
- 系统设计原则
- 保持模块的大小适中
- 尽可能减少调用的深度
- 多扇入,少扇出
- 单入口,单出口
- 模块的作用域应该在模块之内
- 功能应该是可预测的
- 系统设计基本原理:抽象、模块化、信息隐蔽、模块独立。
衡量模块独立程度的标准有两个:耦合性和内聚性。
-
- 内聚程度从低到高如下表所示:
|------|-----------------------------------------------------|---------------|
| 内聚分类 | 定义 | 记忆关键字 |
| 偶然内聚 | 一个模块内的各处理元素之间没有任何联系。 | 无直接关系。 |
| 逻辑内聚 | 模块内执行若干个逻辑上相似的功能,通过参数确定该模块完成哪一个功能 | 逻辑相似、参数决定 |
| 时间内聚 | 把需要同时执行的动作组合在一起形成的模块 | 同时执行 |
| 过程内聚 | 一个模块完成多个任务,这些任务必须按指定的过程执行 | 指定的过程顺序 |
| 通信内聚 | 模块内的所有处理元素都在同一个数据结构上操作,或者各处理使用相同的输入数据或者产生相同的输出数据 | 相同数据结构、相同输入输出 |
| 顺序内聚 | 一个模块中各个处理元素都密切相关于同一功能且必须顺序执行,前一个功能元素的输出就是下一个功能元素的输入 | 顺序执行、输入为输出 |
| 功能内聚 | 最强的内聚,模块内的所有元素共同作用完成一个功能,缺一不可 | 共同作用、缺一不可 |
-
- 耦合程度从低到高如下表所示:
|-------|----------------------------------------------------|---------------|
| 耦合分类 | 定义 | 记忆关键字 |
| 无直接耦合 | 两个模块之间没有直接的关系,它们分别从属于不同模块的控制与调用,不传递任何信息 | 无直接关系 |
| 数据耦合 | 两个模块之间有调用关系,传递的是简单的数据值,相当于高级语言中的值传递 | 传递数据值调用 |
| 标记耦合 | 两个模块之间传递的是数据结构 | 传递数据结构 |
| 控制耦合 | 一个模块调用另一个模块时,传递的是控制变量,被调用模块通过该控制变量的值有选择的执行模块内的某一功能 | 控制变量、选择执行某一功能 |
| 外部耦合 | 模块间通过软件之外的环境联合(如I/O将模块耦合到特定的设备、格式、通信协议上)时 | 软件外部环境 |
| 公共耦合 | 通过一个公共数据环境相互作用的那些模块间的耦合 | 公共数据结构 |
| 内容耦合 | 当一个模块直接使用另一个模块的内部数据,或通过非正常入口转入另一个模块内部时 | 模块内部关联 |
人机界面设计
- 人机界面设计三大黄金原则
测试基础知识
测试原则和方法
-
系统测试是为了发现错误而执行程序的过程,成功的测试是发现了至今尚未发现的错误的测试。
-
测试原则
- 应尽早并不断的进行测试;
- 测试工作应该避免由原开发软件的人或小组承担;
- 在设计测试方案时,不仅要确定输入数据,而且要根据系统功能确定预期的输出结果;
- 既包含有效、合理的测试用例,也包含不合理、失效的用例;
- 检验程序是否做了该做的事,且是否做了不该做的事;
- 严格按照测试计划进行;
- 妥善保存测试计划和测试用例;
- 测试用例可以重复使用或追加测试。
-
软件测试方法可分为静态测试和动态测试
- 静态测试:指被测程序不在机器上运行,而采用人工检测和计算机辅助静态分析的手段对程序进行检测,包括对文档的静态测试和对代码的静态测试。对文档的静态测试主要以检查单的形式惊醒,而对代码的静态测试,包括桌前检查、代码审计、代码走查的方式。使用这种方法能够有效地发现30%-70%的逻辑设计和编码错误。
- 动态测试:指在计算机上实际运行程序进行软件测试,一般采用白盒测试和黑盒测试方法。
- 黑盒测试法:功能性测试。不了解软件代码结构,根据功能设计用例,测试软件功能。
- 白盒测试法:结构性测试,明确代码流程,根据代码逻辑设计用例,进行用例覆盖。
测试阶段
- 单元测试:也称为模块测试,测试的对象是可独立编译或汇编的程序模块、软件构建或面向对象软件中的类(统称为模块),测试依据是软件详细设计说明书。
- 集成测试:目的是检查模块之间,以及模块和已集成的软件之间的接口关系,并验证已集成的软件是否符合设计要求。测试依据是软件概要设计文档。
- 确认测试:主要用于验证软件的功能、性能和其他特性是否与用户需求一致。根据用户的参与程度,通常包括以下类型:
- 内部确认测试:主要由软件开发组织内部按照SRS进行测试。
- Alpha测试:用户在开发环境下进行测试。
- Beta测试:用户在实际使用环境下进行测试,通过该测试后,产品才能交付用户。
- 验收测试:针对SRS,在交付前以用户为主进行测试,其测试对象为完整的、集成的计算机系统。验收测试的目的是,在真实的用户工作环境下,检验软件系统是否满足开发技术合同或SRS。验收测试的结论是用户确定是否接收该软件的主要依据。除应满足一般测试的准入条件外,在进行验收测试之前,应确认被测软件系统已通过系统测试。
- 系统测试:测试对象是完整的、集成的计算机系统;测试的目的是在真实系统工作环境下,验证完成的软件配置项能否和系统正确连接,并满足系统/子系统设计文档和软件开发合同规定的要求。测试依据是用户需求或开发合同。主要内容包括功能测试、健壮性测试、性能测试、用户界面测试、安全性测试、安装和反安装测试等,其中,最重要的工作是进行功能测试与性能测试。功能测试主要采用黑盒测试方法;性能测试主要指标有响应时间、吞吐量、并发用户数和资源利用率等。
- 配置项测试:测试对象是软件配置项,测试目的是检验软件配置项与SRS的一致性。测试的依据是SRS。在此之间,应确认被测软件配置项已通过单元测试和集成测试。
- 回归测试:测试目的是测试软件变更之后,变更部分,变更部分的正确性和变更需求的符合性,以及软件原有的、正确的功能、性能和其他规定的要求的不损害性。
测试用例的设计
- 黑盒测试用例:将程序看做一个黑盒子,只知道输入输出,不知道内部代码,由此设计出测试用例,分为下面积累:
- 等价类划分:把所有数据按照某种特性进行归类,而后在每类的数据里选取一个即可。等价类测试用例的设计原则:设计一个新的测试用例,使其尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为之;设计一个新的测试用例,使其仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖位为之。
- 边界值划分:将每类的边界值作为测试用例,边界值一般为范围的两端值以及在此范围之外的与此范围间隔最小的两个值,如年龄范围为0-150,边界值为0,150,-1,151四个。
- 错误推测:没有固定的方法,凭经验而言,来推测有可能产生问题的地方,作为测试用例进行测试。
- 因果图,由一个结果来反推原因的方法,具体结果具体分析,没有固定方法。
- 白盒测试用例:知道程序的代码逻辑,按照程序的代码语句,来设计覆盖代码分支的测试用例,覆盖级别从低至高分为下面几种:
- 语句覆盖SC:逻辑代码中的所有语句都要被执行一遍,覆盖层级最低,因为执行了所有的语句,不代表执行了所有的条件判断。
- 判定覆盖DC:逻辑代码中的所有判断语句的条件的真假分支都要覆盖一次。
-
- 条件覆盖GC:针对每一个判断条件内的每一个独立条件都要执行一遍真和假。
- 条件判定组合覆盖CDC:同时满足判定覆盖和条件覆盖。
-
- 路径覆盖:逻辑代码中的所有可行路径覆盖了,覆盖层级最高。
调试
- 测试是发现错误,调试是找出错误的代码和原因。
- 调试需要确定错误的准确位置;确定问题的原因并设法改正;改正后要进行回归测试。
- 调试的方法有:蛮力法、回溯法(从出错的地方开始,向回找)、原因排除法(找出所有可能的原因,逐一进行排除,具体包括演绎法、归纳法、二分法)。
软件度量
- 软件的两种属性:外部属性指面向管理者和用户的属性,可直接测量,一般为性能指标。内部属性指软件产品本身的属性,如可靠性等,只能间接测量。
- McCabe:又称为环路复杂度,假设有向图中有向边数为m,节点数为n,则此有向图的环路复杂度为m-n+2.
注意m和n代表的含义不能混淆,可以用一个最简单的环路来做特殊值记忆此公式,另外,针对一个程序流程图,每一个分支边(连线)就是一条有向边,每一条语句(语句框)就是一个顶点。
系统运行与维护
系统转换
- 遗留系统是指任何基本上不能进行修改和演化以满足新的变化了的业务需求的信息系统,它通常具有以下特点:
- 系统虽然完成企业中许多重要的业务管理工作,但仍然不能完全满足要求。一般实现业务处理电子化及部分企业管理功能,很少涉及经营决策。
- 系统在性能上已经落后,采用的技术已经过时。例如,多采用主机/终端形式或小型机系统,软件使用汇编语言或第三代程序设计语言的早期开发,使用文件系统而不是数据库。
- 通常是大型的软件系统,已经融入企业的业务运作和决策管理机制之中,维护工作十分困难。
- 没有使用现代信息系统建设方法进行管理和开发,现在基本上已经没有文档,很难理解。
- 系统转换是指新系统开发完毕,投入运行,取代现有系统的过程,需要考虑多方面的问题,以实现与老系统的交接,有以下三种转换计划:
- 直接转换:现有系统被新系统直接取代了,风险很大,适用于新系统不复杂,或者现有系统已经不能使用的情况。有点事节省成本。
- 并行转换:新系统和老系统并行工作一段时间,新系统经过试运行后再取代,若新系统在试运行过程中有新问题,也不影响现有系统的运行,风险极小,在试运行过程中还可以比较新系统的性能,适用于大型系统。缺点是耗费人力和时间资源,难以控制两个系统间的数据转换。
- 分段转换:分期分批逐步转换,是直接和并行转换的集合,将大型系统分为多个子系统,依次试运行每个子系统,成熟一个子系统,就转换一个子系统,同样适用于大型项目,只是更耗时,而且现有系统和新系统间混合使用,需要协调好接口等问题。
- 数据转换与迁移:将数据从旧数据库迁移到新数据库中。有三种方法:系统切换前通过工具迁移、系统切换前采用手工录入、系统切换后通过新系统生成。
系统维护
- 系统的可维护性可以定义为维护人员理解、改正、改动和改进这个软件的难易程度,其评价指标如下:
- 易分析性。软件产品诊断软件中的缺陷或失效原因或识别待修改部分的能力。
- 易改变性。软件产品使指定的修改可以被实现的能力,实现包括编码、设计和文档的更改。
- 稳定性。软件产品避免由于软件修改而造成意外结果的能力。
- 易测试性。软件产品使已修改软件能被确认的能力。
- 维护性的依从性。软件产品遵循与维护性相关的标准或约定的能力。
- 系统维护包括硬件维护、软件维护和数据维护,其中软件维护类型如下:
- 正确性维护:发现了bug而进行的修改。
- 适应性维护:由于外部环境发生了改变,被动进行的对软件的修改和升级。
- 完善性维护:基于用户主动对软件提出更多的需求,修改软件,增加更多的功能,使其比之前的软件功能、性能更高,更加完善。
- 预防性维护:对未来可能发生的bug进行预防性的修改。
净室软件工程
- 净室软件工程是一种应用数学与统计学理论以经济的方式生产高质量软件的工程技术,力图通过严格的工程化的软件过程达到开发中的零缺陷或接近零缺陷。净室方式不是先制作一个产品,再去消除缺陷,而是要求在规约和设计中消除错误,然后以"净"的方式制作,可以降低软件开发中的风险,以合理的成本开发出高质量的软件。
- 在净室软件工程背后的哲学是:通过在第1次正确地书写代码增量,并在测试前验证它们的正确性,来避免对成本很高的错误消除过程的依赖。它的过程模型是代码增量积聚到系统的过程的同时,进行代码增量的统计质量验证。它甚至提倡开发者不需要进行单元测试,而是进行正确性验证和统计质量控制。
- 净室软件工程(CSE)的理论基础主要是函数理论和抽样理论。
- 净室软件工程应用技术手段:
- 统计过程控制下的增量式开发。
- 基于函数的规范与设计。
- 正确性验证。CSE的核心
- 统计测试和软件认证。
- 净室软件工程在使用过程的一些缺点:
- CSE太理论化,需要更多的数学知识。其正确性验证的步骤比较困难且比较耗时。
- CSE开发小组不进行传统的模块测试,这是不现实的。
- CSE也会带有传统软件工程的一些弊端。
基于构件的软件工程
- 基于构件的软件工程(CBSE)是一种基于分布对象技术、强调通过可复用构件设计与构造软件系统的软件复用途径。CBSE体现了"购买而不是重新构造"的哲学,将软件开发的重点从程序编写转移到了基于已有构件的组装。用于CBSE的构件应该具备以下特征:
- 可组装型:对于可组装的构件,所有外部交互必须通过公开定义的接口进行。同时它还必须对自身信息的外部访问。
- 可部署性:软件必须是自包含的,必须能作为一个独立实体在提供其构件模型实现的构件平台上运行。构件总是二进制形式,无需在部署前编译。
- 文档化:构件必须是完全文档化的,用户根据文档来判断构件是否满足需求。
- 独立性:构件应该是独立的,应该可以在无其他特殊构件的情况下进行组装和部署,如确实需要其他构件提供服务,则应显示声明。
- 标准化:构件标准化意味着在CBSE过程中使用的构件必须符合某种标准化的构件模型。构件模型定义了构件实现、文档化以及开发的标准,其包含的模型要素为:
- 接口。构件通过构件的接口来定义,构件模型规定应如何定义构件接口以及在接口定义中应该包含的要素,如操作名、参数以及异常等。
- 使用信息。为使构件远程分布和访问,必须给构件一个特定的、全局唯一的名字或句柄。构件元数据是构件本身相关的数据,比如构件的接口和属性信息。
- 部署。构件模型包括一个规格说明,指出应该如何打包构件使其部署称为一个独立的可执行实体。部署信息中包含有关包中内容的信息和它的二进制构成的信息。
- 构件模型提供了一组被构件使用的通信服务,这种服务包括以下两种。
- 平台服务,允许构件在分布式环境下通信和互操作。
- 支持服务,这是很多构件需要的共性服务。例如,构件都需要的身份认证服务。
中间件实现共性的构建服务,并提供这些服务的接口。
- CBSE过程是支持基于构件组装的软件开发过程,过程中的6个主要活动:系统需求概览、识别候选构件、根据发现的构件修改需求、体系结构设计、构件定制与适配、组装构件创建系统。
- CBSE过程与传统软件开发过程的不同点:
- CBSE早期需要完整的需求,以便尽可能多地识别出可复用的构件。
- 在过程早期阶段根据可利用的构件来细化和修改需求。如果可利用的构件不能满足用户需求,就应该考虑由复用构件支持的相关需求。
- 在系统体系结构设计完成后,会有一个进一步的对构件搜索及设计精化的活动。可能需要为某些构件寻找备用构件,或者修改构件以适合功能和架构的要求。
- 开发就是将已经找到的构件集成在一起的组装过程。
- 构件组装是指构件相互直接集成或是用专门编写的"胶水代码"将它们整合在一起来创造一个系统或另一个构件的过程。常见的组装构件有以下3种组装方式。
- 顺序组装。通过按顺序调用已经存在的构件,可以用两个已经存在的构件来创造一个新的构件。如上一个构件输出作为下一个构件的输入。
- 层次组装。这种情况发生在一个构件直接调用自另一个构件所提供的服务时。被调用的构件为调用的构件提供所需的服务。二者之间接口匹配兼容。
- 叠加组装。这种情况发生在两个或两个以上构件放在一起来创建一个新构件的时候。这个新构件合并了原构件的功能,从而对外提供了新的结构。外部应用可以通过新接口来调用原有构件的接口,而原有构件不相互依赖,也不相互调用。这种组装类型适合于构件时程序单元或者构件是服务的的情况。
- 组装构件的三种不兼容问题(通过编写适配器解决):
- 参数不兼容。接口每一侧的操作有相同的名字,但参数类型或参数个数不相同。
- 操作不兼容。提供接口和请求接口的操作名不同。
- 操作不完备。一个构件的提供接口是另一个构件请求的一个子集,或者相反。