软件工程
初识软件工程
- 软件是软件工程的研究对象,也是软件工程的产品形态与客观存在。
- 工程是将理论和知识应用于实践的科学,其目的是经济有效地解决实际问题。
- 软件=程序+数据+文档
- 软件具有复杂性,一致性、可变性和不可见性等固有的内在特性,这是造成软件开发困难的根本原因。
- 软件开发面临的挑战:客户不满意;项目过程失控;风险与成本问题;无力管理团队
- 1968年,北大西洋公约组织(NATO)召开国际会议,提出软件工程的概念和术语
- 软件开发阶段:瀑布模型,被划分成需求,设计,编码,测试等不同阶段。
- 软件工程是(1)将系统性的,规范性的,可定量的方法应用于软件的开发,运行和维护,即工程化应用到软件上;(2)对(1)中所述方法的研究。
- 好的软件:(1)较低的开发成本(2)按时完成开发任务并及时交付(3)实现客户要求的功能(4)具有良好性能,可靠性,可扩展性,可移植性(5)软件维护费用低
- 软件工程的Wsserman规范:抽象,软件建模方法,用户界面原型化,软件体系结构,软件过程,软件复用,度量,工具与集成环境。
- ISO9126质量模型:外部和内部质量:功能性(适合性,准确性,互操作性,安全性),可靠性(成熟性,容错性,可恢复性),易用性(易理解性,易学性,易操作性,吸引性),效率/性能(时间特性,资源利用),可维护性(易分析性,易改变性,稳定性,易测试性),可移植性(适应性,易安装性,共存性,替换性)
编写高质量代码
- 软件编码规范是与特定语言相关的描写如何编写代码的规则集合。
- 高质量的设计:模块化设计,面向抽象编程,错误与异常处理
- 模块化程序设计:降低程序设计的复杂性,提高模块的可靠性和复用性;缩短产品的开发周期
- 模块化设计的好处:思路清晰,易于测试,适应未来可能的变化
- 代码审查:是一种用来确认方案设计和代码实现的质量保证机制,它通过阅读代码来检查源代码与编程规范的符合性以及代码的质量。
- profile是Python语言内置的性能分析工具,它能够有效地描述程序运行的性能状况,提高各种统计数据帮助程序员找出程序中的性能瓶颈。
- 循环优化的基本原则:尽量减少循环过程中的计算量,在多重循环的时候,尽量将内层的计算提到上一层
- 字符串的优化:Python的字符串对象是不可改变的。字符串连接的使用尽量使用Join()而不是+.当对字符串可以使用正则表达式或者内置函数处理时,选择内置函数
- 使用列表解析和生成器表达式:列表解析要比在循环中重新构建一个新的list更为高效,因此可以利用这一特性来提高运行的效率。
单元测试
- 单元测试是对软件中的最小可测试单元进行检查和验证。
- 单元测试->模块接口->局部数据结构->边界条件->独立路径->出错处理
- 单元测试原则:快速的,独立的,可重复的,自我验证的,及时的
- 代码覆盖率:语句覆盖,判定覆盖,条件覆盖,判定条件覆盖,条件组合覆盖,路径覆盖
- 单元测试方法:静态测试和动态测试
- 黑盒测试:又称功能测试
- 白盒测试:结构测试
- 单元测试之Mock: 需要应用针对接口的编程技术,即被测试的代码通过接口来引用对象,再使用Mock对象模拟所引用的对象及其行为,因此被测试模块并不知道它所引用的究竟是真实对象还是Mock对象。
黑盒测试方法
设计良好的测试用例是关键
- 测试用例包括:测试用例值,期望结果,前缀值,后缀值
- 测试用例设计:具有代表性和典型性,寻求系统设计和功能设计的弱点,既有正确输入也有错误或异常输入,考虑用户实际的诸多使用场景。
- 等价类划分: 是将输入域划分成尽可能少的若干子域,在划分中要求每个子域两两不相交,每个子域称为一个等价类。
**有效等价类:**是对规格说明有意义,合理的输入数据构成的集合,能够检验程序是否实现了规格说明中预先规定的功能和性能
**无效等价类:**是对规格说明无意义,不合理的输入数据构成的集合,以检查程序是否具有一定的容错性。
**测试用例生成:**测试对象通常有多个输入参数,如何对这些参数等价类进行组合测试,来保证等价类的覆盖率,是测试用例设计首先需要考虑的问题。
所有有效等价类的代表值都集成到测试用例中,即覆盖有效等价类的所有组合。任何一个组合都将设计成一个有效的测试用例,也称正面测试用例
无效等价类的代表值只能和其他有效等价类的代表值进行组合。因此,每个无效等价类将产生一个额外的无效测试用例,也称负面测试用例
边界值分析是对输入或输出的边界值进行测试的一种方法,它通常作为等价类划分法的补充,这种情况下的测试用例来自等价类的边界。
- 先确定边界:通常输入或输出等价类的边界就是应该着重测试的边界情况
- 选取正好等于、刚刚大于或刚刚小于边界的值作为测试数据,而不是选取等价类中的典型值或任意值。
白盒测试
- 测试需求:测试需求是软件制品的一个特定元素,测试用例必须满足或覆盖这个特定元素。
- 覆盖标准:一个覆盖标准是一条规则,或者是将测试需求施加在一个测试集上的一组规则
- 测试覆盖
- 覆盖程度
控制流图是一个过程或程序的抽象表示。控制流图的基本符号:矩阵代表了连续的顺序计算,也称基本块,节点是语句或语句的一部分,边表示语句的控制流。
代码覆盖标准
代码覆盖率描述的是代码被测试的比例和程度,通过代码覆盖率可以得知哪些代码没有被覆盖,从而进一步补足测试用例。
- 语句覆盖:程序中的每个可执行语句至少被执行一次。
- 判定覆盖:程序中每个判断的区镇和取假分支至少经历一次,即判断真假值均被满足。
- 条件覆盖:每个判断中每个条件的可能取值至少满足一次
- **条件组合覆盖:**判断中每个条件的所有可能取值组合至少执行一次,并且每个判断本身的结果也至少执行一次。
- 路径覆盖覆盖程序中的所有可能的执行路径
如何看待测试覆盖率 - 覆盖率数据只能代表测试过哪些代码,不能代表是否测试好这些代码
- 较低的测试覆盖率能说明所做的测试还不够,但反之不成立。
- 路径覆盖>判定覆盖>语句覆盖
- 测试人员不能盲目追求代码覆盖率,而应该想办法设计更好的测试用例。
- 测试覆盖率应达到多少需要考虑软件整体的覆盖率情况以及测试成本。
基本路径测试
绘制控制流图—>计算环路复杂度—>确定基本路径—>设计测试用例
软件开发过程
- 过程是一组将输入转化为输出的相互关联或相互作用的活动
- 过程方法是系统地识别和管理组织内所使用的过程,保证更有效地获得期望的结果
- 软甲设计根据需求规格说明,确定软件体系结构,进一步设计每个系统部件的实现算法,数据结构及其接口等。
- 软件维护系统投入使用后对其进行改进,以适应不断变化的需求,完全从头开发的系统很少,将软件系统的开发和维护看成是一个连续过程更有意义
- 软件项目管理是为了使软件项目能够按照预定的成本,进度,质量顺利完成,而对成本人员、进度、质量和风险进行控制和管理的活动
- 软件配置管理是通过执行版本控制,变更控制的规程,并使用合适的配置管理软件,来保证所有产品配置项的完整性和可跟踪性。
软件过程模型
- **瀑布模型:**将基本的开发活动看成是一系列界限分明的独立阶段,这是一种计划驱动的软件过程,有利于规范软件开发活动。
- **原型化模型:**原型是一个部分开发的产品,用于加强对系统的理解,有助于明确需求和选择可行的设计策略。
- **迭代式开发:**将描述,开发和验证等不同活动交织在一起,在开发过程中建立一系列版本,将系统一部分一部分地逐步交付
- **可转换模型:**利用自动化的手段,通过一系列转换将需求规格说明转化为一个可交付使用的系统。
敏捷开发过程
敏捷开发是一种基于更紧密的团队协作,能够有效应对快速变化需求,快速交付高质量软件的迭代和增量的新型软件开发方法。
Scrum迭代开发:迭代开发将整个软件生命周期分成多个小的迭代(一般2~4周),每一次迭代就是一个小的瀑布模型,包括需求分析,设计,实现和测试等活动,结束时都要生成一个稳定和被验证过的软件版本。
团队开发过程
团队组织与管理
人力资源规划—>项目团队组建—>项目团队建设—>项目团队管理
人员选择:应用领域经验、平台经验,编程语言经验,教育背景,解决问题能力,沟通能力,适应性,工作态度,个性。
团队是由若干人构成的群体,他们具有互补的技能,对一个共同目的,绩效目标及方法做出承诺并彼此负责。
**民主式结构:**团队成员完全平等,享有充分民主
**主程序员式结构:**以主程序员为核心
矩阵式结构: 将技术与管理工作进行分离,技术负责人负责技术上的决策,管理负责人
项目沟通管理
完全可分解的任务
无法分解的任务
需沟通的可分解任务
关系错综复杂的任务
- 沟通方式
口头沟通,肢体语言,书面沟通,电子沟通
项目启动会议
项目绩效报告是收集和发布关于项目进展等绩效信息,通常使用文字说明,曲线图形和报表等形式进行描述。
软件项目计划
软件项目技术是对软件项目实施所涉及的活动,资源,任务,进度等进行规划。按时交付是软件项目的最大挑战,合理地安排进度是软件项目计划的关键内容。
顶层设计:描述了最初从系统到子系统的分解,它描述了系统的软件体系结构。
明确设计目标—>初始子系统分解—>不断分解和求精—>任务组织和分配
- 子系统分解应该是高层的,专注于功能,并且要保持稳定
- 每一个子系统可以被分配给一个团队或一个人,由他负责其定义和实现
软件项目估算
项目估算是对完成项目交付物的时间和成本进行预算和估计的过程。
专家估算:不太准确
参数估算: 功能点方法,结构化成本模型COCOMO模型,用例点估算,机器学习方法
敏捷开发与配置管理
敏捷开发之Scrum
- Sprint:
一个sprint是一个1-4周的迭代,它是一个时间盒
sprint的长度一旦确定,将保持不变
sprint的产出是“完成”的,可用的,潜在可发布的产品增量
scrum团队
自组织团队是敏捷软件开发的基本观念,即团队被授权自己管理他们的工作过程和进度,并且团队决定如何完成工作。 - 团队决定谁做什么,即任务的分配
- 团队决定如何做,如何实现目标,即团队做技术决策
- 团队需要在确保目标的前提下制定团队内的行为准则
- 团队有义务保持过程的透明性
- 团队监督和管理他们的过程和进度
产品订单
在迭代计划时,产品负责人告诉开发团队需要完成产品订单中的哪些订单项,开发团队决定在下一次迭代中他们能够承诺完成多少订单项。在迭代的过程中,没有人能够变更迭代订单,这意味着在一次迭代中需求是被冻结的。
scrum规划
发布规划:1.定义用户故事并进行优先级划分。2. 估算规模以及评估团队开发速度 3. 制定发布计划。
迭代规划:1.确定迭代目标并选择用户故事 2. 将用户故事分解和细化到任务 3. 对故事和任务进行时间估算。
用户故事与估算
用户故事是从用户角度对功能的简要描述
- 独立性: 尽可能避免故事之间存在依赖关系,否则会产生优先级和规划问题。
- 可协商:故事是可协商的,不是必须实现的书面合同或者需求
- 有价值:确保每个故事对客户或者用户有价值的,最好是让用户编写故事
- 可估算:开发者应该能够预测故事的规模,以及编码实现所需要的时间
- 短小的:故事尽量短小,最好不超过10个理想人天,至少在一个迭代中完成
- 可测试:所编写的故事必须是可测试的
敏捷估算 - 故事点:它是一个相对度量单位。使用时,可以给每个故事分配一个点值;点值本身并不重要,重要的是点值的相对大小。
- 理想时间:它是一个绝对度量单位。理想时间是某件事在剔除所有外围活动以后所需的时间;一般为一天有效工作时间的60-80%比较合理,但绝不会是全部。
估算原则: 开发团队一起估算,产品负责人和Scrum主管不参与实际估算
敏捷估算扑克
团队协作工具Tower
配置管理
软件配置管理是一种标识、组织和控制修改的技术,它作用于整个软件生命周期,其目的是使错误达到最小并最有效地提高生产率。
软件配置项是为了配置管理而作为单独实体处理的一个工作
版本是在明确定义的时间点上某个配置项的状态;版本管理是对系统不同的版本进行标识和跟踪的过程,从而保证软件技术状态的一致性。
基线是软件配置项的一个稳定版本,它是进一步开发的基础,只有通过正式的变更控制过程才能改变。
版本控制:独占工作模式,并行工作模式
**分支管理:**分支包含了一个项目的文件树及其发展的历史,记录了一个配置项的发展过程。一个配置项可能选择多个分支,归并是将对分支的修改合并到另一个分支。
配置管理工具Git
持续集成与交付
DevOps:为了按时交付软件产品,开发和运维必须紧密合作
使开发和运维一体化的一组过程、方法和工具
DevOps: 配置管理,持续集成,持续交付
- 软件配置管理的核心功能是版本控制
- 持续集成是指开发者在代码的开发过程中,可以频繁地将代码部署集成到主干,并进行自动化测试
- 持续交付:是在持续集成的环境基础上,让软件产品的产出过程在一个短周期内完成,以保证软件可以稳定、持续的保持在随时可以发布的状况。
- 持续部署:是在持续交付的基础上,把部署到生产环境的过程自动化。
华为云DevOps实践
持续规划与设计![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0dfd7844f2541e2c1f31871c2644eb81.png)
需求获取
需求工程师
目标:识别错误假设;确保一致性;提升依从性;减少彼此误解;提高支持速度和效率;提升客户满意度;撰写优质需求文档。
需求定义
“需求”是对外可见的系统特性。
- 领域性质:无论系统存在与否均存在的应用领域的性质。
- 需求:由系统的存在而使能的应用领域性质
- 规约描述:描述系统为满足需求而应具有的行为
- 需求证明的标准:运行在某台机器上的程序满足规约描述;针对给定的领域性质,规约描述满足需求
好的需求是可以度量的,能给出项目成功的必要条件
- 单个需求项的质量
(准确,正确,明确,可行,可证) - 整个需求集合的质量
(现实,精确,全面,一致)
需求分类
抽象层次详细程度:业务需求,用户需求,系统需求,软件设计规约
设计开发约束,包括:开发成本,开发周期,产品特性的变化性,可维护性,可重用性,可移植性。
功能性需求与非功能性需求间的划分并非绝对的,可能存在一定的重叠
需求工程过程
- 需求抽取:主动与干系人协同工作,找出他们的需求,识别潜在的冲突,磋商解决矛盾,定义系统范围与边界
- 需求分析:对产品及其与环境的交互进行更深入的了解,识别系统需求,设计软件体系结构,建立需求与体系结构组件间的关联,在体系结构设计实现过程中进一步识别矛盾冲突,并通过干系人之间的协调磋商解决问题。
- 需求验证:对其他需求工程活动的质量的保证。通过数学的形式化工具或工程化的测试过程来确保系统满足干系人的需求。(评审,原型化,模型验证,确认测试)
- 需求管理:贯穿从需求获取到软件系统下线的全过程。需求管理涉及软件匹配管理,需求跟踪,影响分析和版本控制
需求的主要来源
干系人分析:找出所有干系人,分析其隶属于哪个世界
- 干系人是任何和系统有关的人:资方、客户、系统用户、领域专家、项目研发团队
业务过程:对现有业务过程的分析有助于识别业务问题并加以改进
组织规章与制度
需求获取技术
(面谈,问卷调查,群体诱导技术,参与调查法,文档分析,头脑风暴,情景分析,原型化方法,建模方法,需求讨论会)
竞争性需求分析:Need(需求),Approach(方法),Benefits(收益),Competition(竞争),Delivery(推广)
撰写需求文档
需求文档的组织形式
用例建模
用例建模概念
为什么需要用例建模——描述系统的功能性需求
- 关联干系人需要以及软件需求
- 确认与系统交互的人或对象
- 定义系统的边界
- 捕捉和传达系统的理想行为
用例模型的表示:文本描述或用例图
- 一个用例 定义系统的一系列行为,通过此可为参与者提供有价值且可观测的结果。
用例
- 定义一个参与者要用到的系统功能
- 描述系统为实现参与者价值所开展的行为预测
- 对参与者与系统之间的交互活动进行建模
- 从特定的用户角度出发,是完整的,实现特定用户价值的事件流
场景是用例的实例
用例建模过程
构建用例模型的步骤
- 找到所有的参与者和用例
(识别出参与者并做简单的描述,识别出用例并做简单的介绍) - 编写用例
(给用例事件流程划分重要手段, 按照重要程度排序详细描述事件流程)
识别参与者——是谁与系统进行交互
用例的命名 - 表明参与者的目标或者作用
- 使用主动语态:用动词起始
- 设计一系列操作流程
用例建模过程中的检查项 - 用例建模时是为了表示系统的行为。通过模型可以很容易理解系统进行操作
- 应该识别出所有的用例,用来表达所有的需求。
- 系统的任何一个特性都可以找到对饮的用例
- 用例模型并不包含多余的行为‘所有的用例可以追溯系统’
用例的全部生命周期
Use case模型的建立步骤 - 找出系统外部的参与者和外部系统,确定系统的边界和范围
- 确定每一个参与者所期望的系统行为
- 把这些系统行为命名为Use Case
- 使用泛化,包含,扩展等关键处理系统行为的公共或变更部分
- 编制每个use case的脚本
- 绘制use case图
- 区分主事件流和异常情况的事件流
- 细化use case图,解决use case重复与冲突问题
用例建模精讲
- 设定系统边界
**系统边界:**一个系统所包含的所有系统成分与系统以外各种事物的分界线
建模工具介绍
系统建模工具的主要功能
可视化模型表达
- UML模型
- Web模型,
- 数据库模型
- 用户自定义模型
IBM Rational Rose/ JUDE/ Enterprise Architect
微信抢票应用案例
面向对象分析与设计
面向对象分析
- 面向对象分析技术关注应用领域中的实体,并将其建模为对象
- 面向对象分析技术主要基于分类,泛化,聚合关系在对象集合之间建立结构
- 对象的行为是执行预定的动作(服务/活动)
- 对象通过执行动作来完成状态变迁
面向对象分析方法举例
- peter Coad的面向对象方法
- 对象是问题领域中真实存在的实体,有定义清晰的边界
- 对象中封装有属性和行为
- 面向对象分析的五个核心概念:对象,属性,结构,服务和主题
一般-特殊结构
- 一般-特殊结构将类组织成基于继承关系的分类层次结构
- 自底向上是从特殊到一般的类
- 自顶向下是从一般到特殊的类
整体-部分结构
- 整体部分结构描述对象间的组合关系,例如,一个交通灯对象由0-3个灯组,支撑杆和位置对象组合而成。
服务建模
- 对象为其周遭的其他对象提供服务,例如,医生对象对外提供的服务包括:体检、出体检报告等。
面向对象的分析方法学 - 识别对象和类
- 识别类之间的关系,建立由继承和组合关系组成的类层次结构
- 定义主题,通过主题将对象模型组织成多个抽象层次或视角,一般来说通过继承关系或整体部分关系联系起来的类同属一个主题
- 识别各个对象内部的属性信息,并将其给与相应抽象层次的类
- 为每个类定义服务
CRC卡片分拣法
使用CRC卡片分拣法寻找类
classname responsibilities collaborations
通过名词过滤识别出的对象类
Coad 筛选原则:
- 保存对象信息:系统需要保存对象信息吗?
- 提供所需服务:类对象是否对外提供修改属性值的操作?
- 具有多个属性:只有一个属性的类,应该建模为属性
- 具有公共属性:类属性是否为所有实例对象共享?
- 类操作是够为所有实例对象共享?
- 外部实体:如果生产或使用对象的信息,也应考虑建模为系统类
类识别
- 从原始资料中识别类
- 从其他来源识别类
- 最好识别出尽可能多的候选类
识别类的功能职责
面向对象设计
面向对象思维方式的核心理念
(区分接口与实现,从具体到抽象,最小接口原则)
开闭原则
软件实体在扩展性方面应该是开放的,而在更改性方面应该是封闭的。
子类宽进严出
接口分离原则
在设计时采用多个和特定客户类有关的接口要比采用一个通用的接口要好。
OO设计时要注意的一些问题
- 不同类中相似方法的名字应该相同
- 遵守已有的约定俗称的习惯
- 尽量减少消息模式的数目。只要可能,就使消息具有一致的模式,以利于理解
- 设计简单的类。类的职责要明确,应该从类名就可以较容易地推断出类的用途
- 定义简单的操作,方法
- 定义简单的交互协议
- 泛化结构的深度要适当
- 把设计变动的副作用减至最小
类图建模
对象
- 对象是类的实例,两个对象可以有相同的属性取值
- 对象与其他对象之间发生关联关系
- 注意将属性划归正确的类
类属性定义
属性在类图标的属性分隔框中用文字串说明,UML规定属性的语法为:
限定关联
在关联端紧靠类图标处可以有限定符,带有限定符的关联称为限定关联。
聚合与组合关系 - 聚合用于表达一个整体对象与其成员对象之间的关系
- 组合用于表达一个整体对象与其组成部分之间的关系
继承/泛化
-
子类继承父类的属性,关联和操作
-
子类可以覆盖继承来的内容
-
父类可以声明为抽象类
-
继承/泛化关系建模的意义在于系统环境发生变化时便于添加新的子类
-
继承/泛化过程:自顶向下,和自底向上
总结建立类图的步骤
- 研究分析问题领域,确定系统的需求
- 发现对象与类,明确它们的含义和责任,确定属性和操作
- 发现类之间的关系。把类之间的关系用关联、泛化、聚集、组合、依赖等关系表达出来。
- 设计类与关系。调整和细化已得到的类和类之间的关系,解决诸如命名冲突、功能重复等问题
行为建模
顺序图概念
顺序图用来刻画系统实现某个功能的必要步骤
顺序图建模元素——对象(Object)及其生命线(Liftline)
——消息
顺序图中带条件消息的发送
- 在消息名字前加条件子句
- 使用文字说明
- 添加条件控制组
- 分成多个顺序图子图并关联
-
顺序图建模
顺序图建模过程
- 参与者:顺序图中有关的对象或者实体
- 消息:参与对象之间的通信,通过箭头表示。(顺序图的起始是一个没有发起对象的消息,每个消息代表的操作属于消息接受方)
- 轴:横轴:表明正在进行操作的对象;纵轴:时间(向下表明时间的顺延)
组合框:复杂控制结构表示
顺序图间的关联 - 当一个顺序图过大
- 需要引用其他图表时,选择下述表示:不完整的箭头和注释,通过名为“ref”的框图引用相关图表
例子
下述两个系统的控制流有什么特点
集中式和分布式
顺序图风格
顺序图与用例的关系
- 顺序图表达单个情景实例的行为
- 每个用例对应一个顺序图
- 顺序图表达对象间如何写作完成用例所描述的功能
- 顺序图用于表示为完成用例而在系统边界输入输出的数据以及消息
- 顺序图也用于表示系统内部对象间的消息传递
- 顺序图可帮助分析人员对用例图进行扩展,细化和补遗
- 顺序图可用于开发周期的不同阶段,服务于不同目的,描述不同粒度的行为
- 分析阶段的顺序图不要 包含设计对象,关注消息参数
顺序图建模意义
- 通过顺序图描述算法逻辑
- 高质量的顺序图是代码的抽象
- 顺序图是与语言无关的表示方式
- 可以绘制顺序图来描述业务逻辑
- 可以通过团队协作完成顺序图的绘制
- 可以在同一页浏览多个对象和类的行为
控制焦点的嵌套
顺序图中递归的表示:利用嵌套的FOC表示
状态建模
有限状态机
- 有限数量的状态(所有的属性取值为有限的范围)
- 模型可以表示动作序列(状态变化)
状态空间 - 对于大部分对象而言,状态空间是非常庞大的
状态空间大小是对象每个属性取值空间的乘积加1
状态的抽象表示
往往状态空间中的局部更有探究的价值 - 有一些状态是不可能出现的状态
- 整数或实数值属性往往只在一定范围内取值
状态图
- 状态图用来表示一个类的全生命周期过程
**状态:**一个对象生命期的一个阶段,该阶段中对象要满足一些特定的条件,执行特定的活动或等待某个事件的发生 - 体现为对象属性的取值
- 包含状态入口或出口行为描述
- 从不同的抽象层次分析对象,因此其状态是可嵌套的
**事件:**可以触发对象状态改变的外部刺激,也就是消息的发出与接收 - 决定状态迁移何时发生
**状态迁移:**是状态之间的关系,当发生一个事件,条件满足是就会发生从源状态到目标状态的转变。
状态相关的活动类型 - **do/activity:**只要处于这个状态,某个活动就会一直执行,直到离开这个状态
- **entry/action:**当进入某个状态时执行的动作
- **include:**调用另一个状态图,形成嵌套的状态图
迁移包括五部分: - 源状态,触发事件,警戒条件,动作,目标状态
- 对于给定的状态,最终只能产生一个迁移,因此从相同的状态出来的,事件相同的几个迁移之间的条件应该是互斥的。
UML状态图中的事件
- 变更事件:当给定条件成立时就会发生变更事件
- 调用事件:当给定对象的操作被调用执行时会发生调用事件
- 时间事件,表明时间段过去,或某个特殊时间点的触发
- 信号事件,当给定对象收到某实时信号
状态图精讲
组合状态
组合状态减少复杂度
状态图与其他UML图的关系
- 状态图中的事件为顺序图/交互图中该对象的输入消息
- 状态图应针对类图中具有重要行为的类进行建模
- 每个事件,动作对应于相应类中的一个具体操作
- 状态图中每个输出消息对应于其他类的一个操作
- 状态图中的操作定义等价于类图中的操作定义
软件系统设计
软件交互设计
交互设计概述
软件设计=编码设计+UI设计(交互设计ID)
在更加自然的交互接口上实现高效率的人机信息交互
交互设计目标
GUI设计原则
允许用户直接操作界面的目标
GUI interface elements:WIMP
**GUI设计规则:**可视化,一致性,直接映射,有效反馈
可视化:相似率,接近率,对称律,前背景分离
KLM效率模型
基线程的效率模型:KLM
rule 1:可预知的M,固定连续的动作,减去M
rule 2: 输入一个单元内的其他M
rule 3: 删除连续终止符前的M
rule 4: 系统响应之前的M
Fitts定律
减少运动距离,放大点击范围
交互设计过程
评测—
软件系统测试
软件测试概念
测试——发现问题——修复
软件测试的定义:
正向思维:验证软件正常工作
- 评价一个程序或系统的特性或能力并确定是否达到预期的结果
- 在设计规定的环境下运行软件的所有功能,直至全部通过
逆向思维:假定软件有缺陷 - 测试是为了发现错误而针对某个程序或系统的执行过程
- 寻找容易犯错地方和系统薄弱环节,试图破坏系统直至找不出问题。
软件测试的目的:
直接目标:发现软件错误
期望目标:检测系统是否满足需求
测试的局限性:
测试的不彻底性,测试只能说明错误的存在,但不能说明错误不存在
经过测试后的软件不能保证没有缺陷和错误
测试的不完备性 - 测试无法覆盖到每个应该测试的内容
- 不可能测试到软件的全部输入与响应
- 不可能测试到全部的程序分支的执行路径
测试作用的间接性 - 测试不能直接提高软件质量,软件质量的提高要依靠开发
- 测试通过早期发现缺陷并督促修正缺陷,从而提高软件质量
缺陷的集群性
软件错误有聚集性
杀虫剂悖论:不断增加新的测试用例
软件测试类型
**单元测试:**是对软件基本组成单元进行的测试,其测试对象是软件设计的最小单位
**集成测试:**是在单元测试的基础上,将所有模块按照总体设计的要求组装成为子系统或系统进行的测试。
集成测试对象是模块间的接口,其主要目的是找出在模块接口(包括系统体系结构)设计上的问题
**功能测试:**是在已知产品所应具有的功能基础上,从用户角度来进行功能测试
**性能测试:**是在实际或模拟实际的运行环境下,针对非功能特性所进行的测试,包括压力猜测是、容量测试,安全测试和可靠性
验收测试 是在软件产品完成了系统测试之后,产品发布之前进行的软件测试活动,其目的是验证软件的功能和性能是否能够满足用户所期望的要求
**黑盒测试:**将测试对象看作一个黑盒子,完全不考虑程序内部的逻辑结构和内部特性,只是依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明。
白盒测试: 把测试对象看作一个透明的盒子,允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。
**静态测试:**通过人工分析或程序正确性证明的方式来确认程序正确性
**动态测试:**通过动态分析和程序测试等方式检查程序执行状态,以确认是否有问题
**手工测试:**测试人员根据测试大纲中所描述的测试步骤和方法,手工地输入测试数据并记录测试结果。
**自动化测试:**利用测试工具
软件功能测试
功能测试是在已知产品所应具有的功能基础上,从用户角度来进行功能验证,以确认每个功能是否都能正常使用。
**内容测试:**用于检测web应用系统提供信息的正确性,准确性和相关性
表单测试主要考虑以下方面:
- 表单提交应当模拟用户提交,验证是否完成功能
- 测试提交操作的完整性,以校验提交给服务器的信息的正确性
- 验证数据的正确性和异常情况的处理能力,注意是否符合易用性要求
- 在测试表单时,会涉及到数据校验问题,如果根据给定规则需要对用户输入进行校验,需要保证这些校验功能正常工作。
数据库测试
设计语言测试
软件性能测试
软件性能是一种能非功能特性,它关注的不是软件是否能完成特定功能,而是完成功能时展示出的及时性,资源占用,稳定性,安全性,兼容性,可扩展性,可靠性等
**响应时间:**从客户端发出请求到获得响应的整个过程所经历的时间
**吞吐量:**是指单位时间内系统处理的客户请求的数量,直接体现软件系统的性能承载能力。
**资源利用率:**资源利用率是指系统资源的使用程度,例如服务器CPU利用率,内存利用率,磁盘利用率,网络带宽利用率等。
**性能测试:**是通过自动化测试工具或手段模拟多种正常,峰值以及异常负载条件对系统的各项性能指标进行的一种测试。
压力测试类型
- 稳定性压力测试,破坏性测试,渗入测试,峰谷测试
大数据量测试
疲劳强度测试 长时间运行,系统不发生状况的能力
**应用在客户端性能的测试:**测试网络带宽,延时,负载和TCP变换
应用在服务器性能的测试
软件交付与维护
软件部署与交付
项目实施是将软件系统部署到客户方的计算机系统上,协助客户准备基础数据,使软件系统顺序上线运行。
- 保证软件符合需求,质量过关
- 制定实施计划
- 准备好程序代码和相关文档
项目验收
软件部署是软件生命周期中的一个重要环节,属于软件开发的后期活动,即通过配置,安装和激活等活动来保障软件制品的后续运行
**基本目的:**支持软件运行,满足用户需求,使得软件系统能够被直接使用。 - 保障软件系统的正常运行和功能实现
- 简化部署的操作过程,提高执行效率
- 同时还必须满足软件用户在功能和各功能属性方面的个性化需求
**集中式服务器应用部署:**适用于用户访问量小,硬件环境要求不高
**集群式服务器应用部署:**适用于并发用户访问量大
**持续交付:**以自动化或半自动化方式,将构建版本从一个环境提送到更接近实际使用的交付准备环境中。
软件演化与维护
软件变化是不可避免的
- 软件在使用过程中,新的需求不断出现
- 商业环境在不断地变化
- 软件中的缺陷需要进行修复
- 计算机硬件和软件环境的升级需要更新现有的系统
- 软件的性能和可靠性需要进一步改进
软件维护:是软件被投入运行使用后人们对软件产品所进行的修改,变更通常是修改现有的组件或增加新的组件,一般不涉及体系结构的重大变化 - 改正性维护:修改软件缺陷或不足
- 适应性维护:修改软件使其适应不同操作环境,主要包括硬件变换,操作系统变化或者其他支持软件变化等
- 完善性维护“”:增加或修改系统功能,使其适应业务的变化
影响维护成本的因素: - 团队稳定性
- 合同责任
- 人员技术水平
软件再工程 - 重新构造