[toc]
第一章 从程序到软件
1 何为程序及程序的质量要求
(1)何为程序
- 程序(Program)是由程序设计语言所描述的、能为计算机所理解和处理的一组语句序列
- 程序严格遵循程序设计语言的各项语法和语义规定
- 程序代码可表现为二种形式
- 源代码(Source Code):用程序设计语言所描述的代码
- 可执行代码(Executable Code):可执行的二进制或中间码
(2) 程序组成
- 语句:声明、定义、控制、计算等;实现特定的功能;
- 模块:包,类,方法;每个模块实现特定功能
(3)程序的二类利益相关者
- 用户:
- 程序的运行展示 功能和性能
- 满足和实现用户的需求
- 程序员
- 编写,阅读维护程序
- 发现和修改程序中的缺陷
- 用户和程序员对程序有这不同的质量需求
(4)程序质量的内在和外在体现
- 外在(External)质量
- 用户视点
- 对外可展示,用户可直接感触到、所关心的
- 使用流畅性、响应速度、界面美观、操作简易性、运行可靠性等
- 内在(Internal)质量
- 程序员视点
- 体现在程序的内在方面,程序员可以感触到的、所关心的
- 易于理解、结构清晰、易于修改、可重用好等
2 程序质量保证方法
- 程序质量保证方法
- 遵循编码风格
- 采用程序设计方法
- 开展代码重用
- 进行结对编程
(1)程序质量的语法和语义体现
- 代码风格规范-语法
- 语法和结构层次
- 明确如何来规范程序的书写
- 表现为是否易于阅读和理解
- 代码设计规范-语义
- 语义和内涵层次,外在的
- 明确如何来组织和封装程序语句
- 表现为良好的结构和易于重用
(2)遵循编码风格
- 良好的编程行为:对代码符号进行良好的组织、合理的命名、提供必要的注释,那么将可增强代码的可读性和可理解性,进而提高代码的可维护性和可重用性,提升代码的内部质量
- 编码风格:程序员在编码时要遵循特定的样式及要求,以规范程序员的编程行为以及所产生程序代码的样式
- 编写代码的基本原则
- 易懂,一看就懂
- 简明,降低复杂度
- 易改,便于维护
- 无二义,不产生歧义
- 代码风格举例:
- 代码布局:缩进,大括号换行
- 代码组织:按字母顺序说明对象,单入口单出口
- 命名规范:一看就懂,望文生义;小驼峰,大驼峰
- 代码注释:有效、必要、简洁的注释;注解位置
(3)采用程序设计方法
- 语句设计
- 单入口单出口,少用goto语句
- 加强对异常处理
- 将更多的时间和精力放在处理异常代码上
- 模块化设计
- 模块是逻辑上相对独立、具有良定义接口的编程单位
- 模块可表现为函数、过程、方法、类、程序包等
- 高内聚低耦合原则
- 高内聚:模块内各要素紧密相关,仅实现单一功能,否则再进行拆分
- 低耦合:模块间的关系应设计的非常松散
(4)代码重用
定义:在编写代码过程中,充分利用已有和现成的代码,并将其集成到程序之中,从而来实现程序功能
好处:由于被重用的代码经过多次反复的使用,代码质量得到充分检验,因而代码重用不仅可极大提高编程效率,而且还可有效提高程序质量
- 重用代码片段
- 重用函数、类和软构件
- 重用开源代码
(5)结对编程
3 程序质量的分析方法
- 人工审查方法
- 自动化分析方法
- 程序测试方法
(1)程序代码中潜在的质量问题
- 质量问题
- 编写不合理 – 没有遵循编码规范
- 设计不合理 – 没有遵循设计规范
- 代码有错误 – 代码编写的不正确
(2)人工审查代码(Code Review)
- 方法描述:阅读和理解代码;发现缺陷和问题;提出改进的建议
- 方法特点:人工审查效率低;难以发现一些深层次问题;难以全面地进行系统分析
- 审查方面:
- 代码是否符合编程规范
- 代码中是否存在缺陷
- 从质量的角度哪些代码需要改进
(3)自动化工具审查-代码静态分析
-
由计算机软件来自动完成代码审查
- 无需运行被测代码,仅通过分析或检查程序的语法、结构、过程、接口等来检查程序
- 30% - 70% 的代码缺陷可通过静态分析发现
-
分析什么
- 找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌套语句,错误的递归,非法计算,可能出现的空指针引用等等
- 程序遵循编码规范的程度
-
特点:快速定位、有效发现隐藏的错误和缺陷
-
自动化代码分析工具:SonarQube
- 基于Web、用于管理程序代码质量的代码分析工具
- www.sonarqube.org
- 能以插件的形式集成到众多的软件开发环境(如Eclipse)
(4)软件测试技术
- 程序本质上是对数据的处理
- 设计数据(测试用例) -> 运行测试用例(程序来处理数据) -> 判断运行结果(是否符合预期结果)
4 何为软件及软件的特点
(1)何为软件
- 软件是指在计算机系统的支持下,能够完成特定功能与性能的程序、数据和文档
- 文档:记录软件开发活动和阶段性成果、软件配置及变更的阐述性资料
- 定义和理解软件
- 记录软件开发成果
- 辅助不同人员间的交流
- 数据:程序的加工处理对象和结果
- 数据形式:用户,订单,交易,日志
- 数据处理:表示,获取,存储,检索,分析
- 文档:记录软件开发活动和阶段性成果、软件配置及变更的阐述性资料
(2)软件概念给我们的启示
- 软件
程序 - 软件涉及更多制品
- 这些制品间有关联、相互依赖
- 开发软件
编写程序 - 软件开发需要做更多事情
- 对软件提出更高的要求
- 软件的规模和复杂性意味着要采用行之有效的方法—工程方法
(3)软件生命周期
- a 需求分析
- b 软件设计
- c 编码实现
- d 软件测试
- e 部署运行
- f 使用维护
- 转a
(4)软件特点
- 逻辑性:逻辑产品,逻辑思维(非物理活动)的结果、不会磨损和老化
- 设计开发:是设计开发而成的,不是生产制造而成的,而是一系列以设计为核心的软件开发活动
- 易变性:需求经常变、难以把控,影响软件的制品即开发过程;产品难以成熟
- 复杂性:规模大;运行复杂;环境复杂;
- 缺陷的隐蔽性:缺陷隐藏在逻辑代码中,不像硬件系统那样直观显现,很难被人们所发现和排除
5 软件的分类
(1)软件的分类
-
应用软件
- 面向特定应用领域的专用软件。它们针对相关行业和领域的特定问题,为其提供基于计算的新颖解决方案。
- 示例:淘宝、12306、携程、微信、QQ等软件
-
系统软件
- 对计算机资源进行管理,为应用软件的运行提供基础设施和服务的一类软件。从计算服务的视角,系统软件介于计算机硬件和应用软件之间。
- 示例:操作系统、数据库管理系统、编译软件、软件中间件等
-
支撑软件
- 辅助软件开发和运维,帮助开发人员完成软件开发和维护工作的一类软件
- 示例:SonarQube、Visual Studio、Eclipse等
-
通用软件产品
- 由软件开发组织开发的,在市场上公开销售,可以独立使用的软件.
- 关于产品应该做什么的规格说明由开发者确定,相关的变更决策也由开发者做出.
-
定制化软件产品
- 受特定客户委托,由软件开发商针对特定客户需求专门设计和实现的软件.
- 关于产品应该做什么的规格说明由客户给出,相关的变更需求也由客户提出.
(2)闭源软件
- 何为闭源软件
- 软件代码不对用户开放的一类软件,购买软件时只提供可运行软件或服务,没有提供源代码
- 以许可证(License)的方式授权用户使用软件
- 闭源软件带来的问题
- 无法掌握软件内部实现情况(如是否存在安全漏洞和恶意代码),也无法对软件进行修改和完善,极大影响了开发者的创新自由
- 示例
- 微软的Windows、Office软件,
- 典型企业:微软、IBM、Oracle等
(3)开源软件
- 何为开源软件
- 一种源代码可以自由获取和传播的计算机软件,其拥有者通过开源许可证赋予被许可人对软件进行使用、修改和传播
- 开源软件的好处
- 源代码可自由传播
- 激发创作者的热情
- 免费使用降低成本
- 示例:开源软件
- Linux, Ubuntu
- Apache, Jboss, Tomcat
(4)开源软件托管平台
- Github:全球最有影响力的开源软件托管平台
- SourceForge:一个有影响力的开源软件开发平台和仓库,为开源软件提供存储、协作和发布的支持
- Gitee:中国的开源软件托管平台
- Stack Overflow:全球最大的软件开发知识分享平台,它支持开发者交流和讨论软件开发问题、分享软件开发经验和知识,进而促进相关开发问题的解决,推动开源软件的开发
(5)开源软件的优势
-
采购和开发的成本更低
- 开源软件通常是免费的,即使要付费,其费用也非常低廉
-
软件质量更高、更安全
- 核心代码都在公众的视野之中,代码问题(如缺陷、安全漏洞等)很容易被人发现
-
软件研制和交付的更快
- 基于开源软件的项目开发可以更为快速地给用户交付软件产品
-
软件功能更为强大
- 大量的软件开发者不仅参与软件开发,贡献他们的代码,而且还参与软件的创新,提出和构思软件需求,不断完善软件功能
-
开源软件许可证
- 何为开源许可证
- 声明获得开源代码后拥有的权利,界定对别人的开源作品进行何种操作、何种操作是被禁止的,规范开源软件的使用要求和约束
- 开发者虽然可自由地获取开源软件的源代码,但在如何使用开源软件方面还需要遵循相关的开源软件协议
- 二类许可证
- 宽松式开源许可证:三方面特点:代码使用没有任何限制;用户自担代码质量的风险;用户使用开源软件时须披露原始作者
- Copyleft式开源许可证:更多限制,带有许多条件和要求,比如分发二进制代码时须提供源代码,修改后的开源软件须与之前保持一致的许可证等
- 何为开源许可证
(6)开源软件的利用
- 学习开源软件
- 不仅反映了核心开发者的软件技术和功能创意,而且还蕴含了高水平的软件开发技能,如架构设计、编码风格、模块封装等
- 重用开源代码
- 开源软件构成了支撑软件开发的可重用软件资源库,可实现更大粒度的软件重用
- 参与开源建设,掌握开源技术,理解开源文化
- 包括反馈软件缺陷、提出软件需求、讨论问题的解决、贡献程序代码等等
- 重用和集成开源软件来快速搭建高质量的系统
6 软件质量
- 软件质量是指软件满足给定需求的程度,它是产品生命线
- 正确性(Correctness):软件满足规格说明和用户要求的程度,即在预定环境下能正确地完成预期功能和非功能需求的程度。
- 可靠性(Reliability):在规定条件下、限定时间范围内,软件系统完成预期功能、不引起系统故障的能力。
- 健壮性(Robustness):在计算环境发生故障、输入无效数据或操作错误等意外情况下,软件仍能做出适当响应的程度。
- 有效性(Efficiency):软件利用计算资源和存储资源以实现其功能的能力
- 安全性:包括系统安全(Safety)和信息安全(Security),系统安全是指软件能及时有效地避免给人员、设施、环境、经济等造成损害,信息安全是指软件能有效防控各类的非法获取、传播和使用
- 可维护性(Maintainability):是否易于对其进行修改以更正错误、增强功能、适应新运行环境
- 可移植性(Portability):把软件从一种运行环境转移到另一种运行环境下运行的难易程度
- 可重用性(Reusability):软件模块、构件、设计方案等在其他软件开发中被再次使用程度
- 可理解性(Comprehensibility):软件开发者或用户理解该软件系统的容易程度
- 可信性(Dependability):采取有效措施确认软件满足人们的要求和期望
- 持续性(Sustainability):面对各种突发异常事件,仍能提供令人满意的服务的能力
- 可用性(Usability):使用和操作软件系统难以程度
- 互操作性(Interoperability):软件系统与其他的系统进行交换信息、协同工作的能力
第二章 软件工程概述
1 软件工程产生背景
(1)软件危机的出现
- 进度经常延迟
- 质量无法保证
- 成本超出预算
- 软件维护困难
- 失败风险很大
(2)如何来解决软件危机?
- 软件危机根源
- 对软件这样一类复杂和特殊系统的认识不清:软件是新生事物,对其特点、规律性和复杂性认识不够
- 没有找到支持软件系统开发的有效方法:基础理论、关键技术、开发过程、支撑工具等
- 缺乏成功软件开发实践以及相应的开发经验:系统总结、认真分析、充分借鉴、吸取教训
- 软件开发迫切需要理论和方法指导,软件工程应运而生
2 软件工程基本内涵
(1)何为软件工程
-
将系统的、规范的、可量化的方法应用于软件的开发、运行和维护的过程;以及上述方法的研究
- 系统化:提供完整和全面的解决方法,包括目标、原则、过程模型、开发活动、开发方法和技术等
- 规范化:支持各类软件系统的开发,包括语言标准、质量标准、编程标准、方法标准、能力极其改进标准等
- 可量化:工作量、成本、进度、质量等要素可以量化,基于定量的数据支持开发和管理,确保科学性和可行性
-
软件工程对软件开发的新认识
- 软件是产品(Product):面向用户,存在质量、成本、利润等特征
- 软件开发是一项工程(Project):存在约束,需要质量保证,进行组织管理,…
- 要按工程化方法来组织软件生产
- 分阶段分步骤来实施
- 按计划开展开发活动
- 进行各种形式质量保证
- 采用行之有效的方法
- 借助各种工具的支持…
(2)软件工程三要素
- 过程
- 从管理的视角,回答软件开发、运行和维护需要开展哪些工作、按照什么样的步骤和次序来开展工作
- 对软件开发过程所涉及的人、制品、质量、成本、计划等进行有效和可量化的管理
- 典型成果
- 过程模型,如瀑布模型、增量模型、原型模型、迭代模型、螺旋模型等等
- 方法,如敏捷开发方法、群体化开发方法、DevOps方法
- 管理,如配置管理、质量管理、团队组织等
- 方法学(Methodology)
- 从技术的视角,回答软件开发、运行和维护如何做的问题
- 为软件开发过程中的各项开发和维护活动提供系统性、规范性的技术支持
- 如何理解和认识软件模型是什么
- 如何用不同抽象层次的模型来描述软件制品
- 采用什么样的建模语言来描述软件模型等等
- 典型成果
- 结构化软件开发方法学
- 面向对象软件开发方法学
- 基于构件的软件开发方法学
- 工具
- 从工具辅助的视角,主要回答如何借助工具来辅助软件开发、运行和维护的问题
- 帮助软件开发人员更为高效地运用软件开发方法学来完成软件开发过程中的各项工作,提高软件开发效率和质量,加快软件交付进度。
- 如需求分析、软件设计、编码实现、软件测试、部署运行、软件维护、项目管理、质量保证等,简化软件开发任务,
- 典型成果:SonarQube、Eclipse等
(3)计算机辅助软件工程
- 什么是计算机辅助软件工程(Computer-Aided Software Engineering, CASE)
- 在软件工程活动中,开发人员按照软件工程的方法和原则,借助于计算机及其软件的帮助来开发、维护和管理软件产品的过程
- CASE工具:支持CASE的软件工具,如编辑器、编译器等
- CASE环境:
- 将CASE工具按统一标准和接口组装起来,使工具间、人员间、各个过程间能方便交互的集成环境
- 如Visual Studio将编辑、编译、调试、界面设计、安装程序生成等等集成在一起
- 代码编写,项目管理,软件建模,软件测试,软件运维
(4)软件开发的本质
- 软件开发 = 软件创作 + 软件生产
- 软件创作:基于软件开发者的经验和技能,借助于智慧,进行自由创新,如软件设计、编码实现等
- 软件生产:基于工程化的手段,遵循约束和规范,开展软件生产,如遵循过程、按照标准、质量保证等
(5)软件工程的目标
在成本、进度等约束下,指导软件开发和运维,开发出满足用户要求的足够好软件
(6)软件工程原则
- 抽象与建模
- 抽象:将与相关开发活动所关注的要素提取出来,不关心的要素扔掉,形成与该开发活动相关的软件要素
- 建模:基于特定的抽象,借助于建模语言(如数据流图、UML等),建立起基于这些抽象的软件模型,进而促进对软件系统的准确理解
- 模块化
- 将软件系统的功能分解和实现为若干个模块,每个模块具有独立的功能,模块之间通过接口进行调用和访问。
- 软件重用
- 在软件开发过程中尽可能利用已有的软件资源和资产(如函数库、类库、构件库、开源软件、代码片段等)来实现软件系统
- 努力开发出可被再次重用的软件资源(如函数、类、构件等)
- 有助于提高软件开发效率,降低软件开发成本,满足开发工程约束,得到高质量的软件产品
- 信息隐藏
- 模块内部信息(如内部的语句、变量等)对外不可见或不可访问,模块间仅仅交换那些为完成系统功能所必需交换的信息(如接口)
- 模块设计时只对外提供可见的接口,不提供内部实现细节。信息隐藏原则可提升模块的独立性,减少错误向外传播,支持模块的并行开发
- 关注点分离
- 分而治之
- 双向追踪原则
- 当某个软件制品发生变化时,一方面要追踪这种变化会对那些软件制品产生影响,进而指导相关的开发和维护工作,此为正向追踪;另一方面要追踪产生这种变化的来源,或者说是什么因素导致了该软件制品的变化,明确软件制品发生变化的原因及其合理性,此为反向追踪。
- 工具辅助
第三章 软件工程和开发方法
1 何为软件过程模型
(1)软件过程
- 过程(Process)
- 活动:明确要做哪些事情,包括具体的活动
- 关系:活动间存在逻辑关系,如依赖和先后次序
- 软件过程:
- 按照项目进度、成本和质量要求,遵循用户需求,开发和维护软件、管理软件项目的一系列有序软件开发活动
- 软件开发活动:技术活动和管理活动
(2)软件过程模型
- 定义了软件开发的具体活动以及活动间的逻辑关系
- 描述包括:
- 过程中的活动以及这些活动的顺序
- 产品交付物:软件过程活动的产出物;
- 角色:反映了参与过程的人在其中的职责;
- 前置条件和后置条件:在一个过程活动执行之前和之后,或者产品生产之前和之后必须满足的条件。
- 工具
- 资源
2 有哪些软件过程模型
- 瀑布模型
- 增量模型
- 迭代模型
- 原型模型
- 螺旋模型
- 基于构件的过程模型
- UP模型
(1)瀑布模型
- 步骤
- 需求分析
- 活动
- 任务:定义软件需求,包括功能、非功能需求
- 层次和视角:用户角度,仅描述问题和需求
- 方法
- 依据:用户的期望和要求
- 不断与用户进行交流和商讨,抽象、问题分解、多视点等技术
- 产出:软件需求模型;软件需求文档;软件确认测试计划;
- 概要设计
- 活动
- 任务:建立软件总体架构、制定集成测试计划
- 层次和视角:宏观、全局、整体、战略性
- 方法
- 依据:软件需求文档
- 自顶向下, 逐步求精, 抽象, 模块化, 局部化,信息隐藏
- 产出:软件概要设计模型、软件概要设计文档、软件集成测试计划
- 详细设计
- 活动
- 任务:设计模块内部细节(算法、数据结构),制订单元测试计划
- 层次和视角:微观、局部、细节性
- 方法
- 依据:概要设计文档、软件需求文档
- 高质量的软件设计原则,如单入口单出口
- 产出:软件详细设计模型、软件详细设计文档、单元测试计划
- 编码实现
- 活动
- 任务:编写程序代码并进行单元测试和调试
- 层次和视角:最终的实现代码
- 方法
- 依据:软件概要和详细设计文档、单元测试计划
- 采用某种程序设计语言(如C、C++、Java)
- 产出:经过单元测试的源程序代码
- 集成测试
- 活动
- 任务:组装软件模块并进行测试以发现问题
- 层次和视角:系统结构、接口
- 方法
- 依据:软件概要设计文档、软件集成测试计划
- 软件集成测试工具
- 产出:经过集成测试、修复缺陷的源程序代码,集成测试报告
- 确认测试
- 活动
- 任务:测试软件是否满足用户需求
- 层次和视角:从用户角度,聚焦需求是否得以正确实现
- 方法
- 依据:软件确认测试计划、软件需求文档
- 软件测试支撑工具
- 产出:经过确认测试、修复缺陷后的代码,软件确认测试报告
- 特点:
- 与软件生命周期相互一致
- 每个活动结束后需要评审
- 相邻活动间存在因果关系
- 优点:简单,一目了然,易理解、掌握、应用和管理
- 缺点:违背现实
- 适用于需求易于定义、不易变动的软件系统
- 改进的瀑布模型:带反馈和回溯
(2)增量模型
- 优点:渐进快速交付,并行开发,提高效率
- 不足:
- 要求一开始完整确定需求,建立系统架构的要求更高
- 管理复杂,增量开发,要保持多个版本的制品一致性
- 产品是慢慢成熟的,跟办事规程不匹配
(3)迭代模型(Iterative Model)
- 优点:
- 每次迭代是一完整过程
- 体现了小步快跑的开发理念,降低风险
- 适合需求难导出、不甚明确且持续变动的软件
- 不足
- 迭代多少次不确定
- 管理较为复杂
- 高素质管理者和团队
(4)原型模型(Prototype Model)
- 软件原型:用户界面+执行流程
- 特点
- 软件原型作为交流载体和媒介
- 支持用户参与到软件开发中
- 持续、渐进地导出用户要求
- 适合于需求难导出、模糊且不易确定的软件
(5)螺旋模型(Spiral Model)
- 优点:
- 集成迭代模型和原型模型
- 引入风险分析,风险驱动
- 适合于需求不明确、开发风险高、开发过程中需求变更大的内部软件项目
- 不足:风险驱动、管理复杂
(6)不同软件过程模型的特点
3 如何来选择软件过程模型
(1)软件过程模型的选择
-
考虑软件项目的特点
-
软件开发团队的水平
-
分析软件过程模型特点
-
互联网应用软件的开发过程模型
- 特点:软件需求不确定且快速变化
- 如:12306 APP软件,微信软件,淘宝软件
- 选用瀑布模型不合适,迭代模型较为合适
-
装备软件的开发过程模型
- 特点:软件需求确定且较为稳定
- 如:飞行控制软件
- 可考虑选用瀑布模型,用迭代模型不是很合适
(2)传统软件过程模型的特点和不足
- 软件开发和运维的大量工作用于撰写软件文档,而非去编写程序代码
- 软件开发过程中会花费大量时间和精力用于软件文档的评审,以确保软件质量
- 一旦软件需求发生变化,开发人员需要修改软件需求文档,并据此来调整其他的一系列文档,最后再修改程序代码
- 等较长时间才能得到可运行软件系统
- 以文档为中心的重型软件开发方法,非常笨重
4 软件开发方法概述
- Parnas方法
- 结构化方法
- 面向对象方法
- 给予构件的开发方法
- 敏捷开发方法
- 群体化开发方法
(1)Parnas方法
- 出发点:可靠性,可维护性
- 策略
- 信息隐蔽:在设计时仅列出将来可能发生变化的因素,并在模块划分时将这些因素局部化
- 意外故障处理:软件的非连续性,小错误会引发严重的事故,所以必须加强防范
- 特点:Parnas对软件开发提出了深刻的见解,但没有明确的流程,不能独立使用
(2)结构化方法
- 出发点:清晰的程序结构,可理解性。
- 求解复杂问题的一般办法:分而治之(模块化)
- 策略:模块化,自顶向下、逐步求精;SA+SD+SP(系统分析(System Analysis),系统设计(System Design),软件编程(Software Programming))
- 程序=数据+算法,分为:
- 面向数据流的结构化方法
- 面向数据结构的结构化方法
- 特点:
- 数据和行为分开——鸿沟
- 难开发、难理解、不安全、可维护性低
(3)面向对象的方法
- 出发点:对问题领域的实体特征直接自然模拟,更易于理解和开发,结构更稳定。
- 程序=对象+消息
- 策略:
- 通过一组对象的交互来完成系统的功能,对象是领域实体的软件抽象
- OOA+OOD+OOP 面向对象分析(Object-Oriented Analysis)、面向对象设计(Object-Oriented Design)和面向对象编程(Object-Oriented Programming)
- 自顶向下和自底向上相结合
- 特点:
- 对象把数据和操作封装在一起
- 更稳定、更安全、提高了可维护性和可重用性
(4)基于构件的开发方法
- 出发点:提高软件开发效率和质量的基本途径是复用,用大块编程取代,程序=构件+连接件
- 策略:
- 有目的地开发可复用的构件(develop for reuse)
- 管理已有的构件 (management for reuse)
- 复用已有的构件开发新软件(development by reuse)
- 特点:
- 降低开发和维护成本
- 提升开发效率和质量
(5)敏捷开发方法
-
定义:一种轻量级软件开发方法(相对于重量级的软件开发方法而言)
-
主张软件开发要以代码为中心,快速、轻巧和主动应对需求变化,持续、及时交付可运行的软件系统
-
敏捷开发方法的基本观点
- 较之于过程和工具,应更加重视人和交互的价值
- 较之于面面俱到文档,应更加重视可运行软件系统的价值
- 较之于合同谈判,应更加重视客户合作的价值
- 较之于遵循计划,应更加重视响应用户需求变化的价值
-
敏捷方法体现的思想
- 强化可运行的软件,弱化文档:以可运行软件为中心来开展软件开发
- 以适应变化为目的来推进开发:针对变化不断进行优化和调整任务、产品和计划等
- 以人为本:敏捷软件开发是面向人的而不是面向过程的,让方法、技术、工具、过程等来适应人,而不是让人来适应它们
-
敏捷开发方法是一大类方法的统称,它们遵循敏捷思想
-
支持敏捷软件开发的技术
- 极限编程
- 测试驱动开发
- 在开发程序代码之前,先确定和编写测试
- 程序员首先要思考如何对某个功能进行测试,设计好相应的测试用例,编写好相关的测试代码,然后编写相应的程序代码以通过软件测试
- Scrum方法:旨在通过增量或迭代的方式加强软件项目的管理
- 首先,产品拥有者需创建软件产品订单库即“Backblog”
- 描述软件产品需提供的功能需求以及它们的优先级排序
- 其次,筛选出最应该实现的软件需求,
- Scrum主人基于“Backblog”中各项软件需求及其优先级,形成待实现的软件产品冲刺订单库,即“SprintLog”
- 然后,软件开发将进入冲刺“Sprint”周期
- 以实现选定软件订单,每个冲刺就是一次增量开发,一般持续1到4周
- 最后,共同开展Scrum评审
- 一次冲刺完成后,每个团队成员演示自己的开发成果,大家共同审查成果是否高质量地实现了既定功能,并就其中的问题进行反思,以指导和改进下一次冲刺
- 首先,产品拥有者需创建软件产品订单库即“Backblog”
(6)群体化软件开发方法
-
依托互联网平台来吸引、汇聚、组织和管理互联网上的大规模软件开发人员,通过竞争、合作、协商等多种自主协同方式,让他们参与软件开发、分享软件开发知识和成果、贡献智慧和力量的一种新颖软件开发方法
-
群体化软件开发是一种基于社区的软件开发模式
-
群体化软件开发方法的支撑关键技术
- 基于社区的群体化组织
- 开源软件社区将核心开发人员与外围开发人员有机地结合在一起,依托软件仓库进行分布式协同开发
- 基于Issue的任务管理
- 开发任务的二类形式:修复软件缺陷、功能实现需求
- 创建Issue,提出软件开发任务
- 讨论Issue,分析开发任务的意义和价值
- 指派Issue,安排人员来完成Issue
- 掌控Issue,掌握Issue解决的进展状况
- 基于Git的分布式版本管理
- 基于Pull/Request的分布式协同开发
- 每个开发人员在本地完成编程工作后,不是直接向中心仓库推送代码,而是通过发送一个P/R合并请求,将原始代码库的克隆库推荐合并到中心仓库之中
- 接收到合并请求后,软件项目管理团队和开发人员群体需要对P/R进行审查
- 基于群智的知识分享
- 基于社区的群体化组织
第四章 软件计划管理
1 软件计划
(1)软件计划概述
- 软件计划是对软件实施所涉及的目标、任务、活动、资源、进度等进行规划
- 合同和策划阶段
- 制定初步软件开发计划
- 软件项目计划分发到各个开发成员
- 每个成员准确了解各自任务和工作以及实施进度要求
- 项目实施过程
- 根据软件开发的具体计划有序实施项目
- 发现项目实施中存在的问题:如进度滞后
- 出现偏差后调整软件项目计划
- 项目完成之后
- 总结项目计划实施情况
- 分析原因,指导后续其他项目的计划制定
(2)软件进度安排
-
两种途径
- 项目、资源 → 制定计划、交付日期
- 从后往前安排 ← 最后期限
-
进度管理中要妥善处理的2个问题
- 识别任务之间的并行、依赖关系
- 资源的分配和优化
-
甘特图
- 优点:简单,醒目,能动态地反映开发进展
- 缺点:不表示活动之间的依赖关系
-
计划网络图
- 反映任务间的顺序、并行依赖关系
-
软件进度计划的任务
- 确定每个活动的最早(最迟)开始时间和完成时间。
- 在开发方已有的资源投入下求解该软件项目的交付日期(工期),或给定工期(投资方要求)条件下来安排各活动的开始时间和结束时间。
- 确定关键活动、重点监管关键线路。所谓关键活动是指由于这些活动完成的耽误或更改,将直接影响项目工期目标完成。全部由关键活动组成的线路或者线路长度最长的线路称为关键线路。
- 根据给定的工期目标和已有项目各活动时长的条件下,对进度进行调整和优化
(3)计划的优化
- 工期优化
- 若网络计划图的计算工期大于要求的工期时,必须根据要求计划的进度,缩短工程项目的完工工期。主要从两个方面考虑:
- 优化活动间的逻辑关系,串行到并行
- 采取技术措施,提高开发效率,缩短关键工序的持续时间。
- 采取组织措施,充分利用非关键工序的机动时间,合理调配人力、物力和资金等,增加对关键工序的投入,以便缩短关键工序的持续时间
- 若网络计划图的计算工期大于要求的工期时,必须根据要求计划的进度,缩短工程项目的完工工期。主要从两个方面考虑:
- 资源优化
- 在项目工期不变的条件下,合理地利用资源。具体包括:
- 优先安排关键工序所需的资源
- 利用非关键工序的机动时间,错开各工序的开始时间,避开在同一时区内集中使用同一资源以免出现高峰
- 在确实受到资源制约,或在考虑综合经济效益的条件下,在许可时也可适当推迟工期,实现错开高峰的目的。
- 在项目工期不变的条件下,合理地利用资源。具体包括:
2 软件管理
(1)软件管理的特点
- 目标性: 获得预期的结果
- 进度性: 在限定期间完成
- 约束性: 具有有限的资源(如人员、经费、工具等)
- 多方性: 涉及多个不同人与组织
- 独立性: 无重复性
- 不确定性: 项目的实施及其结果不确定性
(2)软件管理内容
-
何为软件项目管理?
- 对软件项目所涉及的过程、人员、产品、成本和进度等要素进行度量、分析、规划、组织和控制的过程,以确保软件项目按照预定的成本、进度、质量要求顺利完成
- 人员:团队建设和管理纪律和激励机制
- 过程:过程定义,软件度量,项目计划,项目跟踪
- 产品:软件产品质量管理,软件产品配置管理,软件产品需求管理
-
过程管理
-
- 过程定义:定义、文档化软件开发过程、明确软件开发活动,得到一个良定义、全面、灵活、简洁和可供剪裁的软件开发过程
-
- 软件度量:对软件项目的过程、产品、资源的属性的定量描述,如软件项目的规模、成本、工作量、质量等
-
- 项目计划
-
- 项目跟踪:随时掌握软件项目的实际开发情况,提供项目实施情况的可视性,保证计划的适时调整
-
- 风险管理:对软件开发过程中各种风险进行识别、分析、预测、评估、监控的过程
-
-
产品管理
- 软件质量保证:为软件产品的质量提供某种可视性,知道哪些地方有质量问题,便于改进方法和措施,提高软件产品的质量
- 软件配置管理:对软件基线产品进行标识、存储、更动和发放,记录和报告其状态,确保软件产品的正确性和一致性,并对上述工作的审计的过程
- 软件需求管理:获取、文档化和评审用户需求,对用户需求变更进行控制和管理
-
人员管理
- 软件项目团队:确定开发团体的结构、明确人员的角色和任务、加强人员间的交流与合作,结构合理、任务明确、团结协作、交流顺畅
- 纪律激励机制:制定和实施纪律约束团体,通过激励机制激发人员的激情,严格的纪律,饱满的激情
(3)软件管理的方法
- 人员组织方式
- 民主制程序员组
- 主程序员组
- 现代程序员组:实际的“主程序员”应该由两个人共同担任: 一个技术负责人,负责小组的技术活动;一个行政负责人,负责所有非技术性事务的管理决策。
第五章 需求分析
1 需求分析基础
- 需求的概念:分类、特点、质量要求、重要性
- 需求工程
- 需求工程的一般过程
- 需求工程的常用方法
- 结构化需求分析方法
- 面向对象需求分析方法
- 需求工程的输出、评审和管理
(1)需求的概念
-
软件开发的本质
-
何为利益相关方(stakeholder)
- 从软件系统中受益或与软件系统相关的人、组织或者系统
- 受益:使用、获益、盈利
- 相关:发生操作和交互、存在关联性
-
软件利益相关方的表现形式
- 用户:最终使用软件的人
- 客户:从中获取利益的组织
- 系统:与待开发系统进行交互的系统
- 开发者:负责开发软件系统的人
- 示例:空巢老人看护软件利益相关方
- 用户:老人,家属,医生
- 客户:投资方
- 系统:机器人
-
何为软件需求(Software Requirement)?
- 从软件本身的角度,软件需求是指软件用于解决现实世界问题时所表现出的功能和性能等方面的要求
- 从软件利益相关方的角度,软件需求是指软件系统的利益相关方对软件系统的功能和质量,以及软件运行环境、交付进度等方面提出的期望和要求
-
软件需求的类别
- 软件功能性需求(Functional)
- 能够完成的功能及在某些场景下可展现的外部可见行为或效果
- 软件质量方面的需求(Quality)
- 外部质量属性,外部可展现的,用户、客户等会非常关心,如运行性能、可靠性、易用性等
- 内部质量属性,隐藏在内部的,软件开发工程师会非常关心,如可扩展性、可维护性、可理解性
- 软件开发约束性需求(Constraint)
- 开发成本、交付进度、技术选型、遵循标准等方面提出的要求
- 软件需求示例:空巢老人看护软件
- 功能性需求:自主跟随老人、获取老人图像和视频信息、检测老人是否摔倒等
- 质量方面的需求:始终保持在2米的安全距离,对机器人的控制在2秒内响应等
- 约束性需求:成本不能超出50万元,要求半年内交付使用等等
- 软件功能性需求(Functional)
-
软件需求的重要性
- 软件的价值所在
- 软件开发的基础和前提
- 软件验收的标准和依据
(2)需求工程
-
旨在用工程的理念和方法来指导软件需求实践,它提供了一系列的过程、策略、方法学和工具,帮助需求工程师加强对业务或领域问题及其环境的理解、获取和分析软件需求,指导软件需求的文档化和评审,以尽可能获得准确、一致和完整的软件需求,产生软件需求的相关软件制品
-
需求工程的方法学
- 抽象
- 20世纪70年代结构化数据和数据流抽象
- 20世纪90年代面向对象抽象
- 建模
- 采用自然语言或结构化自然语言
- 图形化的需求建模语言
- 分析
- 循序渐进地获得软件需求细节,进而逐步得到详细的软件需求
- 抽象
-
需求工程方法(详见复习重点)
- 结构化需求分析方法
- 面向对象需求分析方法
-
需求工程的输出
- 软件需求模型
- 软件需求文档
- 软件原型
- 修正的软件开发计划
- 验收测试计划
2 需求获取
-
获取软件需求是指得到或产生软件需求
-
明确问题和基于软件的解决方案
-
导出和构思初步软件需求
-
描述初步软件需求
- 自然语言描述
- 软件原型模式
- 用例图描述(详见复习重点)
-
用例的进一步详细描述
- 用例名:用户登录
- 用例标识: UC-UserLogin
- 主要执行者:家属、医生
- 目标:通过合法身份登录系统以获得操作权限
- 范围:空巢老人看护软件
- 前置条件:使用App软件之时
- 交互动作:
- 用户输入账号和密码
- 系统验证用户账号和密码的正确性和合法性
- 验证正确和合法则意味着登录成功
3 分析软件需求
(1)分析软件需求概述
-
基于初步软件需求,进一步精化和分析软件需求,确定软件需求优先级,建立软件需求模型,发现和解决软件需求缺陷,形成高质量的软件需求模型和软件需求规格说明书
-
用例视角
- 具有哪些功能、功能间有何关系、功能与利益相关方有何关系
- UML提供了用例图来分析和描述用例视角的软件需求模型
-
行为视角
- 用例是如何通过业务领域中一组对象以及它们间的交互来达成的
- UML提供了交互图、状态图来描述行为视角的软件需求模型
-
结构视角
- 业务领域有哪些重要的领域概念以及它们之间具有什么样的关系
- UML提供了类图来描述和分析业务领域的概念模型
-
UML交互图 详见重点
-
类图 详见重点
-
对象图
- 类图在系统的运行过程中某个时刻点上或某一时间段内的实例化样本
- 类图中的一个类在对象图中可表现为多个活跃的对象实例
- 对象图的链接边是类图中关联边的实例化
- 类图中的其他边,如继承、依赖等在对象图中则无从表现
- 示例:
- 不常用
- 类图在系统的运行过程中某个时刻点上或某一时间段内的实例化样本
-
状态图
- 功效
- 描述实体(对象、系统)在事件刺激下的反应式动态行为及其导致的状态变化
- 刻画了实体的可能状态、每个状态下可响应事件、响应动作、状态迁移
- 图的构成
- 节点:状态
- 边:迁移,即状态间因事件刺激而触发的状态变化
- 功效
(2)分析软件需求过程
- 分析和确定软件需求优先级
- 分析软件需求重要性
- 分析软件需求优先级
- 确定用例分析和实现的次序
- 分析和确定软件需求模型
分析和建立用例的交互模型见重点- 分析和建立分析类模型
- 确定分析类
- 确定分析类的职责
- 确定分析类的属性
- 确定分析类之间的关系
- 绘制分析类图
- 分析和建立软件需求的状态模型
- 用UML的状态图来描述这些对象的状态模型,以刻画对象拥有哪些状态、对象的状态如何受事件的影响而发生变化
- 分析和建立分析类模型
(3)软件需求文档及评审
第六章 软件设计
1 软件设计概述
(1)软件设计基础
-
软件设计:针对软件需求,综合考虑各种制约因素,探究软件实现的解决方案
-
设计前提:软件需求
- 定义了要做什么样的软件
-
设计考虑:制约因素
- 资源:时间、人力、财力、开发辅助工具
- 技术:技术平台,如DBMS还是文件系统
-
软件设计过程
- 软件结构设计
- 从全局和宏观视角、站在最高抽象层次来设计软件系统
- 用户界面设计
- 设计软件对外展示以及与用户进行交互的界面,关注软件如何与用户进行交互
- 软件详细设计
- 对体系结构设计和人机交互设计成果进行细化和精化,获得高质量的、充分细化的软件设计模型
- 数据设计;接口设计;类设计;算法设计;
- 软件结构设计
-
软件设计元素
- 设计类:类既是最基本的设计单元,也是最基本的模块单元
软构件 - 软构件
- 可分离、可单独重用、可独立部署和执行的一类设计元素
- 如动态链接库(.DLL)、可运行的Java JAR包、微服务镜像等就属于软构件
- 子系统
- 完成特定功能、逻辑上相互关联的一组模块集合
- 有助于管理软件系统的复杂度,简化软件设计和实现
- 设计类:类既是最基本的设计单元,也是最基本的模块单元
-
软件设计基本原则
- 抽象原则
- 模块化、高内聚度和低耦合度原则
- 信息隐藏原则
- 关注点分离原则
- 软件重用原则
(2)软件设计方法
- 结构化方法
-
- 复审并精化数据流图
-
- 确定输入流和输出流的边界
-
- 第一级分解方法
-
- 第二级分解方法
-
- 软件结构求精
-
- 面向对象方法
- 用包图表示的软件系统的结构设计
- 用交互图来表示用户界面设计
2 软件体系结构设计
(1)软件体系结构基础
-
软件体系结构设计元素
- 构件/组件(Component):构成体系结构的基本功能部件
- 软件系统中的物理模块,具有特定的功能和精确定义的对外接口,外界可通过接口来访问它
- 例:.dll,.jar文件
- 连接件:组件之间的连接和交互关系
- 每个软构件并非孤立,它们之间通过连接进行交互
- 交互的目的是为了交换数据、获得服务
- 例:接口,端口
- 约束
- 构件/组件(Component):构成体系结构的基本功能部件
-
软件体系结构设计视图
- 逻辑视图
- 开发视图
- 部署视图
- 运行视图
-
软件体系结构建模
- 包图
- 构件图
- 部署图
软件体系结构风格
分层风格、管道过滤器风格、黑板风格、MVC风格、SOA风格、消息总线风格
-
软件设计模式:以设计重用为目的,采用一种良定义的、正规的、一致的方式记录的软件设计经验
-
常用软件体系结构风格
- 分层风格
- 层次间的关系
- 每层为其紧邻上层提供服务,使用紧邻下层所提供的服务
- 上层向下层发出服务请求,下层为上层反馈服务结果
- 下层向上层提供事件信息,上层对下层通知做出处理
- 特点:松耦合,可替换,可复用,标准化
- 层次间的关系
- 管道与过滤器风格
- 构件
- 将软件功能实现为一系列处理步骤,每个步骤封装在一个过滤器构件中
- 连接子
- 相邻过滤器间以管道连接,一个过滤器的输出数据借助管道流向后续过滤器,作为其输入数据
- 编译器采用的就是一个典型的管道/过滤器风格
- 构件
- 黑板风格:将软件系统划分为黑板、知识源和控制器三类构件
- 黑板:负责保存问题求解过程中的状态数据,并提供这些数据的读写服务
- 知识源:负责根据黑板中存储的问题求解状态评价其自身的可应用性,进行部分问题求解工作,并将此工作的结果数据写入黑板
- 控制器:负责监视黑板中不断更新的状态数据,安排(多个)知识源的活动
- MVC风格
- 模型构件:负责存储业务数据并提供业务逻辑处理功能
- 视图构件:负责向用户呈现模型中的数据
- 控制器:在接获模型的业务逻辑处理结果后,负责选择适当的视图作为软件系统对用户的界面动作的响应
- 步骤:
- 创建视图,视图对象从模型中获取数据并呈现用户界面
- 控制器将用户界面事件转换为业务逻辑处理功能的调用
- 模型进行业务逻辑处理,将处理结果回送给控制器,必要时还需将业务数据变化事件通知给所有视图
- SOA风格
- 将软件系统的软构件抽象为一个个的服务(Service),每个服务封装了特定的功能并提供了对外可访问的接口
- 任何一个服务既可以充当服务的提供方,接受其他服务的访问请求;也可充当服务的请求方,请求其他服务为其提供功能
- 任何服务需要向服务注册中心进行注册登记,描述其可提供的服务以及访问方式,才可对外提供服务
- 总线风格:包含了一组软构件和一条称为“消息总线”的连接件来连接各个软构件
- 分层风格
(2)软件体系结构设计过程
-
软件体系结构设计的原则
- 高层抽象和组织
- 模块化
- 信息隐藏
- 软件重用
- 多视点分离
-
设计初步的软件体系结构
- 任务:基于功能性和非功能性软件需求,参考业界已有的软件体系结构设计风格,设计出目标软件系统的初始体系结构,明确每个构件的职责以及构件间的通信和协作关系
- 输出:初步的软件体系结构
-
重用开源软件及已有软件资产
- 可直接使用的软件资产
- 清晰地定义它们与当前软件系统间的交互接口
- 包括数据交换的格式、互操作协议等
- 不可直接使用但具复用潜力的设计资产
- 采用接口重构、适配器等方法将其引入到当前体系结构中
- 接口重构是指,调整当前体系结构中面向可复用设计资产的调用接口,使之与其提供的服务接口相匹配
- 可直接使用的软件资产
-
精化软件体系结构
- 选择软件体系结构所依赖的公共基础设施:如操作系统、软件中间件、数据库管理系统、软件开发框架、安全服务等
- 确定软件体系结构中的设计元素:包括子系统、软构件和关键设计类等,明确其职责和接口,从而为开展详细设计奠定基础
-
设计部署模型:刻画软件系统的各个子系统、软构件如何部署到计算节点上运行的,描述它们的部署和运行环境
3 用户界面设计
(1)用户界面基础
-
人机交互的关键
- 用户的满意度
- 方便输入
- 直观输出
-
用户界面元素及实现方式
- 静态元素
- 动态元素
- 用户输入元素
- 用户命令元素
-
用UML类图表示用户界面元素
- 窗口或对话框 -> 对象类
- 静态和动态元素 -> 类属性
- 输入元素 -> 类属性
- 命令元素 -> 类方法
(2)用户界面设计过程
-
用户界面设计的任务
- 根据软件需求及其操作流程,为其设计出与用户进行交互的界面,支持用户对软件的操作和使用
-
用户界面设计的原则
- 直观性
- 易操作性
- 反应性
- 一致性
- 容错性
- 人性化
-
用户界面设计的过程
-
用户界面初步设计
- 根据需求确定用户界面
- 确定用户界面的设计元素(属性和操作)
-
建立用户界面间的跳转关系
- 用UML图来表示用户界面的跳转关系
- 交互图:表示特定场景下的跳转及跳转发生时的消息传递
- 类图:表示界面间所有可能发生的跳转及跳转的原因
- 用UML图来表示用户界面的跳转关系
4 软件详细设计
(1)软件详细设计基础
- 详细设计的任务
- 输入:软件体系结构设计、用户界面设计、软件需求
- 任务:对体系结构设计和用户界面设计成果进行细化和精化,获得高质量、面向实现的设计模型
- 软件详细设计UML模型(活动图)
(2)软件详细设计活动
- 用例设计
- 任务:为需求模型中每个用例设计软件实现方案
- 原则:整体性、正确性、优化性等
- 输出:用例实现方案的交互图、设计类图
- 类设计
- 任务
- 对界面类、关键设计类、设计类等进行设计优化和精化,
- 明确设计类的内部实现细节
- 精化到可以提交软件实现的程度
- 结果
- 类图、状态图、活动图等
- 任务
- 数据设计
- 任务
- 设计需要持久保存的数据以及这些数据之间的关系
- 数据组织方式(例如关系数据库中的表、关键字、外键等)之间进行映射
- 为提高数据存储、操作性能而设计持久存储机制优化设施
- 设计与建模
- 设计数据的结构、存储、组织和访问
- 对数据设计的结果进行建模
- 任务
- 子系统
- 任务
- 确定子系统内部结构,设置包含于其中的更小粒度子系统、构件和设计类,明确它们之间的协作关系
- 确保它们能够协同实现子系统接口规定的所有功能和行为
- 任务
- 构件设计
- 任务
- 定义构件内部的设计元素及其协作方法
- 内部设计元素可以是子构件,也可以是粒度更细的类
- 任务
5 软件设计整合、验证及评审
- 设计整合
- 汇总迄今获得的所有设计模型
- 包括体系结构模型、界面设计模型、用例设计模型、子系统/构件/类设计模型、数据模型等
- 形成系统、完整的软件设计方案
- 汇总迄今获得的所有设计模型
- 设计验证
- 验证整个设计的正确性、优化性和充分性等
- 验证设计模型之间的不一致性、冗余性等
- 发现设计方案中的问题并进行整改
第七章 软件实现和测试
1 软件实现
(1)软件实现概述
-
软件实现的任务
- 根据软件设计模型(包括体系结构设计模型、用户界面设计模型和详细设计模型),采用编程语言编写出目标软件系统的程序代码,并对代码进行必要的测试,以发现和纠正代码存在中的缺陷,并将可运行的目标代码部署到目标计算机上运行
- 根据软件设计模型(包括体系结构设计模型、用户界面设计模型和详细设计模型),采用编程语言编写出目标软件系统的程序代码,并对代码进行必要的测试,以发现和纠正代码存在中的缺陷,并将可运行的目标代码部署到目标计算机上运行
-
这三项工作均由程序员负责完成
- 编码:基于软件设计模型和文档,采用选定的程序设计语言,编写出目标软件系统的程序代码
- 单元测试:对自己编写的各个基本模块进行单元测试,以发现模块单元中存在的缺陷和问题
- 调试:发现产生缺陷原因,定位缺陷位置,进而对代码缺陷进行修复
-
软件测试由软件测试工程师完成
(2)编程语言的类型和选择
- 选择
- 软件的应用领域
- 不同应用领域的软件通常会选择不同的程序设计语言来加以实现
- 科学和工程计算领域选用Fortran、C等程序设计语言,数据库应用软件开发会选用Delphi、Visual Basic、SQL等程序设计语言,机器人等嵌入式应用选用C、C++、Python等程序设计语言,互联网应用开发选用Java、ASP等程序设计语言
- 与遗留软件系统的交互
- 软件的特殊功能及需求
- 是否需要与底层的硬件系统进行交互,如果需要,可以考虑采用诸如C、汇编语言
- 是否需要丰富的软件库来支持功能的实现,如果需要,可以考虑具有丰富软件库的编程语言,如Python、Java等
- 是否需要对相关的知识进行表示和推理,如果需要,可以考虑选用描述性的程序设计语言,如Prolog、Lisp等
- 软件的目标平台
- 如果目标软件系统需要部署在J2EE架构之上,那么就需要选择Java编程语言;如果需要借助于ROS来开发机器人软件,那么建议选择C、C++和Python等编程语言
- 程序员的编程经验
- 软件的应用领域
2 编码
(1)编码概述
- 编码的原则
- 易读,一看就懂
- 易改,便于维护
- 降低代码的复杂度
- 尽可能地开展软件重用和编写可重用的程序代码
- 要有处理异常和提高代码的容错性
- 代码要与模型和文档相一致
- 遵循编码风格
(2)编码过程
- 编写类代码
- 编写实现类的代码
- 编写实现类方法的代码
- 编写实现类间关联的代码
- 编写实现设计类间聚合和组合关系的代码
- 编写实现接口关系的代码
- 编写实现继承关系的程序代码
- 编写实现包的代码
- 编写用户界面代码
- 代码片段的重用
(3)缺陷
- 软件缺陷是指软件制品中存在不正确的软件描述和实现
3 软件测试
(1)测试概述
- 软件缺陷不可避免
- 如何应对缺陷?
- 预防缺陷
- 容忍缺陷
- 发现缺陷
- 修复缺陷
- 何为软件测试
- 运行软件或模拟软件的执行,发现软件缺陷的过程——缺陷测试
- 向开发人员和客户展示软件的有效性——确认测试
- 软件测试的原理
- 程序本质上是对数据的处理
- 设计数据(测试用例) -> 运行测试用例(程序来处理数据) -> 判断运行结果(是否符合预期结果)
- 程序本质上是对数据的处理
- 测试执行的步骤
-
- 明确待测试对象
-
- 设计测试用例
-
- 运行代码和测试用例
-
- 分析运行结果
-
(2)测试用例设计
-
测试用例是一个四元偶
- 输入数据:交由待测试程序代码进行处理的数据
- 前置条件:程序处理输入数据的运行上下文,即要满足前置条件
- 测试步骤:程序代码对输入数据的处理可能涉及到一系列的步骤,其中的某些步骤需要用户的进一步输入
- 预期输出:程序代码的预期输出结果
-
白盒测试技术:基于程序内部的执行流程来设计测试用例
- 特点:必须了解程序的内部工作流程才能设计测试用例
- 基本路径测试
-
- 根据程序逻辑画出流程图
-
- 将流程图转换为流图
-
- 确定基本路径集合
-
- 针对测试路径设计测试用例
-
-
黑盒测试技术:基于程序的外在功能和接口来设计测试用例
- 特点:
- 知道程序功能和性能,不必了解程序内部结构和处理细节
- 黑盒测试与软件如何实现无关,如果软件实现发生变化,测试用例仍然可以使用
- 黑盒测试用例的开发可以与软件开发并行进行,能够缩短软件开发周期
- 方法:
- 等价分类法
- 思想
- 把程序的输入数据集合按输入条件划分为若干个等价类
- 每一个等价类对于输入条件而言是等价的
- 为每一个等价类设计一个测试用例,包括有效或无效的输入
- 优点
- 可以滤掉同类数据,减少测试次数,不丢失发现错误的机会
- 思想
- 边界值分析法
- 等价分类法
- 特点:
(3)软件测试的过程和策略
-
单元测试
- 测试对象
- 对软件基本模块单元进行测试
- 过程、函数、方法、类
- 测试方法:大多采用白盒测试技术
- 测试对象
-
集成测试
- 测试对象
- 对软件模块之间的接口进行测试
- 过程调用、函数调用、消息传递、远程过程调用
- 测试技术:采用黑盒测试技术
- 测试对象
-
确认测试
- 测试对象
- 对软件的功能和性能进行测试
- 判断目标软件系统是否满足用户需求
- 依据和标准
- 软件需求规格说明书
- 测试技术:采用黑盒测试技术
- 测试对象
-
α测试
- 软件开发公司组织内部人员模拟各类用户行为对即将面市的软件产品(称为α版本、内部测试版)进行测试,发现错误并修正
- 尽可能逼真地模拟实际运行环境和用户对软件产品的操作,并尽最大努力涵盖所有可能的用户操作方式
- 经α测试并进行修改后的软件产品称为β版本(也称外部测试版)
-
β测试
- 软件开发公司组织各方面的典型用户在日常工作中实际使用β版本,或为对外进行宣传而将β版本免费赠送给典型用户(很多情况下,β版本可以通过Internet免费下载,也可以向软件公司索取),并要求用户报告异常情况、提出批评意见
- β测试是在与开发者无法控制的环境下进行的软件现场应用
(4)面向对象软件测试
- OO软件的构成基础与传统结构化程序设计不同
- 需要开发测试驱动程序
- 采用白盒测试方法
(5)非功能性测试
- 性能测试
- 强度测试
- 配置和兼容性测试
- 安全性测试
- 可靠性测试
- 用户界面测试
- 本地化测试
- Web测试
- 安装测试
4 软件调试
- 软件调试就是要基于程序代码,确定软件缺陷的原因、定位缺陷的位置,从而知道那里错了、如何修复缺陷
- 目的
- 测试发现缺陷
- 调试定位缺陷
- 排错纠正错误
- 独立性不同
- 测试由独立的测试小组进行
- 调试和排错由开发人员完成
第八章 软件维护和演化
1. 软件维护与演化
(1)软件维护
-
软件变更和修改是不可避免的
- 待修复的错误
- 需求的变更/新的需求
- 技术和商务环境变化
- 系统的性能或可靠性等需要改进
- 系统中增加了新的计算机和设备
-
软件需要进行维护
- 出故障,不可正常工作
- 服务变化,需要升级
- 运行环境变化,需要适应
-
软件维护:软件在交付使用后,由于应用需求和环境变化以及自身问题,对软件系统进行改造和调整的过程
-
维护形式:
- 纠正性维护:纠正软件中的缺陷和错误
- 完善性维护:对软件进行改造以增加新的功能、修改已有的功能
- 适应性维护:对软件进行改造以便适应新的运行环境和平台
- 预防性维护:对软件结构进行改造以便提高软件的可靠性和可维护性等
-
软件维护工程师
(2)软件演化
- 特点:软件演化与开发是一个集成的、完整的、增量式的过程,可以用螺旋模型表示。主要针对软件的大规模功能增强和结构调整,以实现变化的软件需求,或者提高软件系统的质量。
概念 | 功能增强粒度 | 应对变化方式 | 持续性或间隔性 | 版本变化 |
---|---|---|---|---|
软件演化 | 粗粒度 | 主动 | 持续性 | 是 |
软件维护 | 细粒度 | 被动 | 间隔性 | 不一定 |
- 软件演化法则
- 持续变化法则
- 增加复杂性法则
- 自我调节法则
- 组织稳定性守恒法则
- 熟悉度守恒法则
- 功能持续增长法则
- 质量衰减法则
- 反馈系统法则
2. 软件逻辑老化
(1)逻辑老化的特点
- 何为逻辑老化
- 软件在维护和演化的过程中出现的用户满意度降低、质量逐渐下降、变更成本不断上升这样一种现象
- 软件逻辑老化的现象
- 质量下降
- 变更成本增加
- 用户满意度降低
- 软件逻辑老化的原因
- 缺乏变更
- 负面变更
(2)解决逻辑老化的方法
逻辑老化软件的维护和升级将会收到预算、期限等多种因素的约束,因此维护团队需要对逻辑老化软件基于其质量(失效率和可维护性等)及其业务价值(系统的使用情况、支持的业务流程、系统的可靠性、输出的价值)进行评估,再做出适当决策。
3. 软件维护的过程与技术
(1)软件维护技术
- 代码重组:在不改变软件功能的前提下,对程序代码进行重新组织,使得重组后的代码具有更好的可维护性,能够有效支持对代码的变更
- 逆向工程:基于低抽象层次软件制品,通过对其进行理解和分析,产生高抽象层次的软件制品
- 设计重构
- 再工程
(2)软件维护过程
- 软件维护需要解决的问题
- 人员的问题
- 软件制品的问题
- 维护副作用的问题
- 维护成本不断增加的问题
复习重点
结构化需求分析方法
- 基本思想:数据主义认为,整个宇宙都是由数据流构成的,各个数据处理系统构成人类的社会
- 数据流图
- Data Flow Diagram(简称DFD):描述输入数据流到输出数据流的变换(即加工)过程,用于对系统的功能建模
- 基本元素
- 画分层数据流图的步骤
-
- 画系统的输入和输出
-
- 画系统内部
-
- 画加工内部
-
- 根据自顶向下逐层分解的思想,重复第3步,继续分解加工,直至每个尚未分解的加工都足够简单(即不必再分解)
-
- 分层数据流图示例——空巢老人看护系统
- 确定源或宿:老人、家属、医生、机器人和时钟
- 除了时钟外,都既是源又是宿
- 顶层图唯一的加工:软件系统(空巢老人看护系统)
- 确定数据流:系统的输入/输出信息
- 输入数据流:老人的呼叫、家属和医生的控制命令、老人的图像和视频、定时器
- 输出数据流:家属和医生的语音和视频、异常状态和警告信息、机器人执行指令
- 顶层图通常没有文件
- 确定源或宿:老人、家属、医生、机器人和时钟
面向对象需求分析方法
-
基本思想:现实世界(应用问题)还是计算机世界(软件系统),它们都是由多样化的对象所构成的,每个对象都有其状态并可提供功能和服务,不同对象之间通过交互来开展协作来实现功能和提供服务
-
面向对象软件工程提供对象、类、属性、操作、消息、继承等概念来抽象表示现实世界的应用,分析其软件需求特征,建立起软件需求模型,描述软件需求
-
面向对象建模语言
- 概念:基于面向对象的概念和抽象,提供图形化的图符,用来表示软件系统的一种语言
- 示例:
-
UML: Unified Modeling Language
- Unified(统一)
- 提取不同方法中最好建模技术,如OMT(James Rumbaugh),Booch method(Grady Booch )和OOSE(Ivar Jacobson)
- 采用统一、标准化的表示方式
- Modeling(建模)
- 对现实系统和软件系统进行可视化建模
- 建立系统模型
- Language(语言)
- 图形化语言:语法、语义和语用
- 包括规则,约束 扩展机制
- 图形化语言:语法、语义和语用
- UML用途:用来可视化(visualize) 、描述(specify)、构造(construct)和文档化(document)软件密集型系统的各种产品
- Unified(统一)
-
多视点建模
- 结构视点(Structural View)
- 用于描述系统的构成
- UML提供了包图(Package Diagram)、类图(Class Diagram)、对象图(Object Diagram)和构件图(Component Diagram),从不同的抽象层次来表示系统的静态组织及结构
- 行为视点(Behavioral View)
- 刻画系统的行为
- UML提供了交互图(Interaction Diagram)、状态图(Statechart Diagram)与活动图(Activity Diagram),以从不同侧面刻画系统的动态行为。
- 部署视点(Deployment View)
- 刻画目标软件系统的软件制品及其运行环境
- UML提供了部署图(Deployment Diagram)来描述软件系统的部署模型
- 用例视点(Use Case View)
- 刻画系统的功能
- UML提供了用例图(Use Case Diagram)以描述系统的用例及其与外部执行者之间的关系。
- 结构视点(Structural View)
-
面向对象需求分析步骤
- 明确问题边界,获取软件需求,建立用例模型
- 开展用例分析,精化软件需求,建立分析模型
- 汇总需求模型,撰写需求文档,评审软件需求
用例图描述
-
用例图用来描述初步软件需求
-
图的构成
- 执行者
- 系统之外的实体,他们使用软件系统功能、与软件系统交换信息
- 可以是一类用户,也可以是其他软件系统或物理设备
- 用例
- 表示执行者为达成一项相对独立、完整的业务目标而要求软件系统完成的功能
- 边:执行者与用例间、用例之间、执行者之间的关系
- 执行者
-
用例间的关系
- 用例间的关系-包含关系
- 如果用例B是用例A的某项子功能,则称用例A包含用例B
- 用例间的关系-扩展关系
- 如果用例A与B相似,但A的功能较B多,A的动作序列是在B的动作序列中的某些执行点上插入附加动作序列而构成的,则称用例A扩展用例B
- 用例间的关系-继承
- 如果A与B相似,但A的动作序列是通过改写B的部分动作或者扩展B的动作而获得的,则称用例A继承用例B
- 如果A与B相似,但A的动作序列是通过改写B的部分动作或者扩展B的动作而获得的,则称用例A继承用例B
- 边界框
- 表示整个软件系统或子系统的边界
- 表示整个软件系统或子系统的边界
- 用例间的关系-包含关系
UML交互图
-
作用:刻画对象间的消息传递,分析如何通过交互协作完成功能
- 用例的功能实现方式
- 软件系统在某种使用场景下对象间的交互协作流程
- 软件系统的某个复杂操作的逻辑实现模型
-
二类交互图
- 顺序图(Sequence Diagram):强调消息传递的时间序
- 通信图(Communication Diagram):突出对象间的合作
- 顺序图和通信图语义上等价,没必要针对同一建模目标同时创建这二个图
-
顺序图:描述对象间的消息交互序列
- 纵向:时间轴,对象及其生命线(虚线),活跃期(长条矩形)
- 横向:对象间的消息传递
类图
- 功效:描述系统的类构成,刻画系统的静态组成结构
- 图的构成
- 结点:表示系统中的类(或接口)及其属性和操作
- 边:类之间的关系
- 类的表示
- 属性的表示:
- [可见性] 名称 [: 类型] [多重性] [= 初值] [{约束特性}]
- 可见性
- 公开(+): 所有对象均可访问
- 保护(#): 所在类及子类对象均可访问
- 私有(-): 仅所在类的对象才可访问
- 多重性:属性取值数量, 如1,0…1,0…* ,1…,
- 约束特性
- 可更改性:{readOnly}表示只读,缺省为
- 顺序性: {ordered}表示属性取值是有序的,缺省为
- 唯一性: {bag}表示属性取值元素允许出现重复元素(缺省)
- 静态性:{static}表示静态属性,属性值由类所有实例对象共享
- 方法的表示
- [可见性] 名称[(参数表)] [: 返回类型] [{约束特性}]
- 操作的约束特性
- 查询操作: {isQuery = true}表示查询操作,{ isQuery = false}表示修改操作,缺省为修改操作。
- 多态性:{isPolymorphic = true}表示本操作允许多态,即可被子类中相同定义形式的操作所覆盖
- 并发性:{concurrency = sequential} 任一时刻只有一个对象调用可执行。{concurrency = guarded} 并行线程可同时调用多个对象的本操作,但同一时刻只允许一个调用执行。{concurrency = concurrent} 并行线程可以同时调用多个对象的本操作且这些调用可并发执行
- 异常:操作在执行过程中可能引发异常
- 接口
- 一种不包含操作实现部分的特殊类
- 接口的形式
- 供给接口: 对外提供的接口
- 需求接口: 需要使用的接口
- 类间的关系
- 关联
- 依赖
- 集成
- 实现
- 聚合
- 组成
- 类图注意事项
- 用单数名词来描述类名,少用缩写
- 按照方向表示类间关系
- 垂直方向表示继承关系
- 水平方向表示关联、聚合、组合、依赖、实现关系
- 注意画图位置
- 关联名应位于关联边的居中位置
- 多重性、角色名、约束特性等应靠近关联端
分析和建立用例的交互模型
-
任务:分析和描述用例是如何通过一组对象之间的交互来完成的
-
步骤
- 分析和确定用例所涉及的对象及其类
- 分析和确定对象之间的消息传递
- 绘制用例的交互图
-
软件需求用例的处理通常涉及三种不同类对象:边界类,控制类,实体类
-
边界类
- 定义:由于这些类对象处于系统的边界,需与系统外的执行者进行交互,因而将这些对象所对应的类称之为边界类
- 作用
- 交互控制,处理外部执行者的输入数据,或者向外部执行者输出数据
- 外部接口,如果外部执行者表现为其他的系统或者设备,那么边界类对象需要与系统之外的其他系统或设备进行信息交互
-
控制类
- 控制类对象作为完成用例任务的主要协调者
- 一般而言,控制类并不负责处理具体的任务细节,而是负责分解任务,并通过消息传递将任务分派给其他对象类来完成,协调这些对象之间的信息交互
-
实体类
- 用例所对应业务流程中的所有具体功能最终要交由具体的类对象来完成,这些类称之为实体类
- 用例所对应业务流程中的所有具体功能最终要交由具体的类对象来完成,这些类称之为实体类
-
分析和确定对象之间的消息
- 确定消息的名称
- 直接反映了对象间交互的意图,也体现了接收方对象所对应的类需承担的职责和任务
- 意图:请求、通知
- 一般地,消息名称用动名词来表示
- 确定消息传递的信息
- 信息:通知和请求的内容
- 这些信息通常以消息参数的形式出现,也即一个对象在向另一个对象发送消息的过程中,需要提供必要的参数,以向目标对象提供相应的信息
- 确定消息的名称