软件和软件工程
软件
软件=程序+数据+文档
- 程序:按事先设计的功能和性能需求执行的指令序列
- 数据:程序能正常操纵信息的数据结构
- 文档:与程序开发、维护和使用有关的图文材料
软件的特征
-
软件是开发的或者是工程化的,并不是制造的
-
软件生产可以是是简单的拷贝
-
软件会被多次修改
-
软件开发环境对产品影响较大
-
软件开发时间和工作量难以估计
-
软件的开发进度几乎没有客观衡量标准
-
软件测试非常困难
-
软件不会磨损和老化
-
软件维护易产生新的问题
软件的双重作用
- 一方面是一种产品
- 提供计算能力
- 产生、管理、获取、修改、显示或传输信息
- 另一方面是开发其他软件产品的工具
- 支持或直接提供系统所需的功能
- 控制其他程序(如操作系统)
- 改善通信(如网络软件)
- 帮助开发其他软件(如软件开发工具)
- 其他功能…
软件的分类
- 按软件功能
- 系统软件
- 操作系统
- 数据库管理系统
- 设备驱动程序
- 通信处理程序等
- 支撑软件
- 文本编译程序
- 文件格式化程序
- 磁盘或磁带间数据传输的程序
- 程序库系统
- 支持需求分析、设计、实现、测试和支持管理软件
- 应用软件
- 商业数据处理软件
- 工程和科学计算软件
- 家属其辅助设计/制造软件
- 系统仿真软件
- 智能产品嵌入软件
- 医疗、制药软件
- 事务管理、办公自动化软件
- 计算机软件教学软件
- 系统软件
- 按服务对象
- 项目软件:服务对象是某个具体范围的软,如:教务管理系统
- 产品软件:服务对象是庞大的客户群体的软件
软件的发展
个体化:50中~60中,为解决某个具体问题而编写的程序
作坊式:60中~70中,软件结合了一些说明文档,但没有组织管理
工程化:70中~80中,软件正在结合了文档,开始工程化管理
产业化:80中~现在,形成完整的产业链
软件的发展为什么快?
- 计算需求:适应新环境变化,从单机计算到云计算
- 业务需求:软件必须改善,实现新的业务需求,从单击OA系统到集团互联网OA软件
- 嵌入需求:软件必须扩展,满足新一代系统或数据库的互操作性,从单机数据库到HBase云数据库
- 架构需求:软件必须重新设计,在新的网络环境是可用的
软件危机
在计算机软件的开发和维护过程中所遇到的一系列的严重问题
为什么会发生软件危机?
- 软件成本的日益增加
- 软件技术进本 < 需求增长,只能增加软件复杂度
产生软件危机的原因
- 客观:软件本身的特点
- 逻辑部件
- 规模庞大
- 主观:不正确的开发方法
- 忽视需求分析
- 财务认为:软件开发=程序编写
- 轻视软件维护
消除软件危机的途径:软件工程
软件工程
定义:应用软件应用系统化的、科学化的、定量的方法,来开发、运行和维护软件,即,将工程应用到软件,并对应以上中的各种方法的研究
目标:在给定的时间和预算内,按照用户的需求,开发易修改、高效、可开、可维护、适应力强、可移动、可重用的软件。
软工三要素:方法、工具、过程
-
工具:它为软件工程的过程和方法提rj供自动化或半自动化的工具支持。
- 计算机辅助软件工具(CASE):将若干工具集成起来,与软件工程数据库和计算机系统构成一个软件开发的系统,系统中某个工具的信息加工结构可以作为另一工具的输入
- 软件工程环境:集成的软件工程工具加上人的因素构成了软件工程环境
- 对规则强制性
-
方法:是完成软件工程项目的技术手段。
- 它支持项目计划和估算、系统和软件需求分析、设计、编程、测试和维护。
- 软件工程方法依赖一组原则,它贯穿软件工程的各个环节。
- 软件工程方法分为两类:结构化方法和面向对象方法
-
过程:贯穿软件开发的各个环节,在各个环节之间建立里程碑。
- 管理者在软件工程工程中对软件开发的质量、进度、成本进行评估、管理和控制
- 技术人员采用相应的方法和工具进行评估、管理和控制;技术人员采用相应的方法和工具生成软件工程产品(模型、文档、数据、报告、表格等)。
- 方法和工具相结合
方法的强弱
重型方法论、轻型方法论
-
重型方法论:强制性的文档,适合大规模的团队
-
轻型方法论:灵活性的文档,适合小规模的团队
方法论的选择:根据团队内交流的频率选择
软件工程的发展历程
传统软件工程:解决软件危机而出现的名词,形成基本的框架
对象工程:面向对象的分析与设计,演化为一种完整的软件开发方法和系统的技术体系
过程工程:解决软件质量问题,是软件开发和维护中的管理和支持能力
组件工程:使用可复用构件组装完成,提高开发效率和质量,降低成本和目的
软件工程知识体系
软件工程是解决问题的工具和技术,不一定要使用最新最牛的技术,只要能满足客户实际需求便可
软件工程知识体系
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/ima
ges/20230724024159.png?origin_url=.%5Cassent%5C%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E7%9F%A5%E8%AF%86%E4%BD%93%E7%B3%BB.png&pos_id=img-vq1Crf0n-1717341964795)
软件工程知识体系各主题之间的关联
软件工程 VS 计算机科学
软件工程 | 计算机科学 | |
---|---|---|
目标 | 在时间、资源、人员这3个主要限制条件下构建满足用户需求的软件系统 | 探索正确的计算和建模方法,从而改进计算方法本身 |
产品 | 软件(比如办公包和编译器) | 算法 |
进度与时间表 | 软件项目都有特定的进度与时间表 | 研究项目一般不具有设置进度与时间表 |
关注点 | 软件工程关注如何为用户实现价值 | 软件理论关注的是软件本身运行的原理,比如时间复杂度、空间复杂度和算法的正确性 |
变化程度 | 随着技术和用户需求的不断变化,软件开发人员必须时刻调整自己的开发以适应当前的需求,同时软件工程本身也处于不断的发展中 | 对于某一种特定问题的正确解决方法将永远不会改变 |
需要的其他知识 | 相关领域的知识 | 数学 |
对软件工程的误解
管理方的误解:
-
我们已经有了一本关于软件市场的标准和过程的书,这还不能让我们学习到需要的知识吗?
相比最新的大型主机,工作站和PC,这会使我们在做高质量软件开发时花费更多时间
-
如果我们项目进度落后了,可以加入更多程序员赶进度?
软件开发的机制和手工业不一样。在一个延迟了的软件项目加入新的开发人员只会让它延迟更多
- 如果我们将软件项目外包给第三方,我们就轻松了,让那个公司去完成它吧。
如果种组织管理方不懂得如何从内部管理和控制软件项目,即使将项目外包也无济于事
客户方的误解:
- 对目标的一般陈述就足以开始补充,我们可以今后再补充细节。
前期糟糕的项目需求定义,是导致软件失败的主要原因
项目需求的确在不断变化,但变化所产生的影响根据变化提出的时间不同而不同
开发人员的误解:
- 一旦我们编程完毕并成功运行,我们的工作就结束了。
“越早开始写代码,我们就会花费越长时间去完成它”。工业数据显示,软件开发60%~80%的精力耗费在软件首次提交给用户以后。
- 当我的程序运行之前,我没有办法评估它的质量。
一个最有效的软件质量保证机制应当在项目的正式开始启动时——可以通过技术报告体现
- 唯一可以交付的工作成果是一个成功运行的项目程序
一个可以运行的程序只是软件结构的一部分,它还包含了许多其他因素
-
软件工程会让我们去创建大量不必要的文档,并且总是使我们的进度放慢。
软件工程不只是创建文档,而是创建质量。更好的质量减少返工的概率。更少返工会让项目更早交付。所有的文档都是提高团队沟通和质量是必须的
软件工程的职业道德规范
- 诚信:工程师们应当对他们的雇主和顾客时刻保持诚信而无论之前是否达成关于诚信的协议
- 能力:工程师们不应该虚夸他们的能力水平。他们不应该关于接受一份超出自己能力范围的工作
- 知识产权:工程师们应该了解当地知识产权法律法规,如专利权、版权等。他们应该小心确保雇主和客户的知识产权受到了保护
- 滥用计算机:软件工程师不以他们的工作职责为由滥用别人的电脑。滥用计算机的范围很广,从极小(在雇主的机器上玩游戏)到极其严重的(传播病毒)
软件工程生命周期
概念:软件产品或软件系统从设计、投入使用到被淘汰的全过程
可行性研究:”能不能做“
-
四要素:经济、技术、环境、人员
- 经济:成本-收益、短期收益-长期收益(成本估算:每行代码的成本*行数)
- 技术:功能是否能实现,功能实现周期(最重要)
- 环境:市场、政策
- 市场:技术成熟(风险低,收益低),技术未成熟(风险高,收益高)
- 政策:法律是否允许
- 人员:人员充足
- 四类人:老大、核心技术人员、一般技术人员、外交
-
可行性研究步骤
- 明确系统目标
- 分析系统
- 设计系统
- 获取并比较方案
- 撰写文档
-
项目开发计划:开发计划主要是管理性的文档,对于人员,系统,环境,配置…进行说明
需求分析:一共三步骤,客户需求、需求记录、需求文档
软件设计
-
概要设计
-
详细设计
-
分类:框架设计、模块设计、算法设计、界面设计
编程:版本工具、编程工具、文档编写…
测试:测试工具
维护:修改错误,增加新功能,费用(60%-70%)
新生命周期:平面生命周期(迭代循环)
软件过程
软件过程:是在工作产品构建过程中,所需要完成的工作活动、动作和任务的集合
- 活动:主要实现广泛的目标,与应用领域、项目大小、结果复杂性或实施软件工程的重要程度没有直接关系,如:沟通、策划
- 动作:包含了主要工作产品生产过程中的一系列任务,如:体系结构设计
- 任务:关注小而明确的目标,能够产生实际产品,如:模块设计
- 研发高质量软件从0到1的过程,并规定了各个阶段(生命周期)
开发过程
- 核心过程:业务建模(需求分析三阶段)、软件设计、编程、测试、部署
- 开发子过程:软件设计、软件测试、软件研发、后期维护…
- 管理子过程:项目规划、需求管理、项目监控…
提高软件过程效率:过程规范化
软件过程模型:是软件开发全部过程、活动和任务的结构框架。它能直观表达软件开发全过程,明确规定要完成的主要活动、任务和开发策略。
软件过程评估
能力成熟度模型:CMM(Capability Maturity Model)
- 是迄今为止学术界和工业界公认的有关软件工程和管理实践和最好的软件过程评估模型
- 为评估软件组织和生产提供了标准
- 为提高软件组织的生产过程指明了方向
软件过程评估五个阶段
- 初始级:有能力的人和个人英雄主义
- 可重复级:基本项目管理
- 已定义级:过程标准化
- 量化管理级:量化管理
- 优化级:持续的过程改进
软件工程生命周期模型
- 瀑布模型:层层递增(整体开发模型、需要反复的测试,适用于大项目)
- 原型模型:从需求雏形,客户查验,一步步完善(简化了瀑布模型的需求分析),降低需求不明确的风险
- 增量模型:多个子模块,层层递增(非整体开发模型,瀑布模型、原型模型的结合、组件化开发),降低需求变化的风险
- 螺旋模型:层与层之间,可以同时进行(瀑布模型、原型模型、增量模型的结合,再加上风险分析)
- 敏捷模型:编程大于文档
- 组合模型:实际开发中,可根据需求,同时使用多个模型
瀑布模型
瀑布模型:规定了各项软件工程活动,以及它们自上而下,项目衔接的固定次序,如同瀑布流水逐级下落
- 软件开发过程与软件生命周期一致
- 也称经典生命周期模型
- 线性模型
- 阶段间具有顺序和依赖性
- 编码在软件的中后期,证明了推迟实现的观点
- 是一种使用广泛,以文档为驱动的模型
- 每个阶段都有与其相关联的里程碑和可交付产品
- 每个阶段结束前完成文档审查,及早改正错误
- 一直被用来规范软件开发活动
- 很多其他模型都是在瀑布模型基础上改进
实际瀑布模型
- 当后面阶段发现前面阶段的错误,则沿反馈线返回并修正
- 对软件的维护,则反馈相对应的阶段
瀑布模型的缺点
- 增加工作量:各阶段的划分完全固定,阶段的划分完全固定,阶段之间产生大量的文档,极大地增加了工作量
- 早期错误发现晚: 早期的错误可能要等到开发后期的测试才能发现,进而带来严重的后果
- 开发风险大:由于开发模型是线性的,用户只能等到整个过程末期才能见到开发成果,从而增加了开发的风险
- 不适应需求变化:不能反映实际开发方式,软件开发需要迭代;无法适应需求不能明确和需求的变化带来的影响
瀑布模型的使用场合
系统需求明确且稳定、技术成熟、工程管理严格的场合,如军工、航天、医疗。
V模型:瀑布模型的变种,每个测试都验证对应的设计或分析,当某个测试发现问题,就从对应的设计或分析开始从头设计或分析,如:系统测试发现问题,就从概要设计-详细设计-编码-单元测试-系统测试
原型模型
原型模型
- 也称原型化模型、快速原型模型
- 一个部分开发的产品,使客户和开发人员能够对计划开发的系统的相关方面进行检查
- 举例:图书借阅系统:主要界面,智能家居信息监控和电器控制
原型化的目的
- 明确并完善需求,如:演示原型
- 研究技术选择方案,如:技术验证原型
原型结果
- 抛弃原型
- 吧原型发展成最终产品
原型模型的两个阶段
因为原型构建处于系统开发之前,为了满足软件进度要求,所以要快,因此原型模型又称快速原型模型
原型模型的优缺点
优点:
- 减少需求不明确带来的风险
缺点:
- 构造原型采用的技术和工具不一定主流
- 快速建立起来的系统加上连续的修改可能导致原型质量底下
- 设计者在质量和原型中进行折中
- 客户意识不到一些质量问题
原型模型的使用场合
- 客户定义一个总体目标集,但是他们并不清楚系统的具体输入输出;或开发者不确定算法的效率、软件与操作系统是否兼容以及客户与计算机交互的方式
- 此时,原型模型是很好的选择
增量模型
增量模型
-
增量:满足用户需求的一个子集,能够完成一定功能、小而可用的软件
-
举例:文字处理软件:创建文本、组织文本、格式化文本
- 第一次发:创建文本
- 第二次发:创建文本、组织文本
- 第三次发:创建文本、组织文本、格式化文本
增量模型2
- 项目初期对需求不明确使用
- 由于后面增量无法集成,所以风险较大
增量的方式
- 增量方式:(创建文本)-增加新功能-(创建文本、组织文本)
- 迭代方式:(创建文本、组织文本)-改进功能-(创建文本、组织文本)
- 实际中,常常是两种方式结合
增量模型的特点
- 增量模型是一种非整体开发的模型,是一种进化式的开发过程
- 增量模型从部分需求出发,先建立一个不完整的系统,通过测试原型这个系统取得经验和反馈,进一步使系统扩充和完善
- 如此反复进行,直至软件人员和用户对所设计的软件系统满意为止
- 增量模型结合了原型模型的基本要素和迭代的特征,采用了基于时间的线性序列,每个线性序列都会输出该软件的一个“增量”
- 每个增量的开发可用瀑布或快速原型模型
增量模型的优缺点
优点:
- 增量概念的引入,不需要提供完整的需求,只要一个增量出现,开发可以进行
- 软件能够更早投入市场
- 在项目的初始阶段不需要投入太多的人力资源
- 产品逐步交付,软件开发能够较好地适应需求的变化
- 能够看到软件中间产品,提出改进意见,减少返工,降低低开发风险
- 开放式体系结构,便于集成和维护。
缺点:
- 每个增量必须提供一些系统功能,这使得开发者很难根据客户需求给出大小合适的增量
- 软件必须具备开放式体系结构(困难)
- 易退化成边做边改的方式,使软件过程控制失去整体性
增量模型的使用场合
适用于软件开发需要可能发生变化、具有较大风险、或者希望尽早进入市场的项目
螺旋模型
螺旋模型
- 软件开发普遍存在风险
- 交付的产品用户不满意
- 产品不能按时交付
- 开发成本超过预算
- 产品开发期间关键开发人员离职
- 产品投入市场前竞争对手发布功能相近价格更低产品
- 把开发活动和风险管理结合起来控制风险
- 开发过程分成若干次迭代,每次迭代代表开发的一个阶段,对应模型中一条环线
- 每次迭代分成四个方面的活动,对应笛卡尔坐标的四个象限:
- 确定本阶段目标,选定实施方案,弄清项目开发的限制条件
- 评估所选方案,通过构造原型和风险分析识别和消除风险
- 实施软件开发和验证
- 评价本阶段的工作成果,提出修正建议,并计划下一阶段工作
- 模型结合了瀑布模型和原型模型的特点
螺旋模型的优缺点
优点:
- 螺旋模型强调原型的可扩充性和可修改性,原型的进化贯穿整个软件生命周期,这将有助于目标软件的适应能力,支持用户需求的动态变化
- 原型可看作可执行的需求规格说明,易于为用户和开发人员共同理解,还可作为继续开发的基础,并为用户参与所有关键决策提供了方便
- 螺旋模型为项目管理人员及时调整管理决策提供了方便,进而可降低开发方向
缺点:
- 如果每次迭代的效率不高,致使迭代次数过多,将会增加成本并推迟交付时间
- 使用该模型需要有相当丰富的风险评估经验和专门知识,要求开发队伍水平较高,否则会带来更大风险
螺旋模型的使用场合
- 适用于需求不明确或者需求可能发生变化的大型复杂的软件系统
- 支持面向过程、面向对象等多种软件开发方法,具有广阔前景的模型
喷泉模型
喷泉模型
- 喷泉模型是以用户需求为动力,以对象为驱动的模型,主要描述面向对象的软件开发过程
- 软件开发早期定义对象,整个开发过程充实和扩充对象
- 各个阶段使用统一的概念和表示方法,生命周期各阶段的无缝连接
- 开发步骤多次反复迭代
喷泉模型的优缺点
优点:
喷泉模型的各个阶段没有明显的界限,开发人员可以同步进行开发,可以提高软件项目开发效率,节省开发时间,适应于面向对象的软件开发过程
缺点:
- 由于喷泉模型在各个开发阶段是重叠的,在开发过程中需要大量的开发人员,因此不利于项目管理
- 喷泉模型要求严格管理文档,使得审核的难度加大,尤其是面对可能随时加入的各种信息、需求于资料的情况
喷泉模型的使用场合
适用于面向对象开发
现代软件过程模型
基于构建的开发模型
现代软件过程模型-基于构建的开发模型
- Component-based development model
- 近年来得到广泛应用,改变大型软件开发方式
- 考虑的焦点是集成,而非实现
- 构建/组件(Component)
- 系统化模块化的、可更换的部分
- 实现特定的功能
- 对实现进行封装,暴露一组接口
- 例如:动态连接库(.dll),浏览器插件
基于构件的开发模型
- 需求分析
- 与其他过程模型相同
- 构件分析
- 根据需求搜索构件
- 如果没有完全匹配的构件,则需要修改构件或者修改需求
- 系统设计
- 与其他过程模型不同
- 考虑重用和集成
- 如果没有可重用的构件,则设计新软件
- 开发集成
- 将构件集成到系统中
- 开发新软件
基于构件的开发模型的优缺点
优点:
- 软件复用思想
- 降低开发成本和风险,加快开发进度,提高软件质量
缺点:
- 模型复杂
- 商业构件不能修改,会导致修改需求,进而导致系统不能完全符合客户需求
- 无法完全控制所开发系统的演化
- 项目划分的好坏直接影响项目结果的好坏
基于构件的开发模型的使用场合
适用于系统之间有共性的情况
Rational统一过程模型
现代软件过程模型-Rational统一过程模型
-
Rational Unified Process - RUP
-
由Rational公司(现已被IBM收购)推出的完整且完美的软件工程方法
-
获得广泛适用
-
基于面向对象方法学
-
适用统一建模语言UML(Unified Modeling Language)
-
从3个视角描述软件开发过程
- 动态视角:随时间变化的各个阶段
- 静态视角:所进行的活动
- 实践视角:可采用的良好实践建议
实践视角:6条最佳实践
-
迭代式开发
- 需求变更不可避免
- 每次迭代产生一个可交付版本,用户反馈,减少风险
- 根据客户的轻重缓急来规划增量,先开发和交付优先级最高的增量
-
管理需求
- 采用用例分析来捕获需求,由用例驱动设计和实现
- 对需求机器变更进行管理
用例名称 浏览商品 参与者 普通用户 前置条件 用户已成功登录系统 主要流程 1. 用户进入系统首页。
2. 用户浏览各类商品目录,可以通过搜索、分类等方式查找商品。
3. 用户点击特定商品,查看商品详情。
4. 用户可以查看商品的图片、价格、描述等信息。
5. 用户可以选择添加商品到购物车。备选流程 - 如果用户输入的搜索关键词无效,系统显示无搜索结果。
- 如果用户查看商品详情时出现错误,系统显示错误信息并提示用户稍后再试。后置条件 用户可以继续浏览其他商品或进行下单操作。 -
基于构件体系结构
- 采用基于构件的体系结构
- 提高软件复用率
-
可视化建模
- 使用统一建模语言(UML)对系统进行可视化建模
-
验证软件质量
- 软件质量评估贯穿整个开发过程的所有活动
- 全体成员参与
-
控制软件变更
- 描述如何控制和跟踪软件的变更
Rational统一过程模型
- 初始:项目计划、评估风险
- 精华:设计系统的体系结构、制定项目计划、确定资源需求
- 构建:开发出所有组件和应用程序,集成并进行详尽测试
- 产品化:将产品移交给用户
统一过程的静态结构
- 以工作的内容为组织方式,表现了软件开发的工作流程
- 6个核心工程工作流:
- 业务建模
- 需求
- 分析设计
- 实现
- 测试
- 部署
- 3个核心支持工作流:
- 项目管理
- 配置与变更管理
- 环境
统一过程的动态结构
- 以时间为组织方式,表现了软件开发的4个阶段
- 先启:估算项目的成本和效益,确定项目的规模、功能和架构,估计和安排项目的进度
- 精化:建立软件系统的架构,如建立用例模型、静态模型、动态模型和实现模型
- 构建:通过一系列的迭代过程,增量式地构建和实现用例
- 产品化:试用产品并改正试用中发现的错误,以及制作铲平的最终版本、安装产品、完善优化手册并培训用户等
敏捷开发过程模型
敏捷宣言
17名反叛性的软件开发人员,在美国雪鸟城提出4条价值观和12条原则
敏捷宣言的价值观
我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人。由此我们建立了如下价值观:
个体和互动高于流程和工具
工作的软件高于详尽的文档
客户合作高于合同谈判
响应变化高于遵循计划
也就是说,尽管右项有一定的价值,我们更重视左项的价值。
敏捷宣言遵循的12条原则
- 我们最重要的目标,是通过持续不断地及早交付有价值的软件使客户满意。
- 欣然面对需求变化,即使在开发后期也一样。为了客户的竞争优势,敏捷过程掌控变化。
- 经常地交付可工作的软件,相隔几星期或一两个月,倾向于采取较短的周期。
- 业务人员和开发人员必须相互合作,项目中的每一天都不例外。
- 激发个体的斗志,以他们为核心搭建项目。提供所需的环境和支援,辅以信任,从而达成目标。
- 不论团队内外,传递信息效果最好效率也最高的方式是面对面的交谈。
- 可以工作的软件是首要的进度度量标准。(跟踪项目进度)
- 敏捷过程倡导可持续开发。责任人、开发人员和用户要能够共同维持其步调稳定延续。
- 坚持不懈地追求技术卓越和良好设计,敏捷能力由此增强。
- 以简洁为本,它是极力减少不必要工作量的艺术。
- 最好的架构、需求和设计出自自组织团队。
- 团队定期地反思如何能提高成效,并依此调整自身的举止表现。
极限编程
- eXtreme Prigramming - XP
- 把好的开发实践运用到极致
极限编程的有效实践
- 增量式开发:不需要事先进行详细的架构设计,而是再迭代周期中不断细化架构
- 小版本短周期交付:避免风险和调整优化
- 结对编程
- 代码集体所有:整个团队共同拥有和维护
- 开放的工作空间:便于沟通交互
- 可持续的开发速度:<40小时/周,连续加班不超过两种
- 简单的设计
- 测试驱动开发:先写测试用例,再开发
- 持续集成:保持开发速度,避免一次集成的噩梦
- 重构:改进代码质量而不引进新问题
- 及时调整计划:要根据项目的进展来调整计划
- 客户作为开发团队成员:客户及时反馈,提高软件质量和开发效率
敏捷开发的优缺点
优点:
- 快速响应变化和不确定性
- 可持续开发速度
- 适应商业竞争环境下的有限资源和有限时间
缺点:
- 测试驱动开发可能导致通过测试但非用户期望
- 重构而不降低质量困难
敏捷开发使用场合
- 适用于需求模糊且经常改变的场合
- 适合商业竞争环境下的项目
选择软件过程模型
- 前期需求明确的情况下,尽量采用瀑布模型
- 用户无系统使用经验,需求分析人员技能不足的情况下,尽量借助原型模型
- 不确定因素很多,很多东西无法提前计划的情况下,尽量采用增量模型或螺旋模型
- 需求不稳定的情况下,尽量采用增量模型
- 资金和成本无法一次到位的情况下,可采用增量模型
- 对于完成多个独立功能开发的情况,可在需求分析阶段就进行功能并行,每个功能内部都尽量遵循瀑布模型
- 全新系统的开发必须再总体设计完成后再开始增量或并行
- 编码人员经验较少的情况下,尽量不要采用敏捷或迭代模型
- 增量、迭代和原型可以综合使用,但每次增量或迭代都必须由明确的交付和出口原则
案例
案例1:医疗设备控制软件
- 案例分析:
- 需求明确且稳定
- 可靠性和安全性要求极高
- 对软件错误和故障的控制和跟踪能力
- 需要对软件开发过程严格控制
- 需要大量严格的文档
- 模型选择:瀑布模型
案例2:校园一卡通系统
- 案例分析:
- 包括若干相对独立的功能
- 系统具体需求不明确且会发生变化-系统需要具有可扩充性
- 用户需要熟悉和适应新的系统
- 项目复杂程度中等、有一定风险-产品和文档的再使用率较高
- 模型选择:增量模型
案例3:智能化小区
-
智能家庭
-
家居信息的实时和远程监视–家用电器的远程和自动控制
-
家庭安防报警和远程通知
-
-
智能小区
- 安防门禁、可视对讲等
- 物业管理
- 一卡通系统
- 缴费、包裹、公告、便民信息等发布到户
- 家政相关服务,如送水、送餐等
-
案例分析:
-
包括若干相对独立的业务管理功能
-
系统具体需求不明确且会发生变化
-
部分技术方案可行性不确定
-
系统需要具有可扩充性
-
用户需要熟悉和适应新的系统
-
项目复杂程度较大、风险较大-希望尽早投入市场
-
-
模型选择:原型化模型+增量模型
需求分析
需求分析&获取
需求分析:确定系统必须具有的功能和性能,系统要求的运行环境,并且预测系统发展的前景
修正需求错误的代价
需求获取
- 软件需求的来源
- 软件工程师手机软件需求的方法
需求的类型
- 功能性需求:描述系统应该做什么,即为用户和其他系统完成的功能、提供的服务
- 非功能性需求:必须遵守的标准,外部界面的细节,实现约束,质量属性等
需求获取来源:
- 用户目标、领域知识、投资者、运行环境、组织环境
需求获取技术:
- 采访、设定情景(用例)、原型、会议、观察商业过程和工作流
需求获取面临的挑战:
- 客户说不清需求:可以列出一系列功能给客户筛选
- 需求易变性:把核心建筑放在稳定需求上
- 问题的复杂性和对问题空间理解和不完备性与不一致性
- 需求分析员分析后与客户再次确认,若问题太复杂无法解决问题,设计原型,双方再次确认需求
需求获取经验:
- 尽可能地需求分析清楚哪些式稳定需求,哪些是易变的需求。以便在进行系统设计时,将软件的核心建筑在稳定的需求上,否则将会吃尽苦头
- 在合同中一定要说清楚“做什么”和“不做什么”
需求诱导十原则
- 倾听
- 有准备的沟通
- 需要有人推动
- 最好当面沟通
- 记录所有决定
- 保持通力的协作
- 聚焦并协调话题
- 采用图形表示
- 继续前进原则
- 谈判双赢原则
需求分析的过程
- 需求确认:需求获取-需求提炼-需求描述-需求验证
- 需求更变
需求确认
需求获取
- 上一讲
需求提炼
需求提炼:对应用问题及环境的理解和分析,为问题涉及的信息、功能及系统行为建立模型。将用户需求精确化、完全化,最终形成下一步的需求规格说明书
- 需求提炼(需求分析)的核心在于建立分析模型
- 需求提炼(需求分析)采用多种形式描述需求,通过建立需求的多种视图,揭示出一些更深的问题
- 需求提炼(需求分析)还包括与客户的交流以澄清某些易混淆的问题,并明确哪些需求更为重要,其摸底是确保所有风险承担者尽早地对项目达成共识并对将来的产品有个相同而清晰的认识
需求分析模型
需求描述
软件需求规格说明书:SRS,是对待开发系统的行为的完整描述。它包含了功能性需求和非功能性需求
- 需求分析工作完成的一个基本标志是形成一份我真的、规格的需求规格说明书
- 需求规格说明书的编制是为了使用户和软件开发者双方对该软件的初始规定有一个共同的理解,使之成为整个开发工作的基础
需求验证
需求验证的重要性:如果在后续的开发或当系统投入使用时才发现需求文档中的错误,就会导致更大代价的返工。由需求问题而对系统做更变的成本比修改涉及或代码错误的成本要大的多。
-
假设需求阶段引入1个错误需求,设计时对者需求需要510条设计实现,1设计需要510条程序,1条程序需要3~5中测试组合测试。
-
则100元的修改成本会上升到50000元
需求验证的工作
对需求文档执行一下类型的检查:
- 有效性检查:检查不同用户使用不同功能的有效性
- 一致性检查:在文档中,需求之间不应该冲突
- 完备性检查:需求文档应该包括所有用户想要的功能和约束
- 现实性检查:检查保证能利用现有技术实现需求
需求验证的技术
- 需求评审:分析员、设计员、测试员、用户参与的正式或非正式的评审,要有严格的评审程序,要有会议记录,开发组根据需求说明并重审
- 利用原型检验系统是否符合用户的真正需求
- 对每个需求编写概念性的测试用例
- 编写用户手册。用浅显易懂的语言描述用户可见的功能
- 自动的一致性分析。可用CASE工具检验需求模型的一致性
需求变更
需求变更处理流程
需求分析的任务
- 建立分析模型:准确地定义未来系统的目标,确定为了满足用户的需求系统必须做什么
- 面向过程分析模型
- 面向对象分析模型
- 编写需求说明:用《需求规格说明书》规范的形式准确地表达用户的需求
需求规格文档编制
沟通活动通用任务集
- 识别主要客户和共利益者
- 与主要客户会谈“上下文无关问题”,以确定
- 业务需求和商业价值
- 最终用户的特性\需要
- 需要的用户可见输出
- 业务约束:各种方面的限制,如:预算、时间…
- 写一页项目范围的说明
- 评审范围说明,并应客户要求做出相应修改
- 与客户/最终用户进行协作,确定:
- 常用标准式记录客户可见的使用场景
- 输入和输出
- 重要的软件特性、功能和行为
- 客户定义的商业风险
- 描述场景、输入/输出、特性以及风险
- 与客户细化场景、输入/输出、特性/功能以及风险
- 与每个用户场景、特性、功能和行为分配客户定义的优先级
- 回顾搜集的所有信息并修订
- 为计划活动做准备
软件需求规格说明的原则
- 从现实中分离功能,即描述要“做什么”而不是“怎么实现”
- 要求使用面向处理的规格说明语言(或称系统定义语言)
- 有助于准确地描述系统的功能和行为,而不是过于技术化的细节
- 如果被开发软件只是一个大系统中的一个元素,那么整个大系统也包括在规格说明的描述之中
- 以确保软件与其他组件的集成
- 规格说明必须包括系统运行环境
- 规格说明必须是一个认识模型
- 规格说明应该反映用户和利益相关者对系统的理解和期望,以确保软件满足用户的需求
- 规格说明必须是可操作的
- 能够指导开发人员进行软件的设计和实现,并能够被验证和测试。
- 规格说明必须容许不完备性并允许扩充
- 规格说明可能不是完全详尽的,应该容许在后续开发过程中进行扩充和修改,以满足新的需求和变化
- 规格说明必须局部化和松散耦合
- 我们可以将复杂的系统拆分为更小、更简单的部分,每个部分都相对独立,易于理解和维护,有助于提高系统的可扩展性和适应性,同时降低了开发和维护的难度
软件需求规格说明的结构
IEEE标准为需求文档提出一下结构,组织内部结构可以基于此标准扩展:
-
引言
- 需求文档的目的
- 文档约定
- 预期的读者和阅读建议
- 产品范围
- 参考文献
-
综合描述
- 产品前景
- 产品功能与优先级
- 用户特征
- 运行环境
- 设计与实现上的限制
- 假设和依赖性
-
需求描述
- 功能需求
- 数据需求:与功能有关的数据定义和数据关系
- 性能需求:响应时间、容量要求、用户数等
- 外部接口:用户界面、软硬件接口、通信接口
- 设计约束:软件支持环境、报表、数据命名
- 软件质量属性(可维护性、可靠性、可移植性、可用性、安全性)
- 其他需求
-
附录(词汇表、分析模型、特定问题列表)
-
索引
需求分析的模型
- 面向过程分析模型:其基本思想是用系统工程的思想和工程化的方法,根据用户至上的原则,自始自终按照结构化、模块化、自顶向下地对系统进行分析与设计
- 面向对象分析:由5个层次(主题层、结构层、属性层和服务层)和5个活动(标识对象类、标识结构、定义主题、定义属性和定义服务)组成
分析模型描述工具
面向过程的需求分析 | 面向对象的需求分析 | |
---|---|---|
数据模型 | 实体-联系图(ERD) 数据字典(DD) | 类图、类关系图 |
功能模型 | 数据流图(DFD) | 用例图 |
行为模型 | 状态变迁图(STD) | 活动图、时序图、状态图 |
面向过程分析模型——结构化分析方法
- 面向数据流进行需求分析的方法
- 结构化分析适合于数据处理类型软件的需求分析
- 具体来说,结构化分析方法就是抽象模型的概念,按照软件内部数据传递、变换的关系,自顶向下逐层分解,知道找到满足功能要求的所有可实现的软件为止
面向过程的分析建模工具总览
数据流图中的主要图形元素
数据流图的层次结构
- 顶层流图:在多层数据流图中,顶层流图仅包含一个加工,它代表被开发系统。它的输入流是该系统的输入数据,输出流是系统所输出的数据
- 中间层流图:表示其对上层的细化。它的每一加工可能继续细化,形成子图
- 底层流图:是指其加工不需再做分解的数据流图,它处在最底层
功能模型-面向过程分析
功能模型
数据流图初步
加工
- 表示对数据的操作,如“处理选课单”、“产生发票”等
- 加工的编号,说明这个加工再层次分解的位置
- 加工命名注意事项
- 顶层的加工名就是整个系统项目的名字
- 尽量最好使用动宾词组,也可用主谓词组
- 不要使用空洞的动词,如:数据处理
外部实体
外部实体(数据源点/终点)
- 位于系统之外的信息提供者或使用者,称为外部实体。即存在于系统之外的人员或组织。如“学务科”等
- 说明数据输入的源点(数据源)或数据输出的终点(数据终点)
- 起到更好的理解作用,但不是系统中的事物
数据流
-
表示数据和数据流向,由一组固定成分的数据组成 如“选课单”由“学号、姓名、课程编号、课程名”等成分组成
-
数据流科从加工流向加工,也可在加工与数据存储或外部项之间流动;两个加工之间可有多股数据流
-
数据流的命名原则:
- 用名词,不要使用意义空洞的名词
- 尽量使用现实系统已有名字
-
数据流与数据加工之间的关系
-
画数据流时需注意的问题
-
不要把控制流作为数据流
如:下图读下张卡属于控制流,不应画出。
2.不要标出激发条件
-
数据存储
- 表示需要保存的数据流向,如“学生档案”、“课程设置”等
- 数据存储与加工的方向“读出”、“写入”
- 分层数据流程图中,数据存储一般局限在某一层或某几层
- 命名方法与数据流相似
数据流图常见几种错误
- 加工方没有输入输出
- 数据流向问题
数据流图进阶
-
绘制数据流图顶层
-
绘制数据流图第1层
-
绘制数据流图第2层
-
合成总体数据流图
-
检查与调整数据流图
示例:仓库管理与订货管理
- 某仓库业务的工作过程如下:企业职工填写领料单,经主管审查签名批准后,职工到仓库领取零件。
- 仓库保管员检查领料单是否符合审批手续,填写是否正确等,不正确的领料单退还职工,填写正确的领料单则办理领料手续,进行登记,修改库存量并给予零件。
- 某种零件的库存量低于事先规定的临界值时,登记需要采购零件的订货信息,为采购部门提供一张订货单。要求用计算机辅助领料工作和编制订货单。
绘制数据流图顶层
- 这个数据流图只是一个高层的系统逻辑模型,它反映了目标系统要实现的功能
绘制数据流图第1层
- 从输入端开始,根据仓库业务工作流程,画出数据流经的各加工框,逐步滑倒输出端,得到1层数据流图
绘制数据流图第2层
- 加细每一个加工框
合成总体数据流图
检查与调整数据流图
- 在分析过程中,由于每个人的经验和思路不尽相同,对数据流图的分解方案可以有多种形式,不唯一的。对每一张数据流图进行检查,如果太不均衡,就需要进行调整,尽量使分解后的各个软件子系统的复杂性得到均衡,便于今后设计工作的并行开展
数据流图的改进
数据流图改进的主要工作:
- 检查正确性:数据守恒、数据存储的使用、父图和子图的平衡
- 提高易理解性:简化加工之间的联系、注意分解的均匀、适当地命名
- 重新分解
检查正确性
-
数据守恒:数据不守恒的情况有两种:
- 某个加工输出的数据并无相应的数据来源,可能是某些数据流被遗漏了
- 一个加工的输入并没有用到,这不一定是错误。可与用户进一步讨论,是否属于多余的数据流
-
数据存储的使用
- 判断:是否存在“只读不写”或“只写不读”的数据存储(注意在所有的DFD中检查)
提高易理解性
- 简化加工之间的联系:应尽量减少加工之间输入输出数据流的数目。因为加工之间的数据越少,各个加工的功能就越相对独立
-
注意分解的均衡均匀:图中各个部分不均匀
-
一张图中,如果某些加工已是基本加工(细节),而另一些加工还可进一步分解成**三、层,则应考虑重新分解
-
适当地命名:名字的意义要明确,容易理解
- 如果难以为DFD图中的成分(数据流、加工等)命名,往往说明分解不当,可考虑重新分解
重新分解
- 在画第N层时意识到在第N-1层或第N-2层所犯的错误,词是就需要对第N-1层、第N-2层做重新分解
父子图合并
- 把需要重新分解的某张图的所有子图连接成一张
划分部分
- 把图分成几部分,使各部分的联系最少
重建父图
- 重新建立父图,即把第2)步所得的每一部分化成一个圆,而各部分之间的联系就是加工之间的界面
掏空子图
- 重新建立各张子图,这只需把第2)步所得的图按个部份的边界剪开即可
重新编号
- 为所有的加工重新命名和编号
检查数据流图的原则
- 数据流图上所有图形符号只限于前述四种基本图形元素
- 数据流图的主图必须包括前述四种基本元素,缺一不可
- 数据流图的主图上的数据必须封闭在外部实体之间
- 每个加工至少有一个输入数据流和一个输出数据流
- 在数据流图中,需按层给加工框编号。编号表明加工所处层次及上下层的亲子关系
- 规定任何一个数据流子图必须与它上一层的一个加工对应,两者的输入数据流和输出数据流必须一致。此即父图与子图的平衡
- 图上每个元素都必须有名字
- 数据流图中不可夹带控制流,箭头线上时名词,不是动词
- 初画时可以忽略琐碎的细节,以集中精力于主要数据流
编写数据字典
- 编写数据字典,写出系统需求规格说明书,提交审查,并编写测试验收计划、编写初步的用户手册概要
功能模型-面向对象分析
对象:在现实世界中有意义的、与所要解决的问题有关系的任何事务都可以作为对象,包括具体的物理实体和抽象、人为的概念、任何有明确边界和意义的东西
UML:一种可视化建模语言,能描述开发需要的各种视图,并以此为基础组建系统
面向对象的软件开发模型
- 数据模型(对象模型)
- 描述系统数据结构的对象模型,UML系统分析中会讲
- 行为模型(动态模型)
- 描述系统控制结构
- 功能模型
- 描述系统功能
用例图
用例图的基本图形符号
- 用例建模用于描述系统需求,把系统当作黑盒,从用户的角度,描述系统的场景。主要图形元素有以下几个:
- 参与者:是指外部用户或外部实体在系统中扮演的角色可以是一个人、一个计算机子系统、硬件设备或时间等角色
- 用例:对一组动作序列的描述,系统通过执行这一组动作序列为参与者产生一个可观察的结果。用例名往往用动宾结构命名
- 执行关联:参与者(Actor)执行用例(Use Case)之间的关系
用例建模的过程
- 确定谁会直接使用该系统。这些都是参与者(Actor)
- 选取其中一个作为参与者
- 定义参与者希望系统做什么,参与者希望系统做的每件事成为一个用例
- 对每件事来说,何时参与者会使用系统,通常发生什么,这就是用例的基本过程
- 描述该用例的基本过程
- 考虑一些可变情况,把他们创建为扩展用例
- 复审不同用例的描述,找出其中相同点,抽出相同点作为共同的用例
- 重复步骤2~7找出每一个用例
用例图初步
- 参与者:actor,是指系统以外的、需要使用系统或与系统交互的东西,包括人、设备、外部系统等
- 参与者的三种表现形式
如何确定参与者:在获取用例前首先要确定系统的参与者,开发人员可通过回答以下的问题来来寻找系统的参与者
- 谁将使用该系统的主要功能
- 谁将需要该系统的支持以完成其工作
- 谁将需要维护、管理该系统,以及保持系统处于工作状态
- 系统需要处理哪些硬件设备
- 与该系统交互的是什么系统
- 谁或什么系统对本系统产生的结果感兴趣
示例:饮料自动售货系统
参与者:顾客、供应商、收银员
用例:
-
用例的定义:对一组动作序列的描述,系统通过执行这一组动作序列为参与者产生一个可观察的结果
-
用例特征
-
说明了系统具有的一种行为模式
-
说明了一个参与者与系统执行的一个相关事件序列
-
提供了一种获取系统需求的方法
-
提供了一种最终的用户和领域专家进行沟通的方法
-
提供了一种测试系统的方法
-
-
图形表示
- 用椭圆形表示
用例的获取
怎么获取用例
- 参与者希望用户执行什么任务
- 参与者在系统中访问哪些信息(创建、储存、修改、删除)
- 需要将哪些外界信息提供给系统
- 需要将系统的什么事情告诉参与者
- 如何维护系统
系统和关联
系统:用于界定系统功能范围,描述该系统功能的用例都置于其中,而描述外部实体的参与则都至于其外,用矩形表示
关联:连接参与者的用例,表示参与者所代表的系统外部实体与该用例所描述的系统需求有关,用直线表示
初步的用例图
扩展后用例图
用例扩展后的用例图
用例图的进阶
用例之间的关系
- 关联(Association)
- 泛化(Inheritance)
- 包含(Include)
- 扩展(Extend)
关联:表示参与者与用例之间的通信,任何一方都可以发送或接收消息
- 箭头指向:指向消息接收方
- 备注:参与者可以参与多个用例,由此形成子系统
泛化:就是通常理解的继承关系,子用例和父用例相似,但表现出更特别的行为;子用例将继承父用例的所有结构、行为和关系。子用例可以使用父用例的一段行为;也可以重载它。父用例通常是抽象的。
用例之间的is a kind of关系,表示用例之间的场景共享;Actor之间的is a kind of关系,一般描述职责共享。
- 箭头指向:指向父用例
包含:包含关系用来把一个较复杂用例所表示的功能分解成较小的步骤。一个用例可以包含另外一个用例
- 箭头指向:指向分解出来的功能用例
扩展:扩展关系是指用例功能的延伸,相当于为基础用例提供一个附加功能。由一个用例的扩展点可以扩展出另一个用例
- 箭头指向:指向基础用例
包含、扩展的区别
- 在扩展关系中,一个基本用例执行时,可以执行、也可以不执行扩展用例部分
- 在包含关系,在执行基本用例时,一定会执行包含用例部分
关联、包含、扩展、泛化的区别
软件设计
软件设计
定义:软件设计定义为软件系统或组件的架构、构件、接口和其他特征的定义过程及该过程的结果
- 软件生命周期的一个活动
- 进行软件编码的基础
- 软件需求分析被转化为软件的内部结构
- 是连接用户需求和软件技术的桥梁
设计工程活动
- 软件架构设计:
- 描述软件的顶层架构和组织,划分不同的组件
- 软件详细设计:
- 详细描述各组件一边能够编码实现
- 注意:
- 软件设计主要分解设计D-design(Decomposition design)
- D-设计主要是关于如何将大型问题分解成小型问题的设计策略
- D-设计也有助于我们更好地组织代码和设计文档。
- 可以包括系统模式设计FP-design(Family Patten design)
- FP-设计是一种基于模式的设计策略。这种策略认为,许多问题都有共性,我们可以找出这些共性,将它们抽象成模式,然后在设计时使用这些模式。
- 在FP-设计中,我们通常会维护一个模式库,当我们遇到新的设计问题时,我们会首先查阅模式库,如果有,我们就可以直接使用这个模式,如果没有,我们就需要自己设计新的模式,并将新的模式添加到模式库中。
- FP-设计的优点是可以显著提高设计的效率,FP-设计也有助于我们提高设计的质量,因为模式库中的模式通常都是经过多次验证的,具有较高的可靠性。
- 软件设计主要分解设计D-design(Decomposition design)
设计模型
- 模型输入
- 软件需求的数据模型、功能模型和行为模型
- 设计技术
- 数据设计
- 架构设计
- 接口设计
- 组件设计
分析模型到设计模型的转换
设计质量
好的设计应该具有如下三个特点
- 设计必须实现在分析模型中包含素有明确要求,必须满足客户所期望的所有隐含要求
- 设计必须对编码人员、测试人员及后续的维护人员是可读可理解的
- 设计应提供该软件的完整视图,从实现的角度解决问题、功能及行为等各领域方面的问题
设计质量属性
- 功能性:功能完整、符合客户预期
- 易用性:软件好用、对用户友好
- 可靠性:软件不易出错、稳定
- 性能:软件响应时间、吞吐、运行流畅
- 可支持性:
- 包含三个属性:扩展性、适应性、可维护性
- 扩展性:软件添加、升级新功能是否方便
- 适应性:软件环境适应新的变化是否容易
- 可维护性:程序代码是否易懂,维护成本是否较小
设计指导原则
- 设计应该是一种架构:一开始设计大的框架不需要注意细节
- 设计应该是模块化:把大问题拆分为小问题
- 设计应该包含数据、体系结构、接口和组件各个方面
- 应该设计出系统所用的数据结构
- 应该设计出展现独立功能特性的各组件
- 应该设计出组件与外部环境连接的各接口
- 设计由软件需求分析过程中或的信息驱动,采用可重复使用的方法导出
- 设计应该采用周期的表示法
面向对象设计的八个概念
- 抽象
- 体系结构
- 设计模式
- 模块化
- 信息隐藏
- 功能独立
- 精华
- 重构
抽象
抽象:忽略具体的信息将不同事物看相同事物的过程
抽象机制:参数化、规范化
规范化抽象:
- 数据抽象:描述数据对象的冠名数据集合(门)
- 过程抽象:具有明确和有限功能的指令序列(开)
体系结构
体系结构:软件的整体结构和这种结构提供概念上完整性的方式
体系结构设计可以使用大量一种或多种模型表达:
- 结构模型
- 框架模型
- 动态模型
- 过程模型
- 功能模型
设计模式
设计模式:在给定上下文环境中一类共同问题的共同解决方案
微观结构:
- 实体模式
- 结构模式
- 行为模式
书籍推荐
《设计模式:可复用面向对象软件基础》
- 面向对象的设计中精选出23个设计模型
抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
模块化
模块化:软件被划分为命名和功能相对独立的多个组件(通常称为模块),通过这些组件的集成来满足问题的需求
软件的模块性:程序可被智能管理的单一属性
模块化的理论依据:基于人类解决问题的观测数据
模块化和软件成本
模块化设计标准
- 模块化的分解性:可分解为子问题,为了高内聚
- 模块化的组合性:组装可重用的组件,提高灵活
- 模块化的可理解性:可作为独立单元理解,通过封装使开发人员无需深入接口
- 模块化的连续性:需求小变化只影响单个模块,为了低耦合
- 模块化的保护:模块内异常只影响自身,确保系统的稳定性和安全性
信息隐藏
-
模块化基本问题
- 如何分解软件系统以达最佳的模块划分
-
信息隐藏原则
- 模块应该具有彼此相互隐藏的特性
-
特点
-
抽象有助于定义构成软件的过程(或信息)实体。
-
信息隐藏原则定义和隐藏了模块内的过程细节和模块内的本地数据结构。
-
功能独立
- 含义:每个模块只负责需求中特定的子功能,并且从程序结构的其他部分看,该模块具有简单的接口
- 好处
- 易于开发:功能被划分,接口被简化
- ·易于维护(和测试)︰次生影响有限,错误传递减少,模块重用
- 定性衡量标准
- 内聚性:模块的功能相对强度
- 耦合性:模块之间的相互依赖程度
- 模块独立性强=高内聚低耦合
精化
- 含义:逐步求精的过程
- 与抽象的关系
- 抽象使设计师确定过程和数据,但不局限于底层细节
- 精化有助于设计者在设计过程中揭示底层细节
重构
- 含义:不改变组件功能和行为条件下,简化组件设计(或代码)的一种重组技术
- 方法:检查现有设计的冗余情况、未使用的设计元素、无效或不必要的算法、较差的构建方式或不恰当的数据结构,或任何其他可被更改从而优化设计的问题
面向过程设计的四类设计概述
- 数据设计
- 架构设计
- 接口设计
- 组件设计
数据设计
-
含义:数据设计(有时也被称为数据架构)构建高层抽象(客户/用户的数据视图)的数据模型、信息模型
-
相关概念
-
数据建模:数据字典、E-R图、类图
-
数据结构:计算机存储、组织数据的方式
-
数据库:按照数据结构来组织、存储和管理数据的仓库
-
数据仓库:大规模的数据库,用于数据分析与挖掘
-
设计原则
- 应用于功能和行为系统分析的原则也应适用于数据设计:
- 对系统功能和行为的分析应该反映在数据设计中,确保数据结构和操作能够支持系统所需的功能和行为。
- 所有的数据结构及其对应的操作都应该确定:
- 在设计阶段,应该明确所有数据结构及其对应的操作,包括数据的存储方式、访问方式、更新方式等。这有助于确保系统的数据操作是完备和一致的。
- 建立数据字典并在数据定义和程序设计中应用:
- 数据字典是记录系统中所有数据项及其定义、属性、关系等信息的文档或工具。通过建立数据字典,并在数据定义和程序设计中应用,可以提高数据的一致性和可维护性。
- 低层次的数据设计应该推迟到设计的后期过程:
- 低层次的数据设计指的是具体的数据结构和存储实现细节,如数据库表设计等。这些设计应该推迟到设计的后期过程,首先应该关注于高层次的数据结构和操作的设计,以确保系统的整体架构和功能满足需求。
- 数据结构的表示应该只对直接使用数据结构中数据的模块可见:
- 这意味着数据结构的实现细节应该封装起来,只对直接需要使用数据结构中数据的模块可见。这有助于降低模块之间的耦合度,提高系统的灵活性和可维护性。
- 开发有用的数据结构及其对应操作的程序库:
- 为常见的数据结构和操作开发程序库,可以提高开发效率和代码重用性。这些程序库可以包括各种数据结构的实现,如栈、队列、链表等,以及对应的操作和算法。
- 软件设计和编程语言应该支持抽象数据类型的定义与实现:
- 抽象数据类型(ADT)是指一种数据模型,它定义了数据的抽象结构和操作,而不涉及具体的实现细节。软件设计和编程语言应该支持ADT的定义和实现,以提高系统的模块化和可扩展性,同时降低系统的复杂度和耦合度。
概念数据模型
E-R图
物理数据模型
UML类图
架构设计
- 系统需要执行的函数功能组件集(如数据库、计算模块)
- 数据库怎么设计
- 组件之间通信、协同和合作的连接器
- 增删改查
- 组件集成构成系统的约束
- 用已有的组件开发
- 设计人员通过分析系统组成部分的已知特性,理解其整体特性的语义模型分析
分类
- 数据中心架构
- 数据流体系架构
- 调用和返回架构
- 层次架构
- 面向对象架构
数据中心架构
数据流体系架构
调用和返回架构
层次架构
面向对象架构
组织与细化
两个基本问题
-
控制结构
- 在架构内部如何实现管理控制?
- 是否有不同的控制架构存在?
-
数据传递
- 组件之间如何进行数据传递?
- 数据流是否连续,或者传递给系统的数据对象是否零散?
部署设计
- 以部署环境创建开始,在整个生命周期阶段中处于逻辑设计和技术需求阶段
- 部署环境包含整个解决方案的逻辑架构和服务质量(QoS)需求
- 部署架构设计是一个反复迭代的过程,通常需要多次查看QoS要求和多次检查先前的设计,需要考虑了服务质量QoS需求的相互关系,平衡取舍相关问题成本以实现最佳解决方案,最终满足项目的业务目标
部署设计输出
-
部署架构
这一部分描述了系统或应用程序的部署架构,包括硬件设备、软件组件、网络配置等。它指导着如何将系统部署到目标环境中,以实现系统的功能和性能要求。
-
实施规范
实施规范是一组规则和标准,用于指导部署过程中的各项活动。这些规范可能涉及安全要求、性能要求、数据管理规定等,旨在确保部署过程的顺利进行,并符合相关的法律和标准。
-
实施计划
- 迁移计划:描述从当前系统或环境迁移到新系统或环境的步骤和时间表。
- 安装计划:指导安装和配置系统所需的软件和硬件设备的步骤和时间表。
- 用户管理计划:规划如何管理用户账户、权限和访问控制,以确保系统安全和合规性。
- 测试计划:描述测试活动的范围、方法和时间表,包括功能测试、性能测试、安全测试等。
- 滚动淘汰计划:规划如何逐步淘汰旧系统或版本,并切换到新系统或版本。
- 灾难恢复计划:定义灾难事件发生时的应急响应措施和恢复流程,以最小化系统中断和数据丢失。
- 操作计划(运行书):指导系统的日常运行和维护活动,包括监控、备份、更新等。
- 培训计划:规划用户和管理员的培训计划,以确保他们能够熟练地操作和管理系统。
部署设计方法
接口设计(含界面设计)
-
高效用户界面设计有三条重要原则:
- 允许用户操作控制(用户为中心,重点)
- 减少用户记忆负担
- 保持界面一致
-
环境分析确定了用户接口操作的物理结构和社会结构
-
推荐读物
《交互设计——超越人机交互》,电子工业出版社。 -
《设计心理学》,唐纳德﹒A﹒诺曼
《情感化设计》,唐纳德·A·诺曼 -
《可用性工程》,尼尔森
组件设计
面向过程的组件设计
- 函数与模块的设计
面向对象的组件设计
- 类与操作的设计
面向过程设计的四类设计方法
数据设计方法
数据库详细介绍
架构设计方法
结构化的总体设计方法
- 首先研究、分析和审查数据流图。从软件的需求规格说明中弄清数据流加工的过程,对
于发现的问题及时解决。 - 然后根据数据流图决定问题的类型。数据处理问题典型的类型有两种:变换型和事务型。
- 针对两种不同的类型分别进行分析处理。
- 由数据流图推导出系统的初始结构图。
- 利用一些启发式原则来改进系统的初始结构图,直到得到符合要求的结构图为止。
- 修改和补充数据词典。
系统架构图中的模块
- 传入模块:从下属模块取得数据,经过某些处理,再将其传送给上级模块。它传送的数据流叫做逻辑输入数据流。
- 传出模块:从上级模块获得数据,进行某些处理,再将其传送给下属模块。它传送的数据流叫做逻辑输出数据流。
- 变换模块:它从上级模块取得数据,进行特定的处理,转换成其它形式,再传送回上级模块。它加工的数据流叫做变换数据流。
- 协调模块:对所有下属模块进行协调和管理的模块。
变换型系统结构图
- 变换型数据处理问题的工作过程大致分为三步,即取得数据,变换数据和给出数据。
- 相应于取得数据、变换数据、给出数据,变换型系统结构图由输入、中心变换和输出等三部分组成。
事务型系统结构图
-
它接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元,然后给出结果。
-
在事务型系统结构图中,事务中心模块按所接受的事务的类型,选择某一事务处理模块执行。各事务处理模块并列。每个事务处理模块可能要调用若干个操作模块,而操作模块又可能调用若干个细节模块。
变换与事务分析
变换分析
- 重画数据流图(有错才重画)
- 区分有效(逻辑)输入、有效(逻辑)输出和中心变换部分
- 进行一级分解,设计上层模块
- 进行二级分解,设计输入、输出和中心变换部分的中、下层模块
二级分解
变换分析注意事项
- 深度遍历模块设计:
- 在选择模块设计的次序时,必须对一个模块的全部直接下属模块都设计完成之后,才能转向另一个模块的下层模块的设计。
- 耦合与内聚:
- 在设计下层模块时,应考虑模块的耦合和内聚问题,以提高初始结构图的质量。
- 使用“黑箱”技术:
- 在设计当前模块时,先把这个模块的所有下层模块定义成“黑箱”,在设计中利用它们时,暂时不考虑其内部结构和实现。在这一步定义好的“黑箱”,在下一步就可以对它们进行设计和加工。这样,又会导致更多的“黑箱”。最后,全部“黑箱”的内容和结构应完全被确定。
- 控制直接下属模块数:
- 在模块划分时,一个模块的直接下属模块一般在5个左右。如果直接下属模块超过10个,可设立中间层次。
- 停止模块功能分解的情况
- 模块不能再细分为明显的子任务;
- 分解成用户提供的模块或程序库的子程序;
- 模块的界面是输入/输出设备传送的信息;
- 模块不宜再分解得过小。
事务分析
- 在很多软件应用中,存在某种作业数据流,它可以引发一个或多个处理这些处理能够完成该作业要求的功能。这种数据流就叫做事务。
- 与变换分析一样,事务分析也是从分析数据流图开始,自顶向下,逐步分解,建立系统结构图。
事务分析过程
-
识别事务源
- 利用数据流图和数据词典,从问题定义和需求分析的结果中,找出各种需要处理的事务。通常,事务来自物理输入装置,有时,设计人员还必须区别系统的输入、中心加工和输出中产生的事务。
-
规定适当的事务型结构
- 在确定了该数据流图具有事务型特征之后,根据模块划分理论,建立适当的事务型结构。
-
识别各种事务和它们定义的操作
- 从同定义和需求分析中找出的事务及其媒f作所必需的全部信息,对于系统内部产生的事务。必须仔细地定义它们的操作。
-
注意利用公用模块
- 在事务分析的过程中,如果不同事务的一些中问模块可由具有类似的语法和语义的若千个低层模块组成,则可以把这些低层模块构造成公用模块。
-
事务处理模块
- 对每一事务,或对联系密切的一组事务,建立一个事务处理模块;如果发现在系统中有类似的事务,可以把它们组成一个事务处理模块。
-
操作模块
- 对事务处理模块规定它们全部的下层操作模块
-
细节模块
- 对操作模块规定它们的全部细节模块
混合结构分析
-
变换分析是软件系统结构设计的主要方法。
一般,一个大型的软件系统是变换型结构和事务型结构的混合结构。
-
所以,我们通常利用以变换分析为主、事务分析为辅的方式进行软件结构设计。
接口设计方法
- 《Java编程思想》(Thinking in Java)- Bruce Eckel
- 《Effective Java》- Joshua Bloch
- 《Java设计模式》(Design Patterns: Elements of Reusable Object-Ori
界面设计
- 《交互设计——超越人机交互》,电子工业出版社。
- 《设计心理学》,唐纳德﹒A﹒诺曼
《情感化设计》,唐纳德·A·诺曼 - 《可用性工程》,尼尔森
组件设计方法
组件级设计:组件级设计也称为过程设计、详细设计,位于数据设计、体系结构设计和接口设计完成之后
任何程序总可以用三种结构化的构成元素来设计和实现
- 顺序:任何算法规约中的核心处理步骤
- 条件:允许根据逻辑情况选择处理的方式
- 重复:提供了循环
详细设计工具可以分为以下三类:
- 图形设计符号:流程图、盒图等
- 表格设计符号:决策表等
- 程序设计语言:PDL等
流程图
流程图:利用各种方块图形、线条及箭头等符号来表达解决问题的步骤及进行的顺序;是算法的一种表示方式。
标准作业流程:(SOP, Standard operating procedure)
- 企业界常用的一种作业方法,其目的在使每一项作业流程均能清楚呈现,任何人只要看到流程图,便能一目了然,有助于相关作业人员对整体工作流程的掌握。
程序流程图:(program flow chart)
- 表示程序中的处理过程。
制作流程图的优点
- 所有流程一目了然,工作人员能掌握全局。
- 更换人手时,按图索骥,容易上手。
- 所有流程在绘制时,很容易发现疏失之处,可适时予以调整更正,使各项作业更为严谨。
流程图的基本符号
流程图的基本结构
-
顺序结构(Sequence)
-
选择结构(Selection)
- 二元选择结构(基本结构)
- 多重选择结构
-
循环结构(lteration)
-
while-do结构
-
do-while结构
-
二元选择结构
多重选择结构
while-do结构
do-while结构
流程图绘制原则
- 各项步骤有选择或决策结果,如“可/否”、“通过/不通过"
或其他相对文字时,请检查校正流程是否
有遗漏,以避免悬而未决的状况。 - 流程图符号绘制排列顺序,为由上而下,由左而右。
- 处理程序可用阿拉伯数字,从1开始,依处理程序排列顺序编号,并以文字依处理程序功能命名。
- 相同流程图符号宜大小一致。
- 路径符号宜避免互相交叉。
-
同一路径符号的指示箭头应只有一个。
-
开始符号在流程图中只能出现一次,但结束符号则不限。若流程图能一目了然,则开始符号和结束符号可省略。
-
选择结构与重复结构的选择或决策条件,文字叙述应简明清晰,路径加注“是”、“否”或其它相对性文字指示说明。
-
流程图中若有参考到其他已定义流程,可使用已定义处理程序符号,不必重复绘制。
-
流程图若一页绘制不下,可以使用分级分页绘制方式,并在处理程序编号上表示其级别。
其他组件设计方法
盒图
盒图示例
- 优点
- 易观察作用域
- 结构缺失易发现
- 缺点
- 结构复杂
- 修改困难
PDL
-
PDL是一种用于描述功能模块的算法设计和加工细节的语言。称为程序设计语言。它是一种伪码。
-
伪码的语法规则分为“外语法”和“内语法”。
-
PDL具有严格的关键字外语法,用于定义控制结构和数据结构,同时它的表示实际操作和条件的内语法又是灵活自由的,可使用自然语言的词汇。
PDL示例:拼词检查程序
决策表
- 判定表用于表示程序的静态逻辑
- 在判定表中的条件部分给出所有的两分支判断的列表,动作部分给出相应的处理
- 要求将程序流程图中的多分支判断都改成两分支判断
无多分支流程图-决策表
面向对象的架构设计
面向对象设计活动
- 系统架构设计
- 用户界面设计
- 用例设计
- 数据库设计
- 类设计
架构设计的目的
架构设计的目的:
- 是要勾画出系统的总体结构,这项工作由经验丰富的架构设计师主持完
- 输入:用例模型、分析模型。
- 输出:物理结构、子系统及其接口、概要的设计类。
面向对象架构设计
构造系统的物理模型
- 首先用UML的配置图(部署图)描述系统的物理架构
- 将需求分析阶段捕获的系统功能分配到这些物理节点上。
- 配置图上可以显示计算节点的拓扑结构、硬件设备配置、通信路径、各个节点上运行的系统软件配置、应用软件配置。
- 一个图书馆信息管理系统的物理模型如后图所示。
图书管理系统架构UML部署图
设计子系统
- 对于一个复杂的软件系统来说,将其分解成若干个子系统,子系统内还可以继续划分子系统或包,这种自顶向下、逐步细化的组织结构非常符合人类分析问题的思路。
- 每个子系统与其它子系统之间应该定义接口,在接口上说明交互信息,注意这时还不要描述子系统的内部实现。
- 可用UML组件图表示。
划分各个子系统的方式
- 按照功能划分,将相似的功能组织在一个子系统中;
- 按照系统的物理布局划分,将在同一个物理区域内的软件组织为一个子系统;
- 按照软件层次划分子系统,软件层次通常可划分为用户界面层、专用软件层、通用软件层、中间层和数据层,见后图。
定义子系统之间的关系
划分子系统后,要确定子系统之间的关系。子系统之间的关系:
- “请求–服务”关系,“请求”子系统调用“服务”子系统,“服务”子系统完成一些服务,并且将结果返回给“请求”子系统。
- 平等关系,每个子系统都可以调用其它子系统。
- 如果子系统的内容相互有关联,就应该定义它们之间的依赖关系。在设计时,相关的子系统之间应该定义接口,依赖关系应该指向接口而不要指向子系统的内容。
注意:
如果两个子系统之间的关系过于密切,则说明一个子系统的变化会导致另一个子系统变化,这种子系统理解和维护都会比较困难。
解决子系统之间关系过于密切的办法基本上有两个:
- 重新划分子系统,这种方法比较简单,将子系统的粒度减少,或者重新规划子系统的内容,将相互依赖的元素划归到同一个子系统之中;
- 定义子系统的接口,将依赖关系定义到接口上;
定义子系统的接口
- 每个子系统的接口上定义了若干操作,体现了子系统的功能,而功能的具体实现方法应该是隐藏的,其他子系统只能通过接口间接地享受这个子系统提供的服务,不能直接操作它。
非功能需求设计
- 分析阶段定义了整个系统的非功能需求,在设计阶段要研究这些需求,设计出可行的方案。
- 非功能需求包括:
- 系统的安全性、错误监测和故障恢复、可移植性和通用性等等。
- 具有共性的非功能需求一般设计在中间层和通用应用层,目的是充分利用已有构件,减少重新开发的工作量。
面向对象的用例设计与类设计
进一步细化用例
- 根据分析阶段产生的高层类图和交互图,由用例设计师研究已有的类,将它们分配到相应的用例中。
- 检查每个用例功能,依靠当前的类能否实现,同时检查每个用例的特殊需求是否有合适的类来实现。
- 细化每个用例的类图,描述实现用例的类及其类之间的相互关系,其中的通用类和关键类可用粗线框区分,这些类将作为项目经理检查项目时的重点。
类
- 类是包含信息和影响信息行为的逻辑元素。类的符号是由三个格子的长方形组成,有时下面两个格子可以省略。
- 最顶部的格子包含类的名字,类的命名应尽量用应用领域中的术语,有明确的含义,以利于开发人员与用户的理解和交流。中间的格子说明类的属性。最下面的格子是类的操作行为。
类间关系
分析类图:需求分析阶段
如何找实体类?
- 实体类用于对必须存储的信息和相关行为进行建模
- 实体类源于业务模型中的业务实体,但出于对系统结构的优化,可以在后续的过程中被分拆、合并
如何找边界类?
- 参与者与用例之间应当建立边界类
- 用例与用例之间如果有交互,应当为其建立边界类
- 如果用例与系统边界之外的非人对象有交互,应当为其建立边界类
- 在相关联的业务对象有明显的独立性要求,即它们可能在各自的领域内发展和变化,但又希望互不影响时,也应当为它们建立边界类
如何找控制类?
- 控制类来源于对用例场景中动词的分析和定义
- 控制类主要起到协调对象的作用,例如从边界类通过控制类访问实体类,或者实体类通过控制类访问另一个实体类。
- 如果用例场景中的行为在执行步骤、执行要求或者执行结果上具有类似的特征,应当合并或抽取超类
细化用例
- 第1步:通过扫描用例中所有的交互图识别参与用例解决方案的类。在设计阶段完善类、属性和方法。例如,每个用例至少应该有一个控制
类,它通常没有属性而只有方法,它本身不完成什么具体的功能,只是起协调和控制作用。- 每个类的方法都可以通过分析交互图得到,一般地检查所有的交互图发送给某个类的所有消息,这表明了该类必须定义的方法。例如“借
书控制”类向“读者”类发送“检查读者(读者编号)”消息,那么“检查读者”就作为“读者”类应该提供的方法。
- 每个类的方法都可以通过分析交互图得到,一般地检查所有的交互图发送给某个类的所有消息,这表明了该类必须定义的方法。例如“借
- 第2步:添加属性的类型、方法的参数类型和方法的返回类型。
- 第3步:添加类之间的关系,包括关联、依赖、继承等。
借书类图
详细设计一个类
定义类的属性
- 用所选择的编程语言定义每个类的属性。类的属性反映类的特性,通常属性是被封装在类的内部,不允许外部对象访问。
- 注意点:
- 分析阶段和概要设计阶段定义的一个类属性在详细设计时可能要被分解为多个,减小属性的表示粒度有利于实现和重用。但是一个类的属性如果太多,则应该检查一下,看能否分离出一个新的类。
- 如果一个类因为其属性的原因变得复杂而难于理解,那么就将一些属性分离出来形成一个新的类。
- 通常不同的编程语言提供的数据类型有很大差别,确定类的属性时要用编程语言来约束可用的属性类型。定义属性类型时尽可能使用已有的类型,太多的自定义类型会降低系统的可维护性和可理解性等性能指标。
- 类的属性结构要坚持简单的原则,尽可能不使用复杂的数据结构。
定义类的操作
- 由构件工程师为每个类的方法设计必须实现的操作,并用自然语言或伪代码描述操作的实现算法。一个类可能被应用在多个用例中,由于它在不同用例中担当的角色不同,所以设计时要求详细周到。
- 注意事项:
- 分析类的每个职责的具体含义,从中找出类应该具备的操作。
- 阅读类的非功能需求说明,添加一些必须的操作。
- 确定类的接口应该提供的操作。这关系到设计的质量,特别是系统的稳定性,所以确定类接口操作要特别小心。
- 逐个检查类在每个用例实现中是否合适,补充一些必须的操作。
- 设计时不仅要考虑到系统正常运行的情况,还要考虑一些特殊情况,如中断/错误处理等。
定义类之间的关系
- 设置基数:一个类的实例与另一个类的实例之间的联系。在图书馆信息管理系统中,“图书”类和“读者"类关联,如果需求说明中有“一位读者可借图书的数量为0至10本”,那么它们之间的基数为1∶0.10.。
- 使用关联类:可以放置与关联相关的属性。例如“图书”类和“读者”类,如果要反映读者的借书情况,该如何处理呢?可以创建一个关联类,这个类中的属性是“借书日期”。
UML顺序图
- 顺序图是强调消息时间顺序的交互图。
- 顺序图描述了对象之间传送消息的时间顺序,用来表示用例中的行为顺序。
- 顺序图将交互关系表示为一个二维图。即在图形上,顺序图是一张表,其中显示的对象沿横轴排列,从左到右分布在图的顶部;而消息则沿纵轴按时间顺序排序。创建顺序图时,以能够使图尽量简洁为依据布局。
购买小车的顺序图示例
什么时候会用到顺序图
类的操作会用到
顺序图的组成
顺序图包含4个元素:
- 对象(Object)
- 生命线(Lifeline)
- 消息(Message)
- 激活(Activation)
对象
- 顺序图中对象的符号和对象图中对象所用的符号一样。
- 将对象置于顺序图的顶部意味着在交互开始的时候对象就已经存在了,如果对象的位置不在顶部,那么表示对象是在交互的过程中被创建的。
- 参与者和对象按照从左到右的顺序排列
一般最多两个参与者,他们分列两端。启动这 - 个用例的参与者往往排在最左边;接收消息的参与者则排在最右端;
- 对象从左到右按照重要性排列或按照消息先后顺序排列
生命线
- 每个对象都有自己的生命线,用来表示在该用例中一个对象在一段时间内的存在生命线使用
- 垂直的虚线表示
- 如果对象生命期结束,则用注销符号表示
- 对象默认的位置在图顶部,表示对象在交互之前已经存在
- 如果是在交互过程中由另外的对象所创建,则位于图的中间某处。
激活
- 激活表示该对象被占用以完成某个任务,去激活指的则是对象处于空闲状态、在等待消息。
- 在UML中,为了表示对象是激活的,可以将该对象的生命线拓宽成为矩形。其中的矩形称为激活条(期)或控制期,对象就是在激活条的顶部被激活的,对象在完成自己的工作后被去激活。
激活期
- 当一条消息被传递给对象的时候,它会触发该对象的某个行为,这时就说该对象被激活了。
- 在UML中,激活用一个在生命线上的细长矩形框表示。
- 矩形本身被称为对象的激活期或控制期,对象就是在激活期顶端被激活的。
- 激活期说明对象正在执行某个动作。当动作完成后,伴随着一个消息箭头离开对象的生命线,此时对象的一个激活期也宣告结束。
消息
面向对象方法中,消息是对象间交互信息的主要方式。
- 在任何一个软件系统中,对象都不是孤立存在的,它们之间通过消息进行通信。
- 消息是用来说明顺序图中不同活动对象之间的通信。因此,消息可以激发某个操作、创建或撤销某个对象。
结构化程序设计中,模块间传递信息的方式主要是过程(或函数)调用。
- 对象A向对象B发送消息,可以简单地理解为对象A调用对象B的一个操作(operation)
在顺序图中,消息是由从一个对象的生命线指向另一个对象的生命线的直线箭头来表示的,箭头上面还可以表明要发送的消息名及序号。
- 顺序图中消息编号可显示,也可不显示。协作图中必须显示。
顺序图中,尽力保持消息的顺序是从左到右排列的。在各对象之间,消息的次序由它们在垂直轴上的相对位置决定。
- 一个顺序图的消息流开始于左上方,消息2的位置比消息1低,这意味着消息2的顺序比消息1要迟。因为西方的阅读习惯是从左到右.
在UML中,消息使用箭头来表示,箭头的类型表示了消息的类型。
进行顺序图建模时,所用到的消息主要包括以下几种类型:
- 简单消息(Simple Message)
- 同步消息(Synchronous Message)
- 异步消息(Asynchronous Message)
- 反身消息(Message to Self)
- 返回消息(Return Message)
同步消息
- 同步消息最常见的情况是调用,即消息发送者对象在它的一个操作执行时调用接收者对象的一个操作,此时消息名称通常就是被调用的操作名称。
- 当消息被处理完后,可以回送一个简单消息,或者是隐含的返回。
异步消息
- 异步消息表示发送消息的对象不用等待回应的返回消息,即可开始另一个活动。
- 异步消息在某种程度上规定了发送方和接收方的责任,即发送方只负责将消息发送到接收方,至于接收方如何响应,发送方则不需要知道。对接收方来说,在接收到消息后它既可以对消息进行处理,也可以什么都不做。
返回消息
- 返回消息是顺序图的一个可选择部分,它表示控制流从过程调用的返回。
- 返回消息一般可以缺省,隐含表示每一个调用都有一个配对的调用返回。
- 是否使用返回消息依赖于建模的具体/抽象程度。如果需要较好的具体化,返回消息是有用的;否则,主动消息就足够了。
对象的创建和撤销
对象的创建有两种情况:
- 顺序图中的对象的默认位置是在图的顶部,如果对象在这个位置上,那么说明在发送消息时,该对象就已经存
- 如果对象是在执行的过程中创建的,那么它的位置应该处在图的中间部分。
对象的创建有两种方法:
对象的撤销有两种情况:
- 在处理新创建的对象,或顺序图中的其他对象时,都可以发送“destroy"消息来撤销对象。
- 要想说明某个对象被撤销,需要在被撤销对象的生命线末端放一个“×"符号进行标识。
顺序图和用例
- 顺序图的主要用途之一是用来为某个用例的泛化功能提供其所缺乏的解释,即把用例表达的要求转化为更进一步的精细表达。
- 用例常常被细化为一个或多个顺序图。
- 顺序图除了在设计新系统方面的用途之外,它还能用来记录一个存在于系统的对象现在如何交互。
登录用例:
- 用户将用户名和密码提交给LoginAction
- 由LoginAction调用UserManager
- UserManager到用户数据库User Server中查找用户对象并返回
- 由UserManager判断用户名是否为空、密码是否正确
- 然后将User对象返回
- 返回后台登录主界面。
顺序图建模
- 对系统动态行为建模的过程中,当强调按时间展开信息的传送时,一般使用顺序图建模技术
- 一个单独的顺序图只能显示一个控制流。
- 一般情况下,一个完整的控制流是非常复杂的,要描述它需要创建很多交互图(包括顺序图和协作图),一些图是主要的,另一些图用来描述可选择的路径和一些例外,再用一个包对它们进行统一的管理。
参考策略
- 设置交互的语境
- 这些语境可以是系统、子系统、类、用例和协作的一个脚本。
- 对象从左到右
- 识别对象在交互语境中所扮演的角色,根据对象的重要性及相互关系,将其从左至右放置在顺序图的顶部。
- 设置每个对象的生命线
- 通常情况下,对象存在于整个交互过程中,但它们也可以在交互过程中创建和撤销。对于这类对象,在适当的时刻设置它们的生命线,并用适当的构造型消息显示地说明它们的创建和撤销。
- 消息自上而下
- 从引发某个消息的信息开始,在生命线之间画出从顶到底依次展开的消息,显示每个消息的内容
标识。
- 从引发某个消息的信息开始,在生命线之间画出从顶到底依次展开的消息,显示每个消息的内容
- 设置对象的激活期
- 可视化消息的嵌套或可视化实际计算发生时的时间点。
- 时间和空间约束
- 如果需要设置时间或空间的约束,可以为每个消息附上合适的时间和空间约束。
- 前置和后置条件
- 如果需要形式化的说明某控制流,可以为每个消息附上前置和后置条件。
建立顺序图的步骤
-
确定交互的范围
-
识别参与交互的对象和活动者
-
设置对象生命线开始和结束
-
设置消息
-
细化消息
存款用例的顺序图
借阅图书用例的顺序图
借阅图书的过程为:
- 图书管理员选择菜单项“借阅图书”,弹出BorrowDialog对话框
- 图书管理员在该对话框中输入借阅者信息
- 然后由系统查询数据库,以验证该借阅者的合法性
- 若借阅者合法,则再由图书管理员输入所要借阅的图书信息,系统记录并保存该借阅信息
面向对象的设计原则
- 面向对象设计强调定义软件对象,并且使这些软件对象相互协作来满足用户需求。
- 面向对象分析和设计的界限是模糊的,从面向对象分析到面向对象设计是一个逐渐扩充模型的过程。分析的结果通过细化直接生成设计结果,在设计过程中逐步加深对需求的理解,从而进一步完善需求分析的结果。
- 分析和设计活动是一个反复迭代的过程。
- 面向对象方法学在概念和表示方法上的一致性,保证了各个开发阶段之间的平滑性。
面向对象的设计的四个层次
- 确定系统的总体结构和风格,构造系统的物理模型,将系统划分成不同的子系统。
- 中层设计:对每个用例进行设计,规划实现用例功能的关键类,确定类之间的关系。
- 进行底层设计:对每个类进行详细设计,设计类的属性和操作,优化类之间的关系。
- 补充实现非功能性需求所需要的类。
注意
面向对象设计与结构化设计的过程和方法完全不同,要设计出高质量的软件系统,记住:
- 对接口进行设计
- 发现变化并且封装它
- 先考虑聚合然后考虑继承
高内聚
类内聚——设计类的原则是一个类的属性和操作全部都是完成某个任务所必须的,其中不包括无用的属性和操作。
- 例如设计一个平衡二叉树类,该类的目的就是要解决平衡二叉树的访问,其中所有的属性和操作都与解决这个问题相关,其他无关的属性和操作在这里都是垃圾,应该清除。
低耦合
-
在面向对象设计中,耦合主要指不同对象之间相互关联的程度。如果一个对象过多地依赖于其它对象来完成自己的工作,则不仅使该对象的可理解性下降,而且还会增加测试、修改的难度,同时降低了类的可重用性和可移植性。
-
对象不可能是完全孤立的,当两个对象必须相互联系时,应该通过类的公共接口实现耦合,不应该依赖于类的具体实现细节。
-
耦合的方式:
- 交互耦合:如果对象之间的耦合是通过消息连接来实现的,则这种耦合就是交互耦合。在设计时应该尽量减少对象之间发送的消息数和消息中的参数个数,降低消息连接的复杂程度。
- 继承耦合:继承耦合是一般化类与特殊化类之间的一种关联形式,设计时应该适当使用这种耦合。在设计时要特别认真分析一般化类与特殊化类之间继承关系,如果抽象层次不合理,可能会造成对特殊化类的修改影响到一般化类,使得系统的稳定性降低。另外,在设计时特殊化类应该尽可能多地继承和使用一般化类的属性和服务,充分利用继承的优势。
可重用性
软件重用是从设计阶段开始的,所有的设计工作都是为了使系统完成预期的任务,为了提高工作效率、减少错误、降低成本,就要充分考虑软件元素的重用性。重用性有两个方面的含义:
- 尽量使用已有的类,包括开发环境提供的类库和已有的相似的类
- 如果确实需要创建新类,则在设计这些新类时考虑将来的可重用性。
设计一个可重用的软件比设计一个普通软件的代价要高,但是随着这些软件被重用次数的增加,分摊到它的设计和实现成本就会降低。
框架
框架是一组可用于不同应用的类的集合。框架中的类通常是一些抽象类并且相互有联系,可以通过继承的方式使用这些类。
- 例如,Java应用程序接口(API)就是一个成功的框架包,为众多的应用提供服务,但一个应用程序通常只需要其中的部分服务,可以采用继承或聚合的方式将应用包与框架包关联在一起来获得需要的服务。
一般不会直接去修改框架的类,而是通过继承或聚合为应用创建合适的GUI类。
程序设计
程序设计语言
引言
建筑工程中的砌砖:是工程的基础,是设计实现的具体实施。
概念
程序设计语言:是人与计算机通信的最基本工具。语法+语义+语用
- 开发人员的思路和解决问题的方式
- 代码的可理解性、可维护性
- 程序语言特性的影响
编码之前的一项重要工作就是选择一种适当的编程语言
特点
技术方面
-
需要复杂的数据结构:仔细衡量有哪些语言能提供这些复杂的数据结构描述
-
要求高性能及实时处理能力:选用适合于实时处理的语言,如C或汇编语言
-
要求许多输出报告或繁杂的文件处理:选用PowerBuilder、Delphi或SQL比较合适
-
程序设计语言基本成分分类
-
数据成分
- 指明该语言能接受的数据,如各种类型的变量、数组、指针、记录等
-
运算成分
- 指明该语言可执行的运算,如+,-,*、/
-
控制成分
- 顺序结构、条件选择结构和循环结构
-
传输成分
- 数据的传输方法,例如输入、输出函数
-
软件工程方面
- 详细设计
- 能够直接地翻译成程序代码
- 源程序的可移植性
- 应该严格遵守相应的标准编写程序代码
- 编译程序效率较高
- ·首先应该支持独立编译,纠错功能强,辅助程序员提高程序调试效率
- 应用代码生成工具
- 许多语言都有与它相应的编译程序、连接程序、调试程序、代码格式化程序、交叉编译程序、宏处理程序和标准子程序库等
- 可维护性
- 源程序的可读性、语言的文档化特性是影响可维护性的重要因素
分类
发展历程
选择要素
编程习惯
重要性
结构化程序设计原则
- 简单结构
- 尽量使用语言提供的基本控制结构,即顺序结构、选择结构和重复(循环)结构。
- 组合嵌套
- 复杂结构应该用基本控制结构组合或嵌套实现。
- —致性
- 语言中没有的控制结构,可用一段等价的程序段模拟,但要求该程序段在整个系统中应前后一致。
- 块机制
- 将程序组织成容易识别的块,每块只有一个入口和一个出口。
- GOTO语句
- 严格控制GOTO语句。c++的关键词,不要用会导致维护困难
程序设计风格
- 基本要求
- 程序结构清晰且简单易懂,单个函数的行数一般不要超过100行。
- 算法设计应该简单,代码要精简,避免出现垃圾程序。
- 尽量使用标准库函数(类方法)和公共函数(类方法)。
- 最好使用括号以避免二义性。
- 可读性要求
- 程序头,函数头说明;接口说明;子程序清单,有关数据的说明;模块位置;开发历史等
- 主要变量(结构、联合、类或对象):含义的注释。
- 应保持注释与代码完全一致。
- 处理过程的每个阶段和典型算法前都有相关注释说明,但是不要对每条语句注释。
- 正确性与容错性要求
- 程序格式清晰
- 一行只写一条语句,不要密密麻麻,分不出层次
- 显示程序的逻辑结构,利用空格、空行和缩进进行,缩进量一般为4个字节。
- 程序本身
- 语句力求简单、清晰,不要片面追求效率,程序编写得过于紧凑,使语句复杂化。
- 简单变量的运算速度比下标(数组)变量的运算要快
- 编程时尽可能使用已有的库函数。
- 尽量用公共过程或子程序代替具有独立功能的重复代码段。使用括号清晰地表达算术表达式和逻辑表达式的运算顺序。尽量使用三种基本控制结构编写程序,使用IF THEN ELSE结构实现分支;使用DO UNTIL或DO WHILE来实现循环。
避免采用过于复杂的条件测试,少用含有“否定”运算符的条件语句。
- 尽量用公共过程或子程序代替具有独立功能的重复代码段。使用括号清晰地表达算术表达式和逻辑表达式的运算顺序。尽量使用三种基本控制结构编写程序,使用IF THEN ELSE结构实现分支;使用DO UNTIL或DO WHILE来实现循环。
- 避免使用空的ELSE语句和IF THEN IF语句
- 避免使用ELSE GOTO和ELSE RETURN结构。
- 避免过多的循环嵌套和条件嵌套。
- 数据结构要有利于程序的简化。
- 模块功能尽可能单一化,模块间的耦合能够清晰可见。利用信息隐蔽确保每一个模块的独立性。
- 对递归定义的数据结构尽量使用递归过程。
- 尽量不要修补结构差的程序,而应重新设计和编码。
- 对太大的程序,要分块编写、测试,后再集成
- 数据说明
- 数据说明的先后次序规范化
- 简单变量类型说明、数组说明、公用数据块说明、文件说明
- 同一条说明语句中按如下顺序排列
- 整型量说明、实型量说明、字符量说明、逻辑量说明
- 每个类型说明中可可按字母顺序排列
- 例如:INTEGERcost, length,price, width
- 数据说明的先后次序规范化
- 正确性和容错性要求
- 对所有的用户输入,必须进行合法性和有效性检查。
- 程序首先是正确,其次是考虑优美和效率。
- 不要单独进行浮点数的比较。
- 改一个错误时可能产生新的错误,因此修改前首先考虑其影响。
- 单元测试也是编程的一部分,提交联调测试的程序必须通过单元测试。
- 所有变量在调用前必须被初始化。
- 单元测试时,必须针对类里的每一个public方法进行测试,测试其正确的输入,是否得到正确的输出;错误的输入是否有容错处理。
- 程序格式清晰
- 可移植性要求
- 应当尽量使用语言的标准部分,避免使用第三方提供的接口,以确保程序不受具体的运行环境影响,和平台无关。
- 对数据库的操作,使用符合语言规范的标准接口类例如JDBC,除非程序是运行于特定的环境下,并且有很高的性能优化方面的要求。
- 程序中涉及到的数据库定义和操纵语句,尽量使用标准SQL数据类型和SQL语句
- 输入和输出要求
- 任何程序都会有输入输出,输入输出的方式应当尽量方便用户的使用。在需求分析和设计阶段就应确定基本的输入输出风格,要避免因设计不当带来操作和理解的麻烦。
- 对所有的输入数据进行检验,从而识别错误的输入,以保证每个数据的有效性。√检查
- 输入项各种重要组合的合理性,必要时报告输入状态信息。
- 输入的步骤和操作尽可能简单,并且要保持简单的输入格式。√有些输入信息应提供缺省值。
- 输入一批数据时,最好使用输入结束标志,而不要由用户指定输入数据数目。
- 在以交互式方式进行输入时,要显示提示信息、选择项和取值范围,便于操作。同时,
- 在输入数据的过程和输入数据结束时,也要在屏幕上给出状态信息。
- 当程序设计语言对输入格式有严格要求时,应保持输入格式与输入语句的要求一致。√给所有的输出加上注解信息。
- 按照用户的要求设计输出报表格式。
- 重用性要求
- 可重复使用的、功能相对独立的算法或接口。应该考虑封装成公共的控件或类。
- 相对固定和独立的程序实现方式和过程,应考虑做成程序模板,增强对程序实现方式的复用
程序的效率
概念
程序的效率:程序的执行速度及程序所需占用的存储空间。
- 算法、存储、输入/输出
程序效率的几条准则
- 效率是一个性能要求,应当在需求分析阶段给出。软件效率以需求为准,不应以人力所及为准。
- 好的设计可以提高效率。
- 程序的效率与程序的简单性相关。
- 一般说来,任何对效率无重要改善,且对程序的简单性、可读性和正确性不利的程序设计方法都是不可取的。
效率的影响因素
算法:源程序的效率与详细设计阶段确定的算法的效率直接有关。在设计翻译转换代码,算法效率反映为程序的执行速度和存储容量的要求。
设计向程序转换过程中的指导原则
- 简化:在编程序前,尽可能化简有关的算术表达式和逻辑表达式;
检查 - 仔细:检查算法中的嵌套的循环,尽可能将某些语句或表达式移到循环外面;
- 选用:选用等效的高效率算法;
- 采用:采用“快速”的算术运算;尽量采用整数算术表达式和布尔表达式;
- 尽量:避免使用多维数组;尽量避免使用指针和复杂的表;不要混淆数据类避免刑8群兴美沃式中出现类型混杂;
存储器
大中型计算机系统,存储限制不是主要问题
内存分页功能的虚拟存储管理。效率与系统的分页功能相关。
结构化程序设计,将程序功能合理分块,模块(群)体积与页容量相匹配,减少调度。
在微型计算机系统,存储容量对软件设计和编码的制约很大。
选择可生成较短目标代码且存储压缩性能优良的编译程序,甚至汇编程序。
提高存储器效率的关键是程序的简单性。
输入输出
面向人(操作员)的输入/输出
- 方便、简单地录入输入数据
- 直观、一目了然地了解输出信息
面向设备的输入/输出
- 输入/输出的请求应当最小化;
- 所有的操作,安排适当的缓冲区,以减少交换。
- 对辅助存储,选择尽量简单,可接受的存取方法
- 对辅助存储的输入/输出,应当成块传送;
- 对终端或打印机的输入/输出,应考虑设备特性,尽可能改善输入/输出的质量和速度;
- 任何不易理解的,对改善输入/输出效果关系不大的措施都是不可取的;
- 任何不易理解的所谓“超高效”的输入/输出是毫无价值的;
编码管理
版本管理的意义
目的:标识、控制和追踪软件开发和实施过程中产生的各种软件产品版本。
适用范围:适用于软件源代码、产品版本的管理通常内部使用,不对外发布。
作用:主要是开发者自己对产品进行测试,检查产品是否存在缺陷、错误,验证产品功能与说明书、用户手册是否一致。
常见软件版本
常见版本命名规则
- 目前主要有三种版本控制工具:CVS、SVN、Git.
面向对象程序设计
- 含义:面向对象程序设计是以建立模型体现出来的抽象思维过程和面向对象的方法。
- 主要概念:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。
- 方法:选择程序设计语言、类的实现、方法的实现、用户接口的实现等
- 语言:C++、JAVA、VB、VC++、C#
编码策略
- 自顶向下:从模块的最高层次逐步向下编码
- 复合模式:
- 自顶向下与自底向上相结合
- 可以先总体界面、交互,到基础模块
- 自底向上:从类继承的底层开始向上编码
- 线程模式:
- 线程:执行关键功能的最小模块集合
- 先线程,级关键构建,后其他模块
编码规范
编码规范:一个团队、企业给出的内部开发最佳做法的建议、最好方式的推荐和经验总结。
- 使开发人员有据可依
- 代码易读
- 易于定位错误、变更管理
- 易于测试和维护
软件测试
软件质量保证相关概念
质量相关
- 定义:审查产品相关的各个方面质量的过程
- 内容:
- 元素:过程控制、作业管理等
- 能力:知识、技能、经验和资历等
- 软要素:人员廉正、文化、团队合作等
- 目标:建立体系并确保体系按要求运作,以提供内外部的信任
软件质量相关
- 含义:系统监测和评估工程的各个方面,最大限度提高质量最低标准
- 内容:原料、文档、产品和组件,以及涉及产品的管理、生产和检测过程等质量管理
- 原则:
- 适合用途:该产品应符合预期的目的
- 一次成功:错误应该被淘汰
质量成本:追求质量过程或在履行质量有关活动中引起的费用以及质量不佳引起的下游费用等所有费用。
- 预防成本:
- 质量计划和协调等管理活动
- 需求、设计模型开发成本
- 测试计划的成本
- 相关培训成本
- 评估成本:
- 技术审查成本数据
- 收集和度量估算
- 成本测试和调试成本
- 失效成本:
- 内部失效成本:交付前发现错误的成本–返工、修复故障模式分析
- 外部失效成本:交付后发现缺陷的成本–投诉、退换、帮助作业支持、保修
软件质量:明确表示是否符合功能和性能要求,明确地记载开发标准和所有
专业开发软件的期望的隐性特点
- 符合明确规定的功能和性能要求
- 符合明确的开发标准
- 符合所有软件开发专业的共性、隐性标准,如易用性、可维护性等
软件质量保证(SQA):遵照一定的软件生产标准、过程和步骤对软件质量进行评估的活动。
- 审查:评审既定标准是否得到遵守。如IEEE、ISO、GB/T等
- 监督:对比文档中描述的执行和实际操作步骤,确保执行过程采取适当步骤和操作方式
- 审计:确保开发过程使用了恰当的质量控制措施,以符合相应的标准或过程。
软件评审
软件评审:一个过程或会议期间进行的软件产品的审核,由项目人员、管理人员,用户、客户、用户代表或其他有关各方对一个软件产品进行评论或批准
软件评审常见形式
- 同行评审:同行评估产品技术的含量和质量
- 管理评审:管理人员代表评估当前工作,决定后续安排
- 审计评审:外部人员评估软件产品的规范性、标准化程度、合同履行情况等
软件可靠性
软件可靠性:是指在给定时间内,特定环境下软件无错运行的概率
过程模型
软件测试策略含义
软件测试策略:
- 软件测试策略为软件开发人员、质量保证组织、和客户提供了一个路线图
- 规定了测试的主要步骤
- 为保证可行性,须考虑人力成本、时间和资源
- 故应结合:测试计划、测试用例设计、测试执行、测试结果数据的收集与分析
- 要求:
- 灵活性:有足够的可塑性来应付所有的大软件系统
- 严格:保证对项目进程进行合理的计划和跟踪管理
软件测试策略V模型
- V模型非常明确地标明了测试过程中存在的不同级别,并且清楚地描述了这些测试阶段和开发过程期间各阶段对应关系。
单元测试:主要目的是验证软件模块是否按详细设计的规格说明正确运行。
集成测试:主要目的是检查多个模块间是否按概要设计说明的方式协同工作。
系统测试:主要目的是验证整个系统是否满足需求规格说明。
验收测试:从用户的角度检查系统是否满足合同中定义的需求,以及以确认产品是否能符合业务上的需要。
回归测试
WHY
- 测试中,如有缺陷修正、功能增加,变化的部分必须再测试。
- 软件的修改可能会导致新的缺陷及其他问题。为防止,需再测试。
WHAT
- 回归测试:指有选择地重新测试系统或其组件,以验证对软件的修改没有导致不希望出现的影响,以及系统或组件仍然符合其指定的需求。
BY:回归测试应该尽量采用自动化测试。
回归测试可以在所有的测试级别执行,并应用于功能和非功能测试中。
范围
- 缺陷再测试:重新运行所有发现故障的测试,而新的软件版本已经修正了这些故障。
- 功能改变的测试:测试所有修改或修正过的程序部分。
- 新功能测试:测试所有新集成的程序。
- 完全回归测试:测试整个系统。
软件测试策略注意事项
- 在着手开始测试之前,要对产品的需求进行量化。
- 明确指出测试目标。
- 为每类用户建立描述交互场景的用例。
- 建立一个强调“快速循环测试”的测试计划。
- 设计一个能够测试自身是否“强壮”的软件。
- 在进行测试之前,对软件进行有效的正式技术审核。
- 使用正式技术审核来评估测试策略和测试用例本身。
- 为测试过程建立一种持续的改进方法。
软件测试策略基本步骤
-
单元测试、集成测试和系统测试
-
计划与准备阶段
- 制定计划
- 编写与评审测试用例
- 编写测试脚本和准备测试环境
-
执行阶段
-
搭建测试环境
-
构造测试数据
-
执行测试并记录问题
-
确认问题
-
撰写测试报告
-
-
返工与回归测试阶段
-
单元测试
单元测试概念
- 单元内涵:不同环境含义不同
- 面向过程:函数、过程等。
- 面向对象:类、类中成员函数等。
- 单元测试:针对软件设计的最小单位一程序模块,进行正确性检验的测试工作。
- 测试方法:单元测试需要从程序的内部结构出发设计测试用例。多个模块可以平行地独立进行单元测试。
- 主要依据:详细设计
进入与退出条件
- 进入条件
- 被测代码编译链接通过
- 被测代码静态检查工具检查通过
- 已完成至少一轮代码检视或走读
- 单元测试用例的检视通过
- 单元测试代码写完并通过检测
- 退出条件
- 所用测试用例执行通过
- 单元测试覆盖率达到预定要求
- 单元测试未被执行的代码进行正式审查。
测试内容
- 模块
- 模块接口
- 数据流测试:
- 调用本模块的输入参数是否正确;
- 本模块调用子模块时输入给子模块的参数是否正确;
- 全局量的定义在各模块中是否一致;
- 内外存交换测试:
- 文件属性是否正确;
- OPEN与CLOSE语句是否正确;
- 缓冲区容量与记录长度是否匹配;
- 在进行读写操作之前是否打开了文件;
- 在结束文件处理时是否关闭了文件;
- 正文书写/输入错误,
- 1/О错误是否检查并做了处理。
- 数据流测试:
- 局部数据结构
- 不正确或不一致的数据类型说明
- 使用尚未赋值或尚未初始化的变量
- 错误的初始值或错误的缺省值
- 变量名拼写错或书写错误
- 不一致的数据类型
- 全局数据对模块的影响
- 独立路径
- 重要路径:对模块中重要的执行路径进行测试。
- 计算控制流:查找由于错误的计算、不正确的比较或不正常的控制流而导致的错诣
- 基本循环:对基本执行路径和循环进行测试可以发现大量的路径错误。
- 错误处理
- 出错的描述是否难以理解
- 出错的描述是否能够对错误定位
- 显示的错误与实际的错误是否相符
- 对错误条件的处理正确与否
- 在对错误进行处理之前,错误条件是否已经引起系统的干预等
- 边界条件
- 流边界:注意数据流、控制流中刚好等于、大于或小于确定的比较值时出错的可能性。对这些地方要仔细地选择测试用例,加以测试。
- 关键路径:如果对模块运行时间有要求的话,还要专门进行关键路径测试,以确定最坏情况下和平均意义下影响模块运行时间的因素。
- 模块接口
测试用例设计
- 依据:详细设计说明书和源程序清单
- 了解:该模块的IO条件和模块的逻辑结构
- 手段:主:白盒测试,辅:黑盒测试
- 结果:合理和不合理输入的鉴别和相应比较预计和实际结果
测试环境搭建
-
模块并非独立程序,进行测试时,要考虑它和外界的联系,需用一些辅助模块去做相应模拟
-
驱动模块:用来模拟被测试模块的上一级模块,相当于被测模块的主程序。
-
桩模块:模拟被测试的模块所调用的模块,而不是软件产品的组成的部分。
集成测试
集成测试概念
- 含义:
- 将软件集成起来后进行测试。
- 别名:子系统测试、组装测试、部件测试等。
- 目的:
- 检查诸如两个模块单独运行正常,但集成起来运行可能出现问题的情况。
- 主要方法:
- 自顶向下的集成方法
- 自底向上的集成方法
- SMOKE方法
自顶向下的集成方法
- 基本思想:该集成方式将模块按系统程序结构,沿控制层次自顶向下进行集成。
- 深度优先、广度优先
- 优点:可以较早地验证主要的控制和判断点。按深度方向,可首先实现和验证一个完整的软件功能。
- 缺点:是桩模块的开发量较大
- 适用:
- 控制结构清晰稳定;
- 高层接口变化较小;
- 底层接口未定义或经常可能被修改;
- 接口控制组件具有较大的技术风险,需要尽早被验证;
- 希望尽早能看到产品的系统功能行为。
广度优先方式
深度优先方式
自底向上的集成方法
- 基本思想:从软件结构最底层的模块开始,按照接口依赖关系逐层向上集成以进行测试。
- 优点:每个模块调用其他底层模块都已经测试,不需要桩模块;
- 缺点:必须编写驱动模块;缺陷的隔离和定位不如自顶向下。
- 适用:
- 底层接口比较稳定;
- 高层接口变化比较频繁;
- 底层组件较早被完成。
应用注意事项
- 实际工作中,常综合使用:自底向上、自顶向下
- 如:按进度选择优先测试已经完成的模块
- lf:被测模块所调用的模块未完成,用自顶向下,打桩测试。
- lf:被测模块的上层模块未完成,用自底向上,模拟根模块。
SMOKE方法
- 基本思想:
- 将已经转换为代码的软件构件集成为构造(build)。
- 一个构造包括所有的数据文件、库、可复用的模块以及实现一个或多个产品功能所需的工程化构件。
- 目标:
- 设计暴露影响构造正确地完成其功能的错误的测试。
- 以发现极有可能造成项目延迟的业务阻塞错误。
- 方法:
- 两种方法:自顶向下,自底向上,均可。
- 每天将该构造与其他构造,及整个软件产品集成,冒烟测试。
- SMOKE
- Start: 启动系统或应用程序。
- Main: 测试主要功能,即系统最重要的功能是否正常工作。
- Obtain: 获取结果,确保系统可以正确地提供所需的输出或响应。
- Keep Going: 确保系统可以持续运行,而不会出现意外的崩溃或错误。
- Exit: 退出系统或应用程序。
测试用例设计
- 通过性测试:等价类划分法场景分析法状态图法等
- 失效性测试:·边界值法错误猜测法因果图法状态图法等
- 覆盖率:接口覆盖率接口路径覆盖率等
- 注意接口
- 显性接口:函数调用(API)接口
- 隐形接口:消息、网络协议等
系统测试
系统测试概念
- 含义:从用户使用的角度进行测试,将完成了集成测试的系统放在真实的运行环境下进行。
- 目的:功能确认和验证
- 测试方法:黑盒测试
系统测试必要性
- 系统测试:软件开发过程必不可少的一环,软件质量保证的最重要环节。
- 测试内容方面
- 面向:外部输入层测试,如不做,则外部输入层向接口层转换的代码就没有得到测试。
- 面向:系统所有组件相互协调,单元、集成测试未做。
- 测试角度方面
- 系统测试依据:需求规格说明
- 单元、集成测试依据:技术规格说明
- 测试内容方面
系统测试内容
- 压力测试
- 压力测试:在系统运行环境不正常乃至发生故障的情况下,系统可以运行到何种程度的测试
- 测试方法:
- 把输入数据速率提高一个数量级,确定输入功能将如何响应
- 设计需要占用最大存储量或其它资源的测试用例进行测试。
- 设计出在虚拟存储管理机制中引起“颠簸”的测试用例进行测试。
- 设计出会对磁盘常驻内存的数据过度访问的测试用例进行测试。
- 敏感性测试:压力测试的一个变种。在程序有效数据界限内一个小范围内的一组数据可能引起极端的或不平稳的错误处理出现,或者导致极度的性能下降。
- 恢复测试
- 恢复测试:是要证实在克服硬件故障后,系统能否正常地继续进行工作,并不对系统造成任何损害。
- 手段:人工干预等
- 测试方法:
- 错误探测功能──系统能否发现硬件失效与故障;
- 设备故障时,能否切换或启动备用的硬件;
- 故障发生时,能否保护正在运行的作业和系统状态;
- 系统恢复后,能否从最后记录下来的无错误状态开始继续执行作业等。
- 掉电测试:电源中断时,能否保护当时的状态且不毁坏数据,然后在电源恢复时从保留的断点处重新进行操作。
- 性能测试
- 含义:检查系统是否满足在需求说明书中规定的性能。
- 结合:常常要与压力测试结合进行,硬件和软件检测同时进行。
- 内容:
- 响应时间
- 吞吐量
- 辅助存储区,如缓冲区、工作区的大小、处理精度等。
- 安全测试
- 安全性测试:是要检验在系统中已经存在的系统安全性、保密性措施是否发挥作用,有无漏洞。
- 主要攻击方法:
- 正面、侧面或背面攻击系统中易受损坏的那些部分;
- 以系统输入为突破口,利用输入的容错性进行正面攻击;
- 申请和占用过多的资源压垮系统,以破坏安全措施,从而进入系统;
- 故意使系统出错,利用系统恢复的过程,窃取用户口令及其它有用的信息;通过浏览残留在计算机各种资源中的垃圾(无用信息),以获取如口令,安全码,译码关键字等信息;
- 浏览全局数据,期望从中找到进入系统的关键字;
- 浏览逻辑上不存在,但物理上还存在的各种记录和资料等
- 配置测试
- 功能测试
- 含义:在规定的一段时间内运行软件系统的所有功能,以验证这个软件系统有无严重错误。
- 测试方法:黑盒测试
- 错误类型:
- 功能错误或遗漏
- 界面错误
- 数据结构或外部数据库访问错误。
- 性能错误
- 初始化
- 兼容性测试
- 本地化测试
- 文档测试
- 易用性测试等
验收测试
验收测试概念
- 验收测试:完成系统测试之后,产品发布之前所进行的软件测试活动。
- 最后测试操作:部署软件之前的最后一个测试操作。
- 最后技术测试:技术测试的最后一个阶段。
- 目的:确保软件准备就绪
- 时间节点:系统的有效性测试及软件配置审查通过之后。
- 人员组织:以用户为、主开发人员、质量保证人员
- 测试数据:实际生产数据
- 测试内容:
- 功能和性能外
- 可移植性、兼容性、可维
- 护性、错误的恢复功能等
验收测试过程
- 了解软件的质量要求和验收要求
- 编制《验收测试计划》《项目验收准则》
- 测试实施
- 测试环境搭建
- 测试和测试用例设计
- 测试结果分析
- 撰写测试报告
验收测试形式
- 根据合同的验收测试:系统测试子集再测试
- 用户验收测试:
- 客户
- 最终用户
- 现场测试:
- α测试
- β测试
α测试
- 含义:用户在开发环境、模拟用户在模拟实际操作环境下的测试
- 目的:评价FLURPS特性(力育、同域化、可使用性、可靠性、性能和支持)。尤其界面和特色
- 开始时间:
- 编码结束后
- 模块(子系统)测试完成后
- 系统测试过程中产品达到—疋的稳定和可靠程度后
- 原因:交付后,用户的实际使用程序是无法预测的
β测试
- 测试人员:多个用户在实际使用环境下进行测试。这些用户返回有关错误信息给开发者。
- 测试形式:开发者通常不在测试现场,开发者无法控制的环境下进行的软件现场应用。
- 测试步骤:用户记录所有问题(真实的、主观的),定期向开发者报告。
- 测试自标:产品的FLURPS。着重产品的支持性(文档、客户培训和支持产品生产能力)
- 开始条件:α测试达到一定的可靠程度时开始,测试的最后阶段,所有手册文本此阶段完全定稿。
测试停止标准
- 软件是无法完全测试的
- 何时停止测试
- 测试阶段:满足标准
- 测试用例:达到通过率
- 缺陷收敛趋势:趋势线的走向,比如开始上升,然后下降
- 缺陷修复率:不同等级的修复率,比如严重达到0%停止
- 验收测试: 用户通过
- 覆盖率:测试覆盖用户全部需求
- 缺陷度量:缺陷是否可以容忍
- 质量成本:质量进度成本三个方面的平衡
软件测试的组织
-
测试团队
-
开发团队
-
开发团队中配备测试人员
-
项目团队中若干测试团队
-
独立测试专家
-
单独测试部门
-
-
测试人员
- 测试经理
- 测试设计人员测试自动化人员
- 测试管理员
- 测试人员
软件测试相关概念
相关概念
-
软件测试的定义
-
在某种指定的条件下对系统或组件操作,观察或记录结果,对系统或组件的某些方面进行评估的过程。
-
分析软件各项目以检测现有的结果和应有结果之间的差异,并评估软件各项目的特征的过程。
-
-
软件缺陷
- 软件未实现产品说明书要求的功能。
- 软件出现了产品说明书指明不能出现的错误。
- 软件实现了产品说明书未提到的功能。
- 软件未实现产品说明书虽未明确提及但应该实现的目标。
- 软件难以理解、不易使用、运行缓慢或者——从测试员的角度看最终用户会认为不好。
-
验证(Verification)
- 证软件特定开发阶段的输出已经正确完整地实现了规格说明,是否构造了该产品
- 确认(Validation)
对于每个测试级别,都要检查开发活动的输出是否满足具体的需求或与这些特定级别相关的需求,是否构造了正确的产品
-
软件测试
- 找出软件缺陷,并确保修复
-
软件质量保证
- 创建、执行改进过程并防止缺陷的标准和方法
-
质量与可靠性
- 可靠性(reliability)
- 功能性(functionality)
- 可维护性(maintainaoiy )
- 可移植性(portability)
- 可用性(usability)
- 效率(efficiency)
-
测试用例(test case)
- 是测试输入、执行条件、以及预期结果的集合,是为特定的目的开发的,例如执行特定的程序路径或验证与指定的需求相符合
- 主题。设计者、类型、测试名称、状态、描述、优先级、comment、步骤名、步骤描述、预期结果、评审人、评审备注、评审时间等…
-
软件测试的目标
- 确认系统满足其预期的使用和用户的需要。
- 确认解决了所需解决的问题
- 为测试的过程建立责任和可解释性。
- 便于及早发现软件和系统的异常。
- 及早提供软件和系统的性能的评估。
- 为管理提供真实信息,以决定当前状态下发布产品在商业的风险
- 鉴别出程序在功能等方面的异常集聚之处。
-
软件测试的基本原则
- 穷尽测试是不可能的
- 测试无法显示潜伏的软件缺陷
- 测试活动应尽早进行
- 软件缺陷具有群聚性
- 注意“杀虫剂”现象
- 尽量由独立的测试团队进行测试
-
覆盖率
- 覆盖率=测试集合T/测试需求集合TR
- 100%覆盖率不实际商用自动化测试工具(loadrunner等)
-
故障评估
- 一种统计方法,用于评价遗留在一个程序中的故障的数量和种类。
- 插入故障到程序中,观察测试中是否能够检测出来。
-
变异分值
- 该指标和变异测试密切相关。
- 变异测试:程序进行两个或更多个变异,然后用同样的测试用例执行测试,评估探测程序变异的能力。
-
黑盒测试
- 忽略系统或组件的内部机制,仅关注于那些响应所选择的输入及相应执行条件的输出的测试形式
-
白盒测试
- 考虑系统或组件的内部机制的测试形式
-
灰盒测试
- 介于白盒测试与黑盒测试之间的一种测试,多用于集成测试阶段,不仅关注输出、输入的正确性,同时也关注程序内部的情况。
白盒测试
- 把测试对象看做一个透明盒子,允许利用程序内部逻辑结构及有关信息,进行测试。
- 通过在不同点检查程序的状态,确定实际的状态是否与预期的
状态一致。 - 又称为结构测试或逻辑驱动测试。
检查范围
- 对程序模块的所有独立的执行路径至少测试一次;
- 对所有的逻辑判定,取“真”与取“假”的两种情况都至少测试一次;
- 在循环的边界和运行界限内执行循环体
- 测试内部数据结构的有效性等。
完全测试的困难性:对一个具有多重选择和循环嵌套的程序,不同的路径数目可能是天文数字。
逻辑覆盖:以程序内部的逻辑结构为基础设计测试用例的技术。
- 分支覆盖
- 逻辑覆盖
- 条件覆盖
- 条件组合覆盖
语句覆盖:就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。
分支覆盖:就是设计若干个测试用例,运行被测程序,使得程序中每个判断的取真分支和取假分支至少经历一次。分支覆盖又称为判定覆盖。
条件覆盖:设计若干个测试用例,运行被测程序,使得程序中每个判断的每个条件的可能取值至少执
行一次。
条件组合覆盖:设计足够的测试用例,运行被测程序,使得每个判断的所有可能的条件取值组合
至少执行一次。
基本概念节点
- 控制流图覆盖测试:是将代码转变为控制流图(CFG),基于其进行测试的技术。
- 结点:符号o,表示一个或多个无分支的PDL语句或源程序语句。
- 边:箭头,表示控制流的方向。
- 汇聚节点:在选择或多分支结构中,分支的汇聚处应有一个汇聚结点。
- 区域:边和结点圈定的区域。对区域计数时,图形外的区域也应记为一个区域。
单条件嵌套:如果判断中的条件表达式是由一个或多个逻辑运算符(OR,AND,NAND,NOR)连接的复合条件表达式,则需要改为一系列只有单个条件的嵌套的判断。
边覆盖路径
- 节点覆盖:对图中的每个节点,至少要有一条测试路径访问该节点显然,节点覆盖=语句覆盖
- 边覆盖:对图中每一个可到达的长度小于(无边图)等于1的路径,中至少存在一条测试路径覆盖。显然,边覆盖包含节点覆盖,且边覆盖也可以实现分支覆盖。
路径覆盖
- 路径覆盖测试:就是设计足够的测试用例,覆盖程序中所有可能的路径
-
基本路径测试:将覆盖的路径数压缩到一定限度内,程序中的循环体最多只执行一次。
- 绘制程序控制流图
- 分析控制构造的环路复杂性
- 导出基本可执行路径集合
- 设计测试用例的,保证在测试中,程序的每一个可执行语句至少要执行一次。
-
程序的环路复杂性:程序基本路径集中的独立路径条数,这是确保程序中每个可执行语句至少执行一次所必需的测试用例数目的上界。
-
独立路径:从控制流图来看,一条独立路径是至少包含有一条在其它独立路径中从未有过的边的路径。
-
计算方法:V(G)= e-n+2。
其中,e为图中边的数目;n为节点数目。 -
确定线性独立路径的基本集合
- 从源节点(控制流图的入口点)开始,一直走到汇节点(控制流图的出口点)。该路径作为基线路径。
- 接下来,重新回溯基线路径,依次“翻转”在判断节点上原来选择的路径。即当遇到节点的出度大于等于2时,必须选择不同的边。
- 重复以上过程,直到得到的路径数目等于V(G)
-
基本路径覆盖
- 程序流程图->控制流图->计算环路复杂性
- 导出测试用例
- 确保基本路径集的每一条路径的执行。
- 选择测试用例
- 根据判断结点给出的条件,选择合适用例以保证某一条路径可以被测试到
- 测试结果比较
- 测试执行后,与预期结果进行比较。
- 注意事项
- 非孤立的独的路径可以是另一条路径测试的一部分。
黑盒测试
- 测试对象看做一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性
- 只依据程序的需求规格说明书,检查程序的功能是否符合它的功能说明
- 又叫做功能测试或数据驱动测试。
检查范围
- 是否有不正确或遗漏了的功能?
- 在接口上,输入能否正确地接受?能否输出正确的结果?是否有数
- 据结构错误或外部信息访问错误?
- 性能上是否能够满足要求?
- 是否有初始化或终止性错误?
完全测试的困难性:如果考虑所有可能的输入条件和输出条件中,黑盒测试同样可能是天文数字。
等价类划分
-
基本思想:把所有可能的输入数据,即程序的输入域划分成若干部分,然后从每一部分中选取少数有代表性的数据做为测试用例。
-
测试步骤:
- 划分等价类
- 选取测试用例
-
等价类:某个输入域的子集合。在该子集合中,各个输入数据对于揭露程序中的错误都是等效的。
- 有效等价类:对于程序的规格说明来说,是合理的,有意义的输入数据构成的集合。
- 无效等价类:对于程序的规格说明来说,是不合理的,无意义的输入数据构成的集合。
- 需要同时考虑有效等价类和无效等价类
-
等价类划分
-
原则1:如果输入条件规定了取值范围,或值的个数,则可以确立一个有效等价类和两个无效等价类。
-
原则2:如果输入条件规定了输入值的集合,或者规定了“必须如何”的条件,这时可确立一个有效等价类和一个无效等价类。
-
原则3:如果输入条件是一个布尔量,则可以确定一个有效等价类和一个无效等价类。
-
原则4∶如果规定了输入数据的一组值,而且要对每个输入值分别进行处理。可为每一个输入值确立一个有效等价类,所有不允许的输入值集合为一个无效类。
-
原则5:如果规定了输入数据必须遵守的规则,则可以确立一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。
-
-
等价类划分步骤
- 确定等价类
- 建立等价类表,列出所有划分出的等价类
- 为每一个等价类规定一个唯一编号;
- 设计一个新的测试用例,尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步,直到所有的有效等价类都被覆盖为止;
- 设计一个新的测试用例,仅覆盖一个尚未被覆盖的无效等价类,重复这一步,直到所有的无效等价类都被覆盖为止
-
案例
- 在某一PASCAL语言版本中规定:“标识符是由字母开头,后跟字母或数字的任意组合构成。有效字符数为不超过8个。”
并且规定:“标识符必须先说明,再使用。”“在同一说明语句中,标识符至少必须有一个。”
- 在某一PASCAL语言版本中规定:“标识符是由字母开头,后跟字母或数字的任意组合构成。有效字符数为不超过8个。”
边界值分析
-
含义:边界值分析状态测试静态分析方法
-
方法:确定边界情况,选取正好等于,刚刚大于,或刚刚小于边界的值做为测试数据做为测试数据。
-
边界指标:相当于输入、输出等价类而言,稍高、低于其边界值的一些特定情况
-
原因:大量的错误是发生在输入或输出范围边界上,边界测试可以查出更多的错误
-
案例
-
在做三角形计算时,要输入三角形的三个边长:A、B和C。我们应注意到这三个数值应当满足A>0、B>0、C>0、A+B>C、A+C>B、B+C>A,才能构成三角形。
-
确定边界情况
- 如果把六个不等式中的任何一个大于号“>”错写成大于等于号“立”,那就不能构成三角形。问
题恰出现在容易被疏忽的边界附近。
- 如果把六个不等式中的任何一个大于号“>”错写成大于等于号“立”,那就不能构成三角形。问
-
选取正好等于,刚刚大于,或刚刚小于边界的值做为测试数据
- A、B、C比零稍大、等于的情况,任意两条边的和比第三条边稍大、等于的情况
-
状态测试
-
状态测试:在黑盒测试阶段,通过对状态的测试间接地加以验证功能
-
软件状态:软件当前所处的条件或者模式。除了极少数简单程序外,均需选择重要的内容进行测试。
-
建立状态转换图->根据状态转换图设计测试用例
-
建立状态转换图
- 找出从一种状态转入另一种状态所需的输入和条件。
- 标识出软件可能进入的每一种独立状态。
- 找出进入或退出某种状态时的设置条件及输出结果。
-
根据状态转换图设计测试用例
- 原则
- 每种状态至少访问一次
- 测试看起来是最常见和最普遍的状态转换
- 测试状态之间最不常用的分支
- 测试所有错误状态及其返回值
- 测试状态的随机转换
- 原则
-
静态分析方法
- 含义:不运行程序,通过检查和阅读等手段来发现错误并评估代码质量的测试技术
- 作用:代码标准、质量监控提高可靠性尽早通过源代码检查发现缺陷代码审核定位易产生错误的模块
- 适用:非常有效的质量保证手段越来越多地被采用
通用审评过程
- 计划:汇总资料,提交给评审组织
- 概述:内容过多,对风险较高的作为概述内容
- 准备:准备审评的材料,找到评审对象的缺陷
- 评审会议:发现并讨论其中的问题
- 返工:如果评审不接受,则返工
- 追踪:检查返工是否正确的完成任务
静态分析的主要内容
静态分析的类型
- 同事审查:适用于初次审查,要求最低的正式方法,也称为伙伴审查
- 走查:开发组内部进行
- 审查:以会议形式,由开发组、测试组和相关人员联合进行。
软件维护
软件维护的基本概念
定义:软件维护是指由于软件产品出现问题或需要改进而对代码及相关文档的修改,其目的是对现有软件产品进行修改的同时保持其完整性。
软件维护的成本
- 软件维护阶段一般要消耗软件生命周期中经费开支的大部分。
软件维护的基本类型
- 完善性维护占全部维护活动的50%~66%
- 纠错性维护占全部维护活动的17%~21%
- 适应性维护占全部维护活动的18%~25%
- 预防性维护只占全部维护活动的4%左右
完善性维护
- 在软件的使用过程中,用户往往会对软件提出新的功能与性能要求。
- 为了满足这些要求,需要修改或再开发软件,以扩充软件功能、增强软件性能、改进加工效率、提高软件的可维护性。
- 这种情况下进行的维护活动叫做完善性维护。
- 实践证明:
- 大部分维护工作是改变和加强软件,而不是纠错。
- 完善性维护不一定是救火式的紧急维修,而可以是有计划、有预谋的一种再开发活动。
- 来自用户要求扩充、加强软件功能、性能的维护活动约占整个维护工作的50%。
纠错性维护
- 软件交付使用后,因开发时测试的不彻底、不完全,必然会有部分隐藏的错误遗留到运行阶段。
- 这些隐藏下来的错误在某些特定的使用环境下就会暴露出来。
- 为了识别和纠正软件错误、改正软件性能上的缺陷、排除实施中的误用,应当进行的诊断和改正错误的过程就叫做纠错性维护。
适应性维护
- 在使用过程中
- 外部环境(新的硬、软件配置)
- 数据环境(数据库、数据格式、数据输入/输出方式、数据存储介质)可能发生变化。
- 为使软件**适应这种变化,**而去修改软件的过程就叫做适应性维护。
预防性维护
- 预防性维护是为了提高软件的可维护性、可靠性等,为以后进一步改进软件打下良好基础。
- 预防性维护定义为:采用先进的软件工程方法对需要维护的软件或软件中的某一部分(重新)进行设计、编制和测试。
软件维护应该注意的问题
- 配置管理工作不到位
- 许多软件的可读性差
- 人员变动造成的影响
- 任务紧、时间急的情况下处理维护请求
技术方面
-
程序的理解
-
测试
-
影响分析
-
可维护性
-
决定软件可维护性的主要因素
-
可理解性
-
可测试性
-
可修改性
-
可移植性
-
可重用性
-
-
影响软件可维护性的维护°环境的因素
-
软件维护的文档
-
软件的运行环境
-
软件的维护组织
-
软件维护质量
-
管理方面
- 契合组织的目标
- 人力资源
- 过程
- 如何组织维护活动
- 外包
维护费用估算
-
参数模型
-
M= P+K x exp (c-d)
-
M是维护用的总工作量
-
P是生产性工作量
-
K是经验常数
-
exp是以e为底的指数函数
-
c是复杂程度
-
d是维护人员对软件的熟悉程度
-
-
基于经验
- 专家判断、类推、工作分解结构
IEEE维护模型图
软件维护技术
程序的理解
- 程序理解的任务:以软件维护、升级和再工程为目的,在不同的抽象级别上建立基本软件的概念模型,包括从代码本身的模型到基本应用领域的模型,即建立从问题/应用域到程序设计/实现域的映射集
- 程序理解的具体任务
- 通过检查单个的程序设计结构,程序被表示成抽象语法树、符号表或普通源文本
- 尽量做到程序隐含信息的显性表示及程序内部关系的可视化
- 从源代码中提取信息,并存放在通用的数据库中,然后通过查询语言对数据库进行查询
- 检查程序构造过程中的结构关系,明确表示程序组成部分之间的依赖关系。
- 识别程序的高层概念,如标准算法、数据结构、语法及语义匹配等。
软件再工程
-
定义:软件再工程(Re-engineering)指对现有软件进行仔细审查和改造,对其进行重新构造,使之成为一个新的形式,同时包括随之产生的对新形式的实现。
-
软件再工程模型
- 库存目录分析:仔细的、分析库存目录,按照业务重要程度、寿命、当前可维护性等标准,把库中的应用小排序,从中选出再工程的侯选者。然后合理地分配再工程所需要的资源。
- 逆向工程:分析程序以便在比源程序更高的抽象层次上创建出程序的某种描述的过程,也就是说,逆向工程是一个恢复设计结果的过程。
- 代码重构:代码重构并不修改程序的体系结构,它只关注个体模块的设计细节以及在模块中定义的局部数据结构。
- 数据重构:对数据体系结构差的程序很难进行适应性和完善性维护,因此数据体系结构比源代码对程序的长期生存力有更大的影响。
- 正向工程:正向工程也称为革新或改造。正向工程过程应用现代软件工程的概念、原理、技术和方法,重新开发现有的某些应用系统。
软件逆向工程
- 软件逆向工程(Software Reverse Engineering)
- 是分析目标系统,识别系统的构件及其交互关系,并且通过高层抽象或其他形式来展现目标系统的过程。
- 对逆向工程而言,抽象的层次、完备性、工具与分析人员协同工作的程度、过程的方向性等因素是需要考虑的。
- 逆向工程的主要内容
- 数据的逆向工程
- 发生在不同的抽象层次:
- 内部数据结构的逆向工程
- 数据库结构的逆向工程
- 发生在不同的抽象层次:
- 处理的逆向工程
- 为了理解过程抽象,需要在不同的抽象级别(系统级、程序级、构件级、模式级和语句级)分析代码
- 用户界面的逆向工程
- 弄清几个问题:
- 界面必须处理的基本动作是件么?
- 系统对这些动作的行为反应的简要描述是什么?
- 有哪些界面的等价概念是相关的?
- 弄清几个问题:
- 逆向工程的工具
- 静态模型逆向工具
- Rational Rose
- Rigi
- JBPAS
- 动态模型逆向工具
- SCED
- ISVis
- Borland
- Together
- 静态模型逆向工具
- 数据的逆向工程
软件项目管理
软件项目管理概念
软件项目管理的定义
-
计划、协调、度量、监控、控制及报告等管理方法在软件开发和维护中的具体应用,以保证整个过程是系统的
有原则的、可量化的 -
软件项目管理是为了使软件项目能够按照预定的成本、进度、质量顺利完成,而对人员(People)、产品(Product)、过程(Process)和项目(Project)进行分析和管理的活动。
-
软件项目管理内容
软件项目管理的4P要素
- 人员:招聘、选拔、绩效管理、培训、薪酬、职业发展、组织和工作设计、团队/文化的发展
- 产品:策划一个项目以前,应当建立产品的目标和范围,考虑可选的解决方案
- 过程:软件过程提供一个框架,在此框架下可以制定项目开发的综合计划。
- 项目:理解成功项目管理的关键因素,掌握项目计划、监控和控制的一般方法
人员
- 高级管理者:负责定义业务问题
- 项目管理者:计划、激励、组织和控制软件开发人员
- 开发人员:拥有开发产品或应用软件所需技能的人员
- 客户:阐明软件需求的人员
- 最终用户:直接使用或者与软件产品交互的人
团队
- 封闭式:
- 按照权利层次来组织团队做过去类似项目有优势
- 难以承担创新型项目
- 随机式:
- 松散、专家组合型团队有创新优势
- 难以承担有次序执行的项目
- 开放式
- 封闭式+随机式
- 适合解决有次序又有创新的复杂项目效率可能不是太高
- 同步式
- 根据项目分解进行分工适合松散耦合子系统
- 项目项目集成可能会遇到问题
产品
-
确定软件范围
-
项目环境
- 大系统环境/业务环境
- 环境的约束是什么
-
信息目标
- 输出哪些客户可见对象
- 需要什么数据作为输入
-
功能性能
- 如何将输入变成输出
- 要满足哪些特殊性能
-
-
功能分解
过程
- 根据项目特征选择合适的过程模型
- 根据过程模型进行项目分解
项目
- 项目处于危险的信号:
- 不了解客户需求
- 产品范围定义不清楚
- 变更管理不好
- 最后期限不切实际
- 客户抵制
- …
软件度量概念
软件度量的目的
- 软件项目管理的成熟化也需要度量与数字化,目的是持续改进软件过程,并用于项目估算、质量控制、
生产率评估等。
软件度量的内容
- 生产率度量
- 项目工作量
- 项目周期
- 项目成本
- 质量度量
- 产品发布之前发现的缺陷数
- 产品发布后用户报告的缺陷数
- 产品的运行速度
- …
- 行业及组织的历史数据是软件项目度量的基础
软件度量的方法
- 面向规模的度量
- 面向功能点的度量
- 面向对象的度量
- 面向用例的度量
面向规模的度量
-
通过对质量和(或)生产率的测量进行规范化而得到的,这些测量时根据开发过的软件的规模得到的。
- 干行代码( KLOC) :这些代码指的是源代码,通过源代码的行数来直观度量一个软件程序有多大规模
- 生产率(PM) :PM =L/E, L表示代码总量(单位:KLOC),E表示软件工作量(单位:人月)
- 每干行代码的平均成本(CKL) : CKL = S /L,S为软件项目总开销,L表示代码总量(单位: KLOC)
- 代码出错率(EQRI) : EQRl = Ne /L,Ne表示代码出错的行数,L表示代码总量(单位: KLOC)
- 文档与代码比(DI) : Dl = Pd / L,Pd表示文档页数,L表示代码总量(单位:KLOC)
优点
- 简单易行,自然直观
缺点
- 依赖于程序设计语言的表达能力和功能
- 软件开发初期很难估算出最终软件的代码行数
- 对精巧的软件项目不合适
面向功能的度量
面向功能度量的概念
- 用软件的功能表示软件的规模
- 应用最广泛的是功能点(Function Point,FP)法
- 项目开发初期就可估算出
- 功能点计算目前主要基于经验公式
功能点法计算公式
UFC相关五类组件
- 内部逻辑文件(ILF,Internal Logical Files )
- 一个用户可识别的逻辑相关的数据组,它在应用程序边界内,由用户输入来维护
- 它可能是某个大型数据库的一部分或是一个独立的文件
- 外部接口文件(EIF, ExternalInterface Files)
- 一个用户可识别的逻辑相关的数据组,但只能被引用,且数据完全存于软件外部,由另一个应用程序进行维护·
- 是机器可读的全部接口(如磁盘或磁带上的数据文件)
- 是另一个应用程序的内部逻辑文件
- 外部输入(EI, ExternalInput)
- 来自于软件外部的数据输入
- 控制信息(不更新ILF)/业务逻辑信息(更新ILF)
- 可来自于一个数据输入屏幕或其他应用程序。
- 外部输出(EO,External Output)
- 经过处理的数据,由程序内部输出到外部
- 从ILF、EIF中取出数据经过一定的组合、计算后得出的输出数据,如生成报表,派生数据,可能更新ILF
- 用户查询(EQ,External Query)
- 一个输入输出的组合过程,从一个或多个ILF、EIF中取出数据输出到程序外部
- 输入过程不更新ILF,输出过程不进行任何数据处理
功能组件复杂度加权因子表
UFC的计算方法
- 外部输入El数×加权因子(简单=3,平均=4,复杂=6)
- 外部输出EO数×加权因子(简单=4,平均=5,复杂=7)
- 外部查询EQ数×加权因子(简单=3,平均=4,复杂=6)
- 内部逻辑文件ILF数×加权因子(简单=7,平均=10,复杂=15)
- 外部接口EIF数×加权因子(简单=5,平均=7,复杂=10)
- UFC = 上述计算值的总和(加权和)
计算例子
- 假设每个功能要素的复杂度都是平均的若有一个由25个数据登记表、15个报告、10个外部查询、20个逻辑内部表单和5个接口文件组成的学生管理系统,其未调整功能点计数为:
UFC = (25x4)+(15x5) +(10x4)+(20×10)+(5x7)=450(个功能点)
复杂性调节因素值Fi
- 0-没有影响
- 1-偶有影响
- 2-轻微影响
- 3-平均影响
- 4-较大影响
- 5-严重影响
复杂性调节因素Fi
- 系统需要可靠的备份和复原吗?
- 系统需要数据通信吗?
- 系统有分布处理功能吗?
- 性能是临界状态吗?
- 系统是否在一个紧张使用的操作系统下运行?
- 系统需要联机数据项吗?
- 联机数据项是否在多屏幕或多操作之间进行切换?
- 需要联机更新主文件吗?
- 输入、输出、查询和文件很复杂吗?内部处理复杂吗?
- 代码需要被设计成可重用吗?设计中需要包括转换和安装吗?
- 系统的设计支持不同组织的多次安装吗?
- 应用的设计方便用户修改和使用吗?
面向功能的度量优缺点
- 优点
- 与程序设计语言无关,在开发前就可以估算出软件项目的规模
- 不足
- 没有直接涉及算法的复杂度,不适合算法比较复杂的软件系统;
- 功能点计算主要靠经验公式,主观因素比较多
一个功能点所需的代码行粗略估算
软件估算
软件项目估算概念
-
概念
- 项目启动之前,软件团队应该估算将要做的工作、所需要的资源、成本、从开始到完成的时间,也即是对这些内容进行预测
-
策略
- 项目度量方法为项目估算提供了依据与有效输
- 尽量把估算推迟到项目的后期进行
- 根据已经完成的项目进行估算
-
估算方法
-
基于问题分解的估算(基于分解技术的项目估算方法)
- 基于LOC
- 基于功能点FP
- 基于过程分解的估算
-
基于回归分析的经验估算模型(基于经验的项目估算方法)
-
基于LOC
-
基于功能点FP
-
CoCOMO模型
-
-
三点期望值法
- 在基于问题的分解估算方法中,通过估计最大值,最小值,最可能值的加权平均值作为期望值来估算
- 估计期望值=(最大值+4×最可能值+最小值)/6
- 例如︰如果估计系统X规模的最大值为100KLOC,最小值为50KLOC,最可能值为60KLOC,则其估计期望规模为(100+4×60+50)/6 = 65KLOC
案例
-
软件描述(CAD软件)
- CAD图形软件可接受来自用户的二维和三维几何数据,用户通过界面与CAD软件进行交互,并控制它,该软件具有良好的人机界面设计的特征。所有的几何数据及其支持信息存放仕数据车中。开仅仅计分析模块,以产生所需的输出,这些输出将显示在各种不同的图形化设备上。软件在设计中要考虑与外设进行交互并控制它们,包括鼠标、数字化仪、打印机等。
-
软件子系统划分
- 图形用户界面及其控制机制UICF
- 二维几何分析2DGA
- 三维几何分析3DGA
- 数据库管理DBM
- 图形显示CGDF
- 外设控制(与打印机、数字化仪、扫描仪的接口)PCF
- 设计分析子系统DAM
-
基于LOC的估算:估算出各个子系统的代码行,例如三维几何分析功能的代码行估算范围为:
- 乐观值a: 4 600
- 可能值m: 6 900
- 悲观值b: 8 600
- 估算值: e = (a + 4m + b)/6 = 6 800
-
软件估算
-
历史数据
- 平均生产率PM: 620 LOC/PM(620行代码/人月)
- 每个人月的成本C = 8000¥
-
估算项目成本和工作量
- 估算工作量=总代码行/PM= 33200/620=54人月
- 估算成本=估算工作量x每个人月的成本=54人月×8000 = 43 2000¥
-
基于功能点估算
- 估算功能点
- 计算复杂度调整因子
- 计算成本和工作量
- 计算出FP的估算值
- FP = (0.65 + 0.01×>Fi)×CT = 372
- 历史数据
- 平均生产率6.5FP/PM
- 每个人月的成本C = 8000¥(平均月薪)
- 估算成本和工作量
- 工作量58人月(基于LOC的估算值54人月)
- 成本457000¥(基于LOC的估算值43 2000¥)
- 计算出FP的估算值
基于过程分解的项目估算
基于经验的软件估算
基于回归分析的经验估算模型
面向功能点的回归分析经验估算模型
基本COCOMO模型公式及计算方法
COCOMO模型
- COCOMO是指COnstructive COst MOdel,构造性成本模型,Boehm于1981年提出,用于对软件开发项目的规模、成本、进度等方面进行估算
- COCOMO模型是一个综合经验模型,模型中的参数取值来自于经验值,并且综合了诸多的因素、比较全面的估算模型
- 在欧盟国家应用较为广泛
COCOMO模型的层次–支持不同的阶段
-
基本COCOMO模型
- 系统开发的初期,估算整个系统的工作量(包括维护)和软件开发和维护所需的时间
-
中间COCOMO模型
- 估算各个子系统的工作量和开发时间
-
详细COCOMO模型
- 估算独立的软构件,如各个子系统的各个模块的工作量和开发时间
基本COCOMO模型
中间COCOMO模型公式及计算方法
EAF的取值(考虑15个因素)
- 软件产品属性(3):软件可靠性,软件复杂性,数据库的规模
- 计算机属性(4):程序执行时间,程序占用内存大小,软件开发环境的变化,软件开发环境的响应速度
- 人员属性(5):分析员能力,程序员能力,领域经验,开发环境的经验,程序设计语言的经验
- 项目属性(3):软件开发方法的能力,软件工具的数量和质量,软件开发的进度要求
EAF的取值(范围)
案例分析
项目进度计划
项目进度计划概念
- 定义:对项目进行任务划分,定义任务之间的依赖关系,并进行时间估算和资源分配,确保以最佳的时间与成本输出满足质量要求的产品。
- 编制项目计划本质是一个优化问题。
项目计划编制
表示软件项目工作量(成本)与开发时间之间的PNR曲线
- 项目进度与成本之间是一个非线性关系
- 最低成本的交付时间应该为正常交付时间的两倍左右
项目进度计划的价值
- 有序、可控制地对软件项目进行管理
- 确保员工保持高生产率
- 及时交付软件产品
- 降低软件开发成本
- 提高客户满意度
- 及时发布产品新版本
甘特图
- 显示基本的任务信息
- 定义并查看任务的工期、开始时间和结束时间
- 定义并查看任务所分配的资源的信息
- 可定义任务间的前后关系
微软的Project软件
进度条
里程碑
- 里程碑显示项目进展中的重大工作完成
- 里程碑不同于活动
- 活动是需要消耗资源的·里程碑仅仅表示事件的标记
WBS分解与任务网络图
项目进度计划编制过程
- 编制项目进度计划的步骤
WBS分解
- 定义:工作分解结构(Work Breakdown Structure,WBS)是将项目按照功能或过程进行逐层分解,直到划分为若干内容单便于组织管理的单项工作,最终形成的树形结构示意图。
- 作用:
- 相关成员可直观了解软件项目中的各项任务(活动)
- 将项目分解为可管理的任务(活动)
- 作为项目计划与跟踪的基础
两种分解模式
WBS构建应该注意的原则
- 一个任务只应该在WBS中的一个地方出现
- VBS中某项任务的内容是其下所有WBS项的总和一个WBS项只能由一个人责任,其他人只能是参与者
- WBS必须与实际工作中的执行方式一致
- 应让项目团队成员积极参与创建WBS,以确保WBS的一致性
- 每个WBS项都必须文档化,以确保准确理解已包括和未包括的工作范围
- WBS可以根据需求进行必要变更维护
任务网络图
- 定义:任务网络图是项目所有任务(活动)及其之间逻辑关系(依赖关系)的一个图解表示,并从左到右来表示项目的时间顺序。
- 作用
- 可以分解任务以及各项任务所需要耗费的时间及成本·可以显式的描绘各个任务间的时序依赖关系
- 构成
- 任务网络图是一个有向权重网络图,一般用节点表示事件,弧表示任务(活动),弧上的权值表示任务(活动)耗费的时间
个人中心模块开发任务网络图
关键路径
- 关键路径(critical path)
- 在任务网络图中,从项目开始到项目完成有许多条路径,路径上所有弧权重之和最大的路径(路径最长)叫关键路径。
- 非关键路径(noncritical path)
- 在整个任务网络图中非最长的路径都叫非关键路径。
关键路径的意义
- 关键路径上任何任务(活动)的延长都会导致整个项目周期的延长
- 如果想缩短项目周期,就必须缩短关键路径的长度
- 项目经理应该随时关注关键路径上任务(活动的完成情况以及关键路径是否发生了变化
- 对WBS中任务的串行与并行安排方式有指导意义
可用资源对项目计划与关键路径的影响
- 例子:
有一个停车管理软件需要开发,包含三个功能:停车位管理、停车收费管理、人员管理。
每个功能都需要经过三个活动:需求分析、系统设计、系统开发,假定这三个功能在这三个活动上花费的时间分别为(5天、4天、3天),(5天、4天、4天),(4天、5天、5天)有三个工程师:一个需求分析员、一个软件设计师、一个程序员
如何安排此项目活动比较好?
问题
软件工程问题
与计算机硬件相比,计算机软件有哪些特点?
-
软件无磨损
-
依赖系统
-
可复用
为什么说软件工程的发展可以在一定程度上解决软件危机的各种弊端?
-
高质量、低成本
-
高性能、好功能
-
按时完成、好维护
请简述软件工程的基本原则?
-
划分生命周期的阶段
-
对产品的管控和审查
-
人员数量少和技术精
-
人员技术不断更新迭代
请简述软件工程研究的内容?
- 开发方法:生命周期
- 开发模型:瀑布模型、原型模型、增量模型…
- 开发过程:CASE工具(绘图工具)
- 开发管理:产品质量管理
请简述软件工三要素?
答:过程、方法、工具
请简述软件工程的目标?
-
高质量、低成本
-
高性能、实现功能
-
按时完成、好维护
通常有哪几种软件开发方法?
-
结构化方法(交换、事务)
-
面向数据结构方法(jackson(流程图)、warnier(层次))
-
面向对象方法
-
形式化方法
请列举你所知道的软件工程工具?
dev c++ idea vscode
软件过程问题
如何理解软件生命周期的内在特征?
概念:软件生命周期是从可行性研究、需求分析、软件设计、实现、测试、验收、维护的整个过程
特性:通过拆分阶段、减低每个阶段的难度
请对比瀑布模型、快速原型模型、增量模型和螺旋模型
- 瀑布模型:层层递进(不可回溯)
- 快速原型模型:快速的建造一个雏形,持续迭代(简化瀑布模型的需求分析阶段)
- 增量模型:是瀑布模型和原型模型的结合,每个子模块分批次层层递进(组件化模型)
- 螺旋模型:把瀑布、原型、增量相结合、层与层之间没有明确的划分,同时进行(在三个基础上,加上风险分析)
在统一软件开发过程模型中核心工作流程包含哪些?
答:业务建模、需求、分析和设计、实现、测试和部署
当需求不能一次搞清楚,且系统需求比较复杂时应选用哪种开发模型比较适合?
螺旋模型
敏捷过程的核心价值观有哪些?它对传统方法的“反叛”体现在哪些方面?
核心价值观:沟通、编程、客户、变更
- 沟通大于过程
- 编程大于文档
- 客户大于合同
- 变更大于计划
体现:强调个体的重要性、不像传统方法中,文档需求一步步执行,而是体现灵活,同时进行
什么是软件过程?它与软件工程方法学有何关系?
软件过程:获取高质量软件的过程
软件工程方法学:软件从0到1的过程,具体是(生命周期:可行性研究、需求分析、软件设计、实现、测试、维护),三要素:方法、工具、过程
关系:软件工程方法学包含软件工程
某大型企业计划开发一个“综合信息管理系统?
某大型企业计划开发一个“综合信息管理系统”,该系统涉及销售、供应、财务、生产人力资源等多个部门的信息管理。该企业的想法是按部门优先级别乏别逐个实现,边应用边开发。对此,需要一种比较合适的过程模型。请对这个过程模型做出符合应用需要的选择,并说明选择理由。
增量:按级别逐个实现
可行性问题
可行性研究的任务
经济、技术、环境(市场、政策)、人员
简述技术可行性
当下技术是否可实现该功能,且在指定的周期里完成功能
简述操作可行性
市场中技术是否成熟、法律、政策是否允许该技术
如何估算软件成本
代码行估算:每行代码*每行代码的收益
任务估算:把任务分解成小任务,计算每个小任务的成本
可行性研究的步骤
明确系统的目标、分析系统、设计系统、制作方案、编写文档
经过可行性研究之后,为什么要进行项目开发计划
对一些不可预料的风险进行估计,计算人员、环境、配置等预算是否超出
需求工程问题
理解需求分析的作用和重要性
作用:分析用户的需求,把用户的需求转化为对应的文档
重要性:需求分析的好坏直接影响到整个工程是否能够成功,不会偏离用户真正需要的效果
常用的需求获取的方法有哪些?对比各种方法的优缺点
直接面谈:优点(更直观的获取用户需求),缺点( 只适合少数人群)
问卷调查:优点(适合多数人群),缺点(无法更直观的获取用户需求)
现场勘察:优点(在现场直观的看到业务逻辑,一些异常处理)缺点:(只能看到一些业务的逻辑)
快速原型:优点(用户可以看到雏形后,可以更准确说出需求)缺点:(需要程序员耗费一定时间)
理解结构化需求分析的基本思想
分解、抽象
分解:顶层是问题的整个系统目标、中间层是把大问题拆分为小问题、底层是实现的细节
抽象:忽略功能的细节、保留事物的重要属性、置顶向下逐步细化
简述数据流图的作用
逻辑关系:直观的看出对象与对象之间的逻辑关系
交流工具:开发人员与用户之间
分析设计:系统分析和系统设计
简述数据字典的作用
信息查询:用户和编程人员
设计数据:设计数据库
粘合剂:功能模型、行为模型、数据模型
简述E-R图的作用
E-R图:属性、实体、关系
描述实现世界的概念模型
简述状态图的作用
顺序:记录事件的开始、过程、结束的顺序
状态:状态的转换所需的因素
软件设计问题
简述软件设计与需求分析的关系
先需求分析再软件设计
需求分析:根据用户要求通过三阶段用户需求、用户记录、需求文档
软件设计:在需求分析上对软件进行设计
简述软件设计的目标和任务
目标:把需求文档变为“蓝图”的过程
任务:软件设计分为:概要设计(是要点,框架接口设计)和详细设计(过程设计、体系结构设计、界面)
软件设计的过程遵循的规则
规则:模块化、封装、可复用、易维护、灵活
软件设计如何分类,分别有哪些活动
分类:概要设计、详细设计
四个活动:接口设计、界面设计、过程设计、体系结构设计
结构化设计的优点
面向功能设计、单出口、单入口
把大问题分解成小问题、阶段性、清晰、易理解
效率高、少调试、少维护
面向数据流的设计方法的主要思想
- 对数据流图进行复审、精化
- 判断是交换数据流、事务数据流
- 交换数据流:确定输入输出
- 事务数据流:区分事务中心
- 执行交换结构、事务结构
用户界面设计遵循的原则
- 界面置于用户控制之下
- 减少用户的短期记忆
- 界面一致性
改进jackson图和传统jackson图有哪些优点
提高表达能力:for whie if等逻辑语句
不用斜线好打印
高内聚、低耦合有利于提高系统的独立性
高内聚:把相同功能的模块放在一起
低耦合:模块内修改不会影响其他模块
面向对象方法问题
面向对象的基本概念
- 面向对象:现实世界与概念模型的映射
- 对象:现实中的每个实体
- 类:模板
- 消息:方法之间的调用
- 五大特性:继承、封装、多态、重写、抽象
- 包:用于划分不同对象,让好的名称得到保护
- 包的接口:隐藏具体内部实现,通过接口与外部关联
与结构化开发过程相比,为什么面向对象更能真实反映客观世界
- 符合人类的思维方式:用方法属性类对象模拟现实世界
- 更稳定:从方法级别到类级别,功能改变软件结构改变
- 可复用:多态、继承
- 易维护:封装
什么是面向对象技术?面向对象方法的特点有哪些
面向对象技术:模拟现实世界在计算机中实现
特点:继承、封装、类、消息(方法调用)、构件
什么是类?类与传统数据类型有什么关系
类是一种模板,通过类的实例可以构建出很多对象
类与传统类型的关系:对传统属性的升级,更好的语义化
类是具有一组相同属性、方法的对象模板,具有抽象、继承、封装、多态、消息等特性,传统属性:浮点型、布尔型、整形,本身只有类型
与传统的软件工程方法相比,面向对象的软件工程方法法有哪些优点?
- 易编程:与现实世界接轨
- 模块化:高耦合低内聚
- 易维护易扩展:封装、继承的思想
UML的作用和优点有哪些?
统一、规范、易沟通、易维护
如何着手从自然语言描述的用户需求中画出用例图?
用例图由:参与者、用例(功能)、边界、关系组成
- 识别参与者:功能使用者
- 识别用例:系统所需功能
- 画用例图
- 文档描述:功能前置条件、后置条件、标识符…
用例脚本的作用
脚本是用例的实例,用于贯穿用例的一条竖线,用于显示用例中的特殊情况
类之间的外部关系有至有几种类型?每种关系表达什么语义?
泛型:继承
依赖:类与类之间的关系,方法调用、成员变量、返回值形参等
关联:类与类之间的关系,双向,成员变量与方法,把b作为a的变量
实现:class实现多个接口的功能
面向对象分析问题
对比面向对象需求分析方法和结构化需求分析方法
结构化需求分析:分解和抽象,工具:数据流图、数据字典E-R图
面向对象需求分析:贴近现实、稳定性、易维护、易扩展
类之间的外部关系有至有几种类型?每种关系表达什么语义?
- 泛型:继承
- 依赖:类与类之间的关系,方法调用、成员变量、返回值形参等
- 关联:类与类之间的关系,双向,成员变量与方法,把b作为a的变量
- 实现:class实现多个接口的功能
简述面向对象分析的原则?
- 有意义的对象:与解决问题息息相关的对象
- 准确的模型:定义属性无二意性
- 共享:抽出相同的属性,用继承、实现等方法实现信息共享
- 封装:隐藏内部信息,使用接口与外部建立联系
请简述面向对象分析的过程?
- 确定操作对象,确定参与者
- 识别用例,把每个功能看成一个用例
- 把具有相似属性、方法的对象定义成一个类
什么是动态模型?
用状态图描述对象和关系的状态、状态转换的触发条件、对象的行为
什么是对象模型?
描述了类与对象的关系,表示系统目标的静态数据结构
什么是功能模型?
描述了数据的依赖关系,数据的操作,由数据流图组成
软件体系结构问题
什么是软件体系结构?
系统各部分所组成且相互联系的一门技术学科
软件体系结构的作用体现在哪些方面?
规范软件体系的基本结构、模块化
便于开发人员之间的沟通
易前期部署、后期维护、高效、少返工
典型的体系结构风格有哪些?它们各自有什么特点?
B/S:
优点:C/S缺点相反
缺点:技术难
C/S:
交互性好、用户体验好
版本差异、跨平台、兼容性、安全性、下载耗时间、维护成本高
MVC:
优点:多视图对应一个模型,独立模块、移植性强、
缺点:耦合高、视图访问效率低、程序复杂
什么是软件质量属性?
软件系统在其生命周期的过程中的特征
客户机/服务器体系结构有什么特点?
C/S的优点
MVC模型有什么特点
可重用代码且灵活
什么是设计模式?常用的设计模式有哪些?
前人经过多次实践,研究出解决特定问题的方法
单例、工厂、代理
良好的软件体系结构设计有什么好处?
模块化、基本结构
易沟通
易扩展、易维护、高效、少返工
面向对象设计问题
请比较结构化软件设计方法和面向对象软件设计方法
基本单位:结构化、对象
分析方法:数据流图、面向对象
局限不同:数据流为中心、反复迭代
请简述面向对象设计的启发规则?
系统结构清晰、特殊结构深度恰当、简单协议、简单服务、设计简单类
请简述面向对象的设计原则?
高内聚、低耦合、信息隐藏、复用、模块、抽象
请简述系统设计和对象设计?
系统设计是对系统的策略和目标系统的高层结构
对象设计:针对对象展开,结果是详细对象模型
软件实现
在选择编程语言时,通常要考虑哪些因素?
项目范围、用户要求、算法结构、程序员喜好、项目移植性、开发工具、平台支持
请简述编程风格的重要性。要形成良好的编程风格可以从哪些方面做起?
重要性:具有良好的源码,可读、可维护性,可以提高团队的效率,是优秀程序员的体现
- 版权、版本
- 程序版式
- 语句构造
- 注释
- 数据说明
- 效率
- 输入输出
编程语言主要有哪几类?总结每类语言的优缺点。
机器语言:运行速度快,缺(程序员要求高,易出错,难维护)
汇编语言:硬件访问控制快,缺(不能直接识别)
高级语言:易懂、易记、易改、易维护,缺(需要解释或编译才被识别,执行效率不如编程语言)
超高级语言:易懂、易记、易改、易维护,缺(需要解释或编译才被识别,执行效率不如编程语言)
对标识符命名时,要注意哪些原则?
命名规则、命名规范
为什么要对源程序进行注释?
有利于程序员之间的交流,和后期的维护
软件测试问题
对比白盒测试和黑盒测试
白盒:在程序员讲解代码后,对代码内部逻辑测试,用程序结构信息测试,测试所有路径
黑盒:模拟用户,使用穷举法对软件测试,用软件规格说明书,某些代码得不到测试
为什么软件开发人员不能同时完成测试工作?
因为程序员大多对自己的代码很自信,所以很难找到错误,而且测试工作量也很大,程序员应该更注重代码
软件测试的目的?
为了找到软件中的错误,而程序运行中,很难找到所有错误,所以要把错误或缺陷减到最小
软件测试分为几阶段?
单元测试、集成测试、验收测试、系统测试、回归测试
单元测试:模块、局部测试
集成测试:接口之间的融合,是否发生错误
系统测试:用户需求规格说明书是否满足
验收测试:兼容性、界面
回归测试:对软件更改后的重新测试,分为黑盒、白盒
软件测试的原则?
不可能完全、多人测试、不能保证无缺陷、风险测试、集中易错测试、长期测试、设计用例:一输入一输出
静态测试与动态测试的区别?
静态:代码、语法、死循环…
动态:运行程序,黑盒、白盒
单元测试、集成测试、确认测试各自的主要目标是什么?他们之间的区别是什么?又有什么区别?
单元:模块
集成:接口
确认:用户需求
单元是:黑盒、白盒
集成:黑盒
确认:黑盒
什么是集成测试?非增量测试与增量测试有什么区别?增量测试如何组织模块?
集成:接口
非增量测试:分为多个单元测试,最后组装到一起
增量测试:先把未测试组装到已测试上,每加入一次进行一次集成测试
增量测试:排错好、更彻底、时间长
非增量式:排错难、时间中等、没彻底、大型项目均匀分布
常用的需求获取的方法有哪些?对比各种方法的优缺点
直接面谈:优点(更直观的获取用户需求),缺点( 只适合少数人群)
问卷调查:优点(适合多数人群),缺点(无法更直观的获取用户需求)
现场勘察:优点(在现场直观的看到业务逻辑,一些异常处理)缺点:(只能看到一些业务的逻辑)
快速原型:优点(用户可以看到雏形后,可以更准确说出需求)缺点:(需要程序员耗费一定时间)
理解结构化需求分析的基本思想
分解、抽象
分解:顶层是问题的整个系统目标、中间层是把大问题拆分为小问题、底层是实现的细节
抽象:忽略功能的细节、保留事物的重要属性、置顶向下逐步细化
简述数据流图的作用
逻辑关系:直观的看出对象与对象之间的逻辑关系
交流工具:开发人员与用户之间
分析设计:系统分析和系统设计
简述数据字典的作用
信息查询:用户和编程人员
设计数据:设计数据库
粘合剂:功能模型、行为模型、数据模型
简述E-R图的作用
E-R图:属性、实体、关系
描述实现世界的概念模型
简述状态图的作用
顺序:记录事件的开始、过程、结束的顺序
状态:状态的转换所需的因素
软件设计问题
简述软件设计与需求分析的关系
先需求分析再软件设计
需求分析:根据用户要求通过三阶段用户需求、用户记录、需求文档
软件设计:在需求分析上对软件进行设计
简述软件设计的目标和任务
目标:把需求文档变为“蓝图”的过程
任务:软件设计分为:概要设计(是要点,框架接口设计)和详细设计(过程设计、体系结构设计、界面)
软件设计的过程遵循的规则
规则:模块化、封装、可复用、易维护、灵活
软件设计如何分类,分别有哪些活动
分类:概要设计、详细设计
四个活动:接口设计、界面设计、过程设计、体系结构设计
结构化设计的优点
面向功能设计、单出口、单入口
把大问题分解成小问题、阶段性、清晰、易理解
效率高、少调试、少维护
面向数据流的设计方法的主要思想
- 对数据流图进行复审、精化
- 判断是交换数据流、事务数据流
- 交换数据流:确定输入输出
- 事务数据流:区分事务中心
- 执行交换结构、事务结构
用户界面设计遵循的原则
- 界面置于用户控制之下
- 减少用户的短期记忆
- 界面一致性
改进jackson图和传统jackson图有哪些优点
提高表达能力:for whie if等逻辑语句
不用斜线好打印
高内聚、低耦合有利于提高系统的独立性
高内聚:把相同功能的模块放在一起
低耦合:模块内修改不会影响其他模块
面向对象方法问题
面向对象的基本概念
- 面向对象:现实世界与概念模型的映射
- 对象:现实中的每个实体
- 类:模板
- 消息:方法之间的调用
- 五大特性:继承、封装、多态、重写、抽象
- 包:用于划分不同对象,让好的名称得到保护
- 包的接口:隐藏具体内部实现,通过接口与外部关联
与结构化开发过程相比,为什么面向对象更能真实反映客观世界
- 符合人类的思维方式:用方法属性类对象模拟现实世界
- 更稳定:从方法级别到类级别,功能改变软件结构改变
- 可复用:多态、继承
- 易维护:封装
什么是面向对象技术?面向对象方法的特点有哪些
面向对象技术:模拟现实世界在计算机中实现
特点:继承、封装、类、消息(方法调用)、构件
什么是类?类与传统数据类型有什么关系
类是一种模板,通过类的实例可以构建出很多对象
类与传统类型的关系:对传统属性的升级,更好的语义化
类是具有一组相同属性、方法的对象模板,具有抽象、继承、封装、多态、消息等特性,传统属性:浮点型、布尔型、整形,本身只有类型
与传统的软件工程方法相比,面向对象的软件工程方法法有哪些优点?
- 易编程:与现实世界接轨
- 模块化:高耦合低内聚
- 易维护易扩展:封装、继承的思想
UML的作用和优点有哪些?
统一、规范、易沟通、易维护
如何着手从自然语言描述的用户需求中画出用例图?
用例图由:参与者、用例(功能)、边界、关系组成
- 识别参与者:功能使用者
- 识别用例:系统所需功能
- 画用例图
- 文档描述:功能前置条件、后置条件、标识符…
用例脚本的作用
脚本是用例的实例,用于贯穿用例的一条竖线,用于显示用例中的特殊情况
类之间的外部关系有至有几种类型?每种关系表达什么语义?
泛型:继承
依赖:类与类之间的关系,方法调用、成员变量、返回值形参等
关联:类与类之间的关系,双向,成员变量与方法,把b作为a的变量
实现:class实现多个接口的功能
面向对象分析问题
对比面向对象需求分析方法和结构化需求分析方法
结构化需求分析:分解和抽象,工具:数据流图、数据字典E-R图
面向对象需求分析:贴近现实、稳定性、易维护、易扩展
类之间的外部关系有至有几种类型?每种关系表达什么语义?
- 泛型:继承
- 依赖:类与类之间的关系,方法调用、成员变量、返回值形参等
- 关联:类与类之间的关系,双向,成员变量与方法,把b作为a的变量
- 实现:class实现多个接口的功能
简述面向对象分析的原则?
- 有意义的对象:与解决问题息息相关的对象
- 准确的模型:定义属性无二意性
- 共享:抽出相同的属性,用继承、实现等方法实现信息共享
- 封装:隐藏内部信息,使用接口与外部建立联系
请简述面向对象分析的过程?
- 确定操作对象,确定参与者
- 识别用例,把每个功能看成一个用例
- 把具有相似属性、方法的对象定义成一个类
什么是动态模型?
用状态图描述对象和关系的状态、状态转换的触发条件、对象的行为
什么是对象模型?
描述了类与对象的关系,表示系统目标的静态数据结构
什么是功能模型?
描述了数据的依赖关系,数据的操作,由数据流图组成
软件体系结构问题
什么是软件体系结构?
系统各部分所组成且相互联系的一门技术学科
软件体系结构的作用体现在哪些方面?
规范软件体系的基本结构、模块化
便于开发人员之间的沟通
易前期部署、后期维护、高效、少返工
典型的体系结构风格有哪些?它们各自有什么特点?
B/S:
优点:C/S缺点相反
缺点:技术难
C/S:
交互性好、用户体验好
版本差异、跨平台、兼容性、安全性、下载耗时间、维护成本高
MVC:
优点:多视图对应一个模型,独立模块、移植性强、
缺点:耦合高、视图访问效率低、程序复杂
什么是软件质量属性?
软件系统在其生命周期的过程中的特征
客户机/服务器体系结构有什么特点?
C/S的优点
MVC模型有什么特点
可重用代码且灵活
什么是设计模式?常用的设计模式有哪些?
前人经过多次实践,研究出解决特定问题的方法
单例、工厂、代理
良好的软件体系结构设计有什么好处?
模块化、基本结构
易沟通
易扩展、易维护、高效、少返工
面向对象设计问题
请比较结构化软件设计方法和面向对象软件设计方法
基本单位:结构化、对象
分析方法:数据流图、面向对象
局限不同:数据流为中心、反复迭代
请简述面向对象设计的启发规则?
系统结构清晰、特殊结构深度恰当、简单协议、简单服务、设计简单类
请简述面向对象的设计原则?
高内聚、低耦合、信息隐藏、复用、模块、抽象
请简述系统设计和对象设计?
系统设计是对系统的策略和目标系统的高层结构
对象设计:针对对象展开,结果是详细对象模型
软件实现
在选择编程语言时,通常要考虑哪些因素?
项目范围、用户要求、算法结构、程序员喜好、项目移植性、开发工具、平台支持
请简述编程风格的重要性。要形成良好的编程风格可以从哪些方面做起?
重要性:具有良好的源码,可读、可维护性,可以提高团队的效率,是优秀程序员的体现
- 版权、版本
- 程序版式
- 语句构造
- 注释
- 数据说明
- 效率
- 输入输出
编程语言主要有哪几类?总结每类语言的优缺点。
机器语言:运行速度快,缺(程序员要求高,易出错,难维护)
汇编语言:硬件访问控制快,缺(不能直接识别)
高级语言:易懂、易记、易改、易维护,缺(需要解释或编译才被识别,执行效率不如编程语言)
超高级语言:易懂、易记、易改、易维护,缺(需要解释或编译才被识别,执行效率不如编程语言)
对标识符命名时,要注意哪些原则?
命名规则、命名规范
为什么要对源程序进行注释?
有利于程序员之间的交流,和后期的维护
软件测试问题
对比白盒测试和黑盒测试
白盒:在程序员讲解代码后,对代码内部逻辑测试,用程序结构信息测试,测试所有路径
黑盒:模拟用户,使用穷举法对软件测试,用软件规格说明书,某些代码得不到测试
为什么软件开发人员不能同时完成测试工作?
因为程序员大多对自己的代码很自信,所以很难找到错误,而且测试工作量也很大,程序员应该更注重代码
软件测试的目的?
为了找到软件中的错误,而程序运行中,很难找到所有错误,所以要把错误或缺陷减到最小
软件测试分为几阶段?
单元测试、集成测试、验收测试、系统测试、回归测试
单元测试:模块、局部测试
集成测试:接口之间的融合,是否发生错误
系统测试:用户需求规格说明书是否满足
验收测试:兼容性、界面
回归测试:对软件更改后的重新测试,分为黑盒、白盒
软件测试的原则?
不可能完全、多人测试、不能保证无缺陷、风险测试、集中易错测试、长期测试、设计用例:一输入一输出
静态测试与动态测试的区别?
静态:代码、语法、死循环…
动态:运行程序,黑盒、白盒
单元测试、集成测试、确认测试各自的主要目标是什么?他们之间的区别是什么?又有什么区别?
单元:模块
集成:接口
确认:用户需求
单元是:黑盒、白盒
集成:黑盒
确认:黑盒
什么是集成测试?非增量测试与增量测试有什么区别?增量测试如何组织模块?
集成:接口
非增量测试:分为多个单元测试,最后组装到一起
增量测试:先把未测试组装到已测试上,每加入一次进行一次集成测试
增量测试:排错好、更彻底、时间长
非增量式:排错难、时间中等、没彻底、大型项目均匀分布