考点:
- 软件过程模型 ⭐️⭐️⭐️⭐️
- 基于构件的软件⼯程 ⭐️⭐️
- 逆向⼯程 ⭐️
- 净室软件⼯程 ⭐️
- 需求⼯程 ⭐️⭐️
- 系统分析与设计 ⭐️⭐️
- 软件测试 ⭐️⭐️
- 系统运⾏与软件维护 ⭐️
UML!
目录
1 软件过程模型 ⭐️⭐️⭐️⭐️
原型及相关模型之间的关系:
1.1 瀑布模型
瀑布模型(Waterfall Model)将软件⽣存周期(系统生命周期,System Development Life Cycle,SDLC)中的各个活动规定为线性顺序连接的若⼲阶段(如图所示)。
特点:
- 严格区分阶段,每个阶段因果关系紧密相连
- 只适合需求明确的项⽬
缺点:
- 软件需求完整性、正确性难确定(大部分开发项目需求不明确)
- 严格串⾏化,很⻓时间才能看到结果
- 瀑布模型要求每个阶段⼀次性完全解决该阶段⼯作,这不现实
效果奇差,项目失败率95%
1.2 原型模型
原型模型(Prototype Model)即典型的原型开发⽅法,一般用在需求阶段,适合需求不明确的项目。
原型模型两个阶段:
- 原型开发阶段
- ⽬标软件开发阶段
从原型的最终结果来分,可以分为:
- 【抛弃型原型】/快速原型(Rapid Prototyping)/探索式原型:达到预期⽬的后,原型本身被抛弃。抛弃式原型主要⽤在解决需求不确定性、⼆义性、不完整性、含糊性等。
- 【演化型原型】:为开发增量式产品提供基础,逐步将原型演化成最终系统,主要⽤在必须易于升级和优化的场合,适合于Web项⽬。
在本章开头的“原型及相关模型之间的关系”图中,增量模型融合了瀑布模型的基本成分和原型。
从原型是否实现功能来分,可以分为:
- ⽔平原型(也称为⾏为原型):⽤来探索预期系统的⼀些特定⾏为,并达到细化需求的⽬的。⽔平原型通常只是功能的导航,但未真实实现功能。主要⽤在界⾯上。
- 垂直原型(也称为结构化原型):实现了⼀部分功能。垂直原型主要⽤在复杂的算法实现上。
1.3 V模型
V模型(V-Shape Model)是⼀种测试的开发模型,强调测试贯穿项⽬始终,⽽不是集中在测试阶段。
W模型强调测试和开发【并⾏进⾏】。
1.4 增量模型与迭代模型
增量模型(Incremental Model)与迭代模型(Iterative Model)的区别如图中例子所示。
增量:顺次添加个体。迭代:整体逐渐变好
两者常同时出现
1.5 螺旋模型
螺旋模型(Spiral Model)以快速原型为基础,叠加了瀑布模型(前一层的结果是后一层的原型)。如图所示,将开发流程分成了4个象限,特别地,螺旋模型考虑了【⻛险分析】。
- 演化模型跟螺旋模型,增量模型,原型法开发的关系?
- 答
- 与原型化的关系:原型化可分为两种——抛弃式原型和演化式原型,其中最终演化成⼀个产品的就演变成为演化模型。
- 螺旋模型是通过演化模型和瀑布模型的结合所产⽣的,并且螺旋模型强调了⻛险管理。
- 增量模型是原型模型和瀑布模型所结合⽽产⽣的。
- 螺旋模型和增量模型的区别?
- 答:螺旋模型“⼀直旋下去”,旋到最后才是⼀个产品,⽽增量模型每⼀个增量都发布了⼀个可操作的产品。
1.6 构件组装模型
1.6.1 构件化思想
构件组装模型(Component Model)的基本思想为先构造构件,再将这些构件组装起来。
流程:
- 需求分析定义
- 设计构件组装(体系结构设计)
- 建立构件库
- 构建应用软件
- 测试和发布
优点:易扩展、易重⽤、降低成本、安排任务更灵活。
缺点:构件设计要求经验丰富的架构师、设计不好的构件难重⽤、强调重⽤可能牺牲其它指标(如:性能)、第三⽅构件质量难控制。
示例:方舱医院、乐高积木
1.6.2 基于构件的软件⼯程(CBSE) ⭐️⭐️
CBSE(Component-Based Software Engineering)拓宽了构件组装模型的思想,体现了“购买⽽不是重新构造”的哲学,方方面面都考虑到构件。
CBSE的构件应具备的特征:
- 可组装性:所有外部交互必须通过公开定义的接⼝进⾏。
- 可部署性:构件总是⼆进制形式的,能作为⼀个独⽴实体在平台上运⾏。
- ⽂档化:⽤户根据⽂档来判断构件是否满⾜需求。
- 独⽴性:可以在⽆其他特殊构件的情况下进⾏组装和部署。
- 标准化:符合某种标准化的构件模型。
软件构件(Component)是软件系统中具有一定意义的、相对独立的可重用单元。与对象相比,构件可以基于对象实现,也可以不作为对象实现。构件需要在容器(Container)中管理并获取容器提供的服务;客户程序可以在运行状态下利用接口动态确定构件所支持的功能并调用。
构件的组装⼀般都要借助胶⽔代码。可分为如下几类:
- 顺序组装:按顺序调⽤已经存在的构件,可以⽤两个已经存在的构件来创造⼀个新的构件。
- 层次组装:被调⽤构件的“提供”接⼝必须和调⽤构件的“请求”接⼝兼容。(分层)
- 叠加组装:多个构件合并形成新构件,新构件整合原构件的功能,对外提供新的接⼝。
组装可能出现3种不兼容:参数不兼容、操作不兼容、操作不完备。
构件模型要素:
- 【接⼝】:构件通过构件接⼝来定义,构件模型规定应如何定义构件接⼝以及在接⼝定义中应该包含的要素,如操作名、参数以及异常等。
- 【使⽤信息】:为使构件远程分布和访问,必须给构件⼀个特定的、全局唯⼀的名字或句柄。构件元数据是构件本身相关的数据,⽐如构件的接⼝和属性信息。⽤户可以通过元数据找到构件提供的服务。构件模型的实现通常包括访问构件的元数据的特定⽅法。构件是通⽤实体,在部署的时候,必须对构件进⾏配置来适应应⽤系统。
- 【部署】:构件模型包括⼀个规格说明,指出应该如何打包构件使其部署成为⼀个独⽴的可执⾏实体。部署信息中包含有关包中内容的信息和它的⼆进制构成的信息。
基于构件的软件开发中的两种模型:
- 逻辑构件模型:用功能包描述系统的抽象设计,用接口描述每个服务集合,以及功能之间如何交互以满足用户需求,它作为系统的设计蓝图以保证系统提供适当的功能
- 物理构件模型:用技术设施产品、硬件分布和拓扑结构、以及用于绑定的网络和通信协议描述系统的物理设计,这种架构用于了解系统的性能、吞吐率等许多非功能性属性
1.7 快速应⽤开发(RAD)
快速应⽤开发(Rapid Application Development,RAD)在⽣命周期中引入基于构件的开发,由此实现快速开发。
组成:SDLC(瀑布模型)、CBSD(基于构件)
过程:业务建模 → 数据建模 → 过程建模 → 应⽤⽣成 → 测试与交付
适⽤性:RAD对模块化要求⽐较⾼,如果某项功能不能被模块化,则其构件就会出问题;如果⾼性能是⼀个指标,且必须通过调整结构使其适应系统构件才能获得,则RAD也有可能不能奏效;RAD要求开发者和客户必须在很短的时间完成⼀系列的需求分析,任何⼀⽅配合不当都会导致失败;RAD只能⽤于管理信息系统的开发,不适合技术⻛险很⾼的情况。
1.8 统⼀过程(UP/RUP)
在软考中,UP、RUP都指统⼀过程
统一过程((Rational) Unified Process,(R)UP)是一种迭代增量式的软件开发方法论,它强调将系统开发过程分为一系列的迭代周期。
核心特点:
- ⽤例驱动
- 以架构为中⼼
- 迭代和增量
- 优点:
- 降低了在一个增量上的开支风险。如果开发人员重复某个迭代,那么损失只是这一个开发有误的迭代的花费。
- 降低了产品无法按照既定进度进入市场的风险。通过在开发早期就确定风险,可以尽早来解决而不至于在开发后期匆匆忙忙。
- 加快了整个开发工作的进度。因为开发人员清楚问题的焦点所在,他们的工作会更有效率。
- 由于用户的需求并不能在一开始就作出完全的界定,它们通常是在后续阶段中不断细化的。因此,迭代过程这种模式使适应需求的变化会更容易些。
- 优点:
统⼀过程把⼀个项⽬分为4个不同的阶段:
- 初始(构思/初启):定义最终产品视图和业务模型;确定系统范围。
- 细化(精化):设计及确定系统架构;制定⼯作计划及资源要求。
- 构造:开发剩余构件和应⽤程序功能,把这些构件集成为产品,并进⾏详细测试。
- 移交:确保软件对最终⽤户是可⽤的,进⾏β测试,制作产品发布版本。
9个核⼼⼯作流与上述4个阶段组成二维工作流程,如下所示(其中需求、分析与设计、实现、测试、部署正是日常软件开发的核心步骤):
- 业务建模
- 需求
- 分析与设计
- 实现
- 测试
- 部署
- 配置与变更管理
- 项目管理
- 环境
1.9 敏捷开发
敏捷开发(Agile Development)是⼀种以⼈为核⼼、迭代、循序渐进的开发⽅法,适⽤于⼩团队和⼩项⽬,具有⼩步快跑的思想。
特点:
- 适应性的
- 以人为本
- 增量迭代,⼩步快跑
- 适合小型项目(不适合开发团队较为庞大的项目)
敏捷宣⾔:
- 个体和交互胜过过程和⼯具
- 可⼯作的软件胜过⼤量的⽂档
- 客户合作胜过合同谈判
- 响应变化胜过遵循计划
常⻅的敏捷开发⽅法:
- 极限编程(ExtremeProgramming,XP):⼀些对费⽤控制严格的公司中的使⽤,⾮常有效,近螺旋式的开发⽅法。
- 4⼤价值观:沟通【加强⾯对⾯沟通】、简单【不过度设计】、反馈【及时反馈】、勇⽓【接受变更的勇⽓】
- 12条过程实践规则:简单设计、测试驱动、代码重构、结对编程、持续集成、现场客户、发⾏版本⼩型化、系统隐喻、代码集体所有制、规划策略、规范代码、40⼩时⼯作机制
- ⽔晶⽅法:提倡“机动性”的⽅法,拥有对不同类型项⽬⾮常有效的敏捷过程。
- SCRUM:侧重于项目管理,明确定义了可重复的⽅法过程。
- 特征驱动开发⽅法(Feature Driven Development,FDD):认为有效的软件开发需要3要素——【⼈、过程、技术】(要素 ⇒ 特征)
- 定义了6种关键的项⽬⻆⾊:项⽬经理、⾸席架构设计师、开发经理、主程序员、程序员和领域专家。
- 开放式源码:程序开发⼈员在地域上分布很⼴【其他⽅法强调集中办公】。
- ASD⽅法:其核⼼是三个⾮线性的、重叠的开发阶段:猜测、合作与学习。
- 动态系统开发⽅法(Dynamic Systems Development Method,DSDM):倡导以业务为核⼼。
2 逆向工程 ⭐️
逆向⼯程(Reverse Engineering)是设计的恢复过程,可分为如下4个等级:
- 实现级:包括程序的抽象语法树、符号表、过程的设计表示。(程序的实现过程)
- 结构级:包括反映程序分量之间相互依赖关系(结构)的信息,例如调⽤图、结构图、程序和数据结构。
- 程序分量:程序和相关的数据结构信息,泛指函数,过程和类的代码等
- 功能级:包括反映程序段功能及程序段之间关系的信息,例如数据和控制流模型。
- 领域级:包括反映程序分量或程序诸实体与应⽤领域概念之间对应关系的信息,例如实体关系模型。
与逆向⼯程相关的概念有重构、设计恢复、再⼯程和正向⼯程。各概念的对比如下:
- 重构/重组(Restructuring):在【同⼀抽象级别】上转换系统描述形式。
- 设计恢复(Design Recovery):借助⼯具从已有程序中抽象出有关数据设计、总体结构设计和过程设计等⽅⾯的信息。
- 逆向⼯程(Reverse Engineering):分析程序,⼒图在⽐源代码更⾼抽象层次上建⽴程序的表示过程,逆向⼯程是设计的恢复过程。
- 正向⼯程(Forward Engineering)。不仅从现有系统中恢复设计信息,⽽且使⽤该信息去改变或重构现有系统,以改善其整体质量。
- 再⼯程/重构⼯程(Re-engineering):对现有系统的重新开发过程,包括逆向⼯程、新需求的考虑过程和正向⼯程三个步骤。
3 软件开发方法:净室软件⼯程 ⭐️
软件开发方法是指软件开发过程所遵循的办法和步骤,从不同的角度可以对软件开发方法进行不同的分类。
形式化方法是一种具有坚实数学基础的方法,从而允许对系统和开发过程做严格处理和论证,适用于那些系统安全级别要求极高的软件的开发。形式化方法的主要优越性在于它能够数学地表述和研究应用问题及软件实现。但是它要求开发人员具备良好的数学基础。用形式化语言书写的大型应用问题的软件规格说明往往过于细节化,并且难以为用户和软件设计人员所理解。由于这些缺陷,形式化方法在目前的软件开发实践中并未得到普遍应用。
净室即⽆尘室、洁净室。也就是⼀个受控污染级别的环境。
净室软件⼯程(Cleanroom Software Engineering,CSE)是软件开发的一种形式化方法,可以开发较高质量的软件。使⽤盒结构规约(或形式化⽅法)进⾏分析和设计建模,并且强调将正确性验证,⽽不是测试,作为发现和消除错误的主要机制。使⽤统计的测试来获取认证被交付的软件的可靠性所必需的出错率信息。CSE强调在规约和设计上的严格性,还强调统计质量控制技术,包括基于客户对软件的预期使用测试。
技术⼿段:
- 统计过程控制下的增量式开发:控制迭代
- 基于函数的规范和设计:盒⼦结构
- 定义3种抽象层次:⾏为视图(⿊盒) → 有限状态机视图(状态盒) → 过程视图(明盒)
- 正确性验证(净室⼯程的核⼼)
- 统计测试和软件认证:使⽤统计学原理,总体太⼤时必须采⽤抽样⽅法。
缺点:
- 太理论化,正确性验证的步骤⽐较困难且耗时。
- 开发⼩组不进⾏传统的模块测试,这是不现实的。
- 脱胎于传统软件⼯程,不可避免带有传统软件⼯程的⼀些弊端。
4 需求工程 ⭐️⭐️
软件需求(Software Requirements)是指⽤户对系统在功能、⾏为、性能、设计约束等⽅⾯的期望。
分类:
老教材分2层,新教材分5层
其中需求分析可分为结构化需求分析与面向对象需求分析。
4.1 需求获取
需求分类:
- 分层:
- 业务需求:整体全局
- 用户需求:用户视角
- 系统需求:计算机化
- 功能需求
- 性能需求:非功能的部分
- 设计约束
- 按QFD(Quality Function Deployment,质量功能展开)分类:
- 基本需求:明示,常规需求
- 期望需求:隐含
- 兴奋需求:多余
QFD:来自项目管理制度。该做的都得做,不该做的绝不做。
需求获取方法:
- ⽤户⾯谈:1对1-3,有代表性的⽤户,了解主观想法,交互好。成本⾼,要有领域知识⽀撑。
- 联合需求计划(JRP):⾼度组织的群体会议,各⽅参与,了解想法,消除分歧,交互好,成本⾼。主要意图是收集需求,而不是对需求进行分析和验证。实施JRP时应把握以下主要原则:
- 在JRP实施之前,应制订详细的议程,并严格遵照议程进行。
- 按照既定的时间安排进行。
- 尽量完整地记录会议期间的内容。
- 在讨论期间尽量避免使用专业术语。
- 充分运用解决冲突的技能。
- 会议期间应设置充分的间歇时间。
- 鼓励团队取得一致意见。
- 保证参加JRP的所有人员能够遵守事先约定的规则。
- 问卷调查:⽤户多,⽆法⼀⼀访谈,成本低。
- 现场观察:针对较为复杂的流程和操作。
- 原型化⽅法:通过简易系统⽅式解决早期需求不确定问题。
- 头脑⻛暴法:⼀群⼈围绕新业务,发散思维,不断产⽣新的观点。
4.2 结构化需求分析(SA)
结构化需求分析(Structured Analysis,SA)的主要工具有DFD、STD、E-R图等(如下图所示)。除此之外,最中心的数据字典(Data Dictionary)是描述数据(数据项、数据结构、数据流、数据存储、处理逻辑等)的信息集合,是对系统中使用的所有数据元素的定义的集合。
4.2.1 数据流图(DFD) ☀️
数据流图(Data Flow Diagram,DFD)是极为常用的结构化分析工具,能够分层地表示功能模型。
组成元素:
- 数据流:由一组固定成分的数据组成,表示数据的流向。每个数据流通常有一个合适的名词,反映数据流的含义。
- 加⼯:描述了输入数据流到输出数据流之间的变换,即输入数据流做了什么处理后变成了输出数据流。
- 数据存储(文件):暂时存储的数据,每个文件都有名字。流向文件的数据流表示写文件,流出的表示读文件。
- 外部实体:存在于软件系统外的人员或组织。
图元如下:
数据流图具有层次结构,十分契合结构化思想。可将父图拆解为若干子图,如下图所示:
其最上层的图称为顶层图(见下图上半部分),可表示的信息十分有限。保持外部实体不变,对顶层图的系统进行拆解/细化可得其子图,即0层图(见下图下半部分)。该0层图又可拆解为3个加工子图(见下图1,2,3,亦即上图最低层)。
数据流图中的平衡:父图与子图之间的平衡、子图内平衡。(输入/输出一一对应,不可缺失)
异常现象:
- 黑洞:一个加工只有输入数据流而无输出数据流。
- 奇迹:一个加工只有输出数据流而无输入数据流。
- 灰洞:若一个加工的输入数据流无法通过加工产生输出流。
案例分析题型与技巧:
- 详细分析试题说明:根据题干,从整体上分析各成分之间的关系
- 利用数据平衡原则:不建议直接看整体,先单个结点地利用平衡原则进行分析。
- 补充内容
- 补充实体:
- 人物角色:客户、管理员、主管、经理、老师、学生……
- 组织机构:银行、供应商、募捐机构……
- 外部系统:银行系统、工资系统、后台数据库(当要开发的是中间件时)……
- 补充存储:“(?)文件”“(?)表”“(?)库”“(?)清单”“(?)档案”
- 补充数据流
- 数据平衡原则
- 顶层图与0层图对比,是否有顶层图有,但0层图无的数据流,或反之。
- 检查图中每个加工是否存在只有入没有出,或只有出没有入,或根据输入的数据无法产生对应的输出的情况。
- 按题目说明与图进行匹配:说明中的每一句话,都能与图中有对应关系。标出说明中的实体与数据流来缩小对应范围,找出纰漏。
- 补充加工名:因为加工用于处理数据流,故可以在说明中标出该加工涉及到的数据流,再在该数据流名所在的句子中,找“动词+名词”的结构,分析是否可作为加工。
- “动词+名词”例:生成报告、发出通知、批改作业、记录分数。(存在例外情况。如物流跟踪、用户管理等)
4.2.2 状态转换图(STD)
状态转换图(State Transform Diagram,STD)即“流程图”,了解即可。
组成元素:
- 状态(初态、终态)
- 事件
示例:
4.2.3 E-R图
E-R图(Entity Relationship Diagram,实体关系图)用于进行数据建模。详见“数据库系统”篇,此处不多赘述。
示例:
4.3 ⾯向对象需求分析(OOA) ☀️
面向对象需求分析(Object-Oriented Analysis,OOA)在面向对象方法论的指导下逐渐取代了SA。目前广为使用的OOA建模工具为UML图,极为重要,以下将详细介绍UML这种建模语言。
UML(Unified Modeling Language,统一建模语言)整合了所有OOA建模方法,平台无关、语言无关。
UML组成如下所示:
- 构造块
- 事务
- 结构事物:最静态的部分。包括:类、接口、协作、用例、活动类、构件和节点。
- 行为事物:代表时间和空间上的动作。包括:消息、动作次序、连接。
- 分组事物:看成是个盒子。包括:包、构件。
- 注释事物:UML模型的解释部分,描述、说明和标注模型的元素。
- 关系
- 图
- 事务
- 规则
- 范围:给一个名字以特定含义的语境
- 可见性:怎样使用或看见名字
- 完整性:事物如何正确、一致地相互联系
- 执行:运行或模拟动态模型的含义是什么
- 公共机制
- 规格说明:事物语义的细节描述,是模型真正的核心
- 修饰:通过修饰来表达更多的信息
- 公共分类:类与对象、接口与实现
- 扩展机制:允许添加新的规则
在初步的业务需求描述已经形成的前提下,基于UML的需求分析过程大致可分为以下步骤:
- 利用用例及用例图表示需求。从业务需求描述出发获取执行者和场景;对场景进行汇总、分类、抽象,形成用例;确定执行者与用例、用例与用例图之间的关系,生成用例图。【例】
- 利用包图和类图表示目标软件系统的总体框架结构。根据领域知识、业务需求描述和既往经验设计目标软件系统的顶层架构;从业务需求描述中提取“关键概念”,形成领域概念模型;从概念模型和用例出发,研究系统中主要的类之间的关系,生成类图。【包】
4.3.1 UML图的分类
UML2.0中常用的14种图:
静态图(结构图):
- 类图(Class Diagram):⼀组类、接⼝、协作和它们之间的关系。(呈现类的关系)
- 对象图 (Object Diagram):⼀组对象及它们之间的关系。对象图描述了在类图中所建立的事物实例的静态快照。(呈现对象的关系,形式上与类图完全一致)
- 构件图(Component Diagram):类图的变体,描述一个封装的类及其接口、端口,以及由内嵌的构件和连接件构成的内部结构。构件图用于表示系统的静态设计实现视图。对于由小的部件构建大的系统来说,构件图相当重要。
- 包图:软件体系结构图。把共同工作的元素(例如多个类或构件)放到一个包中。由模型本身分解⽽成的组织单元,以及它们之间的依赖关系。
- 部署图 (Deployment Diagram):描述对运行时的处理节点及在其中生存的构件的配置。给出了架构的静态部署视图,通常一个节点包含一个或多个部署图。(软硬件之间映射)
- 制品图:系统的物理结构。
- 组合结构图
动态图(行为图)(顺序图、通信图、定时图、交互概览图合称交互图):
- ⽤例图:描述一组用例、参与者及它们之间的关系。系统与外部参与者的交互。
- 顺序图(Sequence Diagram):强调对象之间消息发送的顺序(操作标有序号),同时显示对象之间的复杂交互过程。
- 通信图(Communication Diagram):强调对象之间存在的消息收发关系,而不专门突出这些消息发送的时间顺序。
- 定时图:用于展示交互过程中的真实时间信息,具体描述对象状态变化的时间点以及维持特定状态的时间段。强调实际时间。
- 状态图(State Diagram):对类描述的补充,针对复杂对象。用于展现此类对象所具有的可能状态(即结点),以及某些事件发生时其状态转移情况。
- 活动图(Activity Diagram):一种特殊的状态图,描述一个操作中要进行的各项活动(与状态图不同)的执行流程。同时,也常被用来描述一个用例的处理流程或者某种交互流程。将进程或其他计算结构展示为计算内部一步步的控制流和数据流,强调对象间的控制流程。存在并行行为。
- 交互概览图:用例实现图
4.3.1.1 用例图
用例图(Use Case Diagram)属于动态图,描述一组用例、参与者及它们之间的关系,从用户角度描述系统功能。
组成:
- 参与者:外部触发因素(包括用户、组织、外部系统、时间、温度等)
- 用例:功能单元
用例的3种关系:
- 包含(Include):将提取出来的公共用例称为抽象用例,而将原始用例称为基本用例/基础用例。当可以从两个或以上的用例中提取公共行为时,应使用包含关系来表示它们。(如下图所示,“指出方包含了指出方”;抽象用例必须用)
- 扩展(Extend):若一个用例明显混合了两种或以上的不同场景,即根据情况可能发生多种分支,则可将该用例分为一个基本用例和一个或多个扩展用例,使得描述尽可能更清晰。(如下图所示,并非OO中的继承,扩展用例可选)
- 泛化(Generalize):当多个用例共同拥有一种类似的结构和行为时,可将它们的共性抽象成为父用例,其他用例作为泛化关系中的子用例。在用例的泛化关系中,子用例是父用例的特殊形式,子用例继承了父用例的所有结构、行为和关系。(如下图所示,特殊/一般关系,即父子继承关系;与扩展的区别在于子类有父亲的职能,可以替换父亲的位置)
箭头
A -(do)→ B
的含义:“It is A that 'does' B.”(后同)
用例建模的流程:
- 识别参与者(必须)
- 合并需求获得用例(必须)
- 细化用例描述(必须),如下图的用例规约所示:
- 调整用例模型(可选):根据上述3种关系
【例】某软件公司拟为物流企业开发一套库存管理系统,该系统的部分需求陈述如下:
(1)库存管理系统主要包括货物入库管理、货物出库管理、仓库管理、统计报表和系统管理等功能。
(2)库存管理系统的用户包括仓库管理员、仓库经理和系统管理员,用户必须在注册后才能使用系统功能;用户可以选择使用邮件注册或电话注册。
(3)仓库管理员在进行出入库操作前必须先登录;仓库经理可以通过系统查看统计报表,如果前一个月的报表未生成,则系统自动生成统计报表,否则直接显示。
(4)系统管理员可以在系统中设置仓库温度范围,当仓库内温度超过最高值或者低于最低值时,系统自动调用温控管理操作,连接温度调节系统进行制冷或加热。
(5)仓库管理功能要求每个月1日零点对前一个月货物入库和出库记录进行数据汇总操作。项目组决定构造用例模型以描述系统需求。
问题1(6分):
用例建模的首要任务是识别系统中的参与者。请根据题目中所描述的需求,识别出系统中有哪些参与者?
问题2(7分):
用例建模的主要工作是书写用例规约。用例规约通常包括哪几部分内容?
问题3(12分):
建立了用例模型后,可以利用用例之间的关系调整用例模型,用例之间的关系包括哪几种?对于每种关系,请根据题目中所描述的需求分别给出一组用例。
【解】
问题1:用例的参与者:仓库管理员、仓库经理、系统管理员、时间、温度、温度调节系统。
问题2:用例名称、简要说明、事件流、非功能需求、前置条件、后置条件、扩展点、优先级。
问题3:用例之间的关系包括:包含关系、扩展关系、泛化关系。“出入库操作”与“登录”属于包含关系;“查看统计报表”与“生成统计报表”属于扩展关系;“用户注册”与“邮件注册”和“电话注册”属于典型的泛化关系。
4.3.1.2 类图与对象图
类图与对象图均属静态图。
类图(Class Diagram):⼀组类、接⼝、协作和它们之间的关系。(呈现类的关系)
对象图 (Object Diagram):⼀组对象及它们之间的关系。对象图描述了在类图中所建立的事物实例的静态快照。(呈现对象的关系,形式上与类图完全一致)
组成:
- 类名:方法名,属性名
- 多重度(比数据库-ER图中不同实体间的各种联系更详细)
1
:一个集合中的一个对象对应另一个集合中一个对象。0..*
或*
:表示一个集合中的1个对象对应另一个集合中的任意多个对象。(可以不对应)1..*
:表示一个集合中的1个对象对应另一个集合中的任意多个对象。(至少对应一个)n..m
:表示一个集合中的n
个对象对应另一个集合中的m
个对象
- 关系
- 依赖(Depend on)关系:一个事物发生变化影响另一个事物。(类
A
调用了类B
,则A
依赖B
) - 泛化关系:特殊(子)/一般(父)关系。(同用例图;继承)(三角
△
) - 关联(Rely on)关系:描述一组链,链是对象之间的连接。
- 聚合(Aggregate)关系:整体与部分生命周期不同。(汽车和轮子,轮子报废汽车尚存)(菱形
◇
) - 组合(Combine)关系:整体与部分生命周期相同。(公司和部门,公司消亡部门亦亡)
- 聚合(Aggregate)关系:整体与部分生命周期不同。(汽车和轮子,轮子报废汽车尚存)(菱形
- 实现(Implement)关系:接口与类之间的关系。
- 依赖(Depend on)关系:一个事物发生变化影响另一个事物。(类
4.3.1.3 交互图
交互图(Interaction Diagram)均属动态图,包含如下几种:
顺序图(Sequence Diagram,序列图)强调对象之间消息发送的顺序(操作标有序号),同时显示对象之间的复杂交互过程。
组成:
- 生命线:时间线(纵轴)
- 对象:位于最上方
- 消息
- 调用
- 返回
通信图 (Communication Diagram,UML1.0中称为协作图)强调对象之间存在的消息收发关系,而不专门突出这些消息发送的时间顺序。(其他方面考的很少)
定时图(计时图;UML2.0新增)强调实际时间,用于展示交互过程中的真实时间信息,具体描述对象状态变化的时间点以及维持特定状态的时间段。(其他图都无法做到)
还有一种交互图:交互概览图
4.3.1.4 状态图与活动图
状态图(State Diagram)属于动态图,是对类描述的补充。用于展现此类对象所具有的可能状态(即结点),以及某些事件发生时其状态转移情况。
【例】在订单处理的过程中,会员可以点击“取消订单”取消该订单。如果支付失败,该订单将被标记为挂起状态,可后续重新支付,如果挂起超时30分钟未支付,系统将自动取消该订单。订单支付成功后,系统判断订单类型:
(1)对于常规订单,标记为备货状态,订单信息发送到货运部,完成打包后交付快递发货;
(2)对于定制订单,会自动进入定制状态,定制完成后交付快递发货。会员在系统中点击收货按钮后变为收货状态,结束整个订单的处理流程。
整个过程的UML图如下所示,要求填充S1、S2、S3、S4、S5处的内容。
【解】该图为状态图,要填充的S1~S5均为状态。
本题较为简单,可直接根据原文获得答案:S1为“挂起状态”,S2为“备货状态”,S3为“定制状态”,S4为“收货状态”,S5为“订单收货状态”。(后续例题会提高亿些难度)
活动图(Activity Diagram)是一种特殊的状态图,描述一个操作中要进行的各项活动(与状态图不同)的执行流程。同时,也常被用来描述一个用例的处理流程或者某种交互流程。将进程或其他计算结构展示为计算内部一步步的控制流和数据流,强调对象间的控制流程。
神似程序流程图,但存在如下巨大区别:
- 活动图是面向对象的,流程图是结构化的
- 如下图所示,活动图存在黑粗线,表示之间的分支可以并行。
- 活动图更凸显系统控制行为的表现,而流程图更关注业务流程
下图称为泳道式活动图,各泳道上的活动仅由对应的角色去完成,能够一目了然地表现各角色的职能:
流程图的环路复杂度计算式为
V(G) = E - N + 2
其中E
为边数,N
为结点数。或使用以下计算式
V(G) = P + 1
其中P
为图中判定结点的数目。
【例】某软件公司为电子商务企业开发一套网上交易订单管理系统,以提升服务的质量和效率。在项目之初,项目组决定来用面向对象的开发方法进行系统开发,并对系统的核心业务功能进行了分析,具体描述如下:
注册用户通进商品信息页面在线浏览商品,将需要购买的商品添加进购物车内,点击“结算”按钮后开始录入订单信息。
用户在订单信息录入页面上选择支付方式,填写并确认收货人、收货地址和联系方式等信息。点击“提交订单”按钮后产生订单,并开始进行订单结算。
订单需要在30分钟内进行支付,否则会自动取消,用户也可以手工取消订单。
用户支付完成,经确认后,系统开始备货,扣除该商品可接单数量,并移除用户购物车中的所有商品资料。
生成订单表单,出货完毕,订单生效。为用户快递商品,等待用户接收。
用户签收商品,交易完成。
问题1(12分):
识别设计类是面向对象设计过程中的重要工作,没计类表达了类的职责,即该类所担任的任务。请用300字以内的文字说明设计类通常分为哪三种类型,每种类型的主要职责,并针对题干描述案例涉及的具体类为每种类型的设计类举出2个实例,
问题2(3分):
在面向对象的设计过程中,活动图 (Activity Diagram)阐明了业务用例实现的工作流程。请用300字以内的文字给出活动图与流程图(flow chart)的三个主要区别。
问题3(10分):
在面向对象的设计过程中,状态图(Statechart Diagram)描述了一个实体基于事件反应的动态行为。请根据题干描述,填写下图中的(a)~(e)空白,完成订单处理的状态图。
【解】
问题1:题干中“设计类”意为在设计阶段的3种类(见OOA最开头)。
(1)实体类:映射需求中的每个实体,保存需要存储在永久存储体中的信息,例如,用户、商品等。
(2)控制类:用于控制用例工作的,用于对一个或几个用例所特有的控制行为进行建模。例如,结算、备货等。
(3)边界类:用于封装在用例内、外流动的信息或数据流。例如,浏览器、购物车等。
问题2:
(1) 活动图描述的是对象活动的顺序关系所遵循的规则,它着重表现系统的行为,而非处理过程;而流程图着重描述处理过程。
(2) 流程图一般都限于顺序进程,而活动图则可以支持并发进程。
(3) 活动图是面向对象的,而流程图是面向过程的。
问题3:
(a)取消;(b)待结算;(c)大于30分钟;(d)订单生效;(c)用户签收。
4.3.1.5 构件图与包图
构件图与包图均属静态图。
构件图(Component Diagram)是类图的变体,描述一个封装的类及其接口、端口,以及由内嵌的构件和连接件构成的内部结构。构件图用于表示系统的静态设计实现视图。对于由小的部件构建大的系统来说,构件图相当重要。
包图包含由模型本身分解⽽成的组织单元,以及它们之间的依赖关系。其基本思想是把共同工作的元素(例如多个类或构件)放到一个包中。通常作为面向对象的设计模型中的软件体系结构图。
两者的区别:
- 构件图聚焦于某一功能,提供了供外部调用的接口,可让其所含的类互相协作,返回结果
- 包图仅将一堆元素放至一个包中,以供管理。
4.3.1.6 部署图
部署图(Deployment Diagram)属于静态图,描述对运行时的处理节点及在其中生存的构件的配置。给出了架构的静态部署视图,通常一个节点包含一个或多个部署图。(软硬件之间映射)
在项目开发完毕后使用,直观地展现服务器上的部署情况。
4.3.2 UML“4+1”视图
UML采⽤“4+1”视图来描述软件和软件开发过程(流程如图所示)
各视图详细解释如下:
- 左上——逻辑视图(Logical View):系统分析、设计人员——类与对象(关注系统功能/逻辑)
- 右上——实现视图(Implementation View):程序员——物理代码文件和组件
- 左下——进程视图(Process View):系统集成人员——线程、进程、并发(进程 ⇒ 并发)
- 右下——部署视图(Deployment View):系统和网络工程师——软件到硬件的映射
- 中心——⽤例视图(Use-case View):最终用户——需求分析模型(即“+1”,四个视图均涉及到)
4.4 需求定义
需求定义(形成需求规格)即形成SRS(软件需求规范/软件需求规格说明书,Software Requirements Specification)。
两种方法:
- 严格定义法
- 所有需求都能够被预先定义
- 开发人员与用户之间能够准确而清晰地交流
- 采用图形/文字可以充分体现最终系统
- 原型法
- 并非所有的需求都能在开发前被准确的说明
- 项目参加者之间通常都存在交流上的困难
- 需要实际的、可供用户参与的系统模型
- 有合适的系统开发环境
- 反复是完全需要和值得提倡的,需求一旦确定,就应遵从严格的方法
4.5 需求验证
需求验证在最后用户签字确认后形成需求基线(经过评审的SRS)。
4.6 需求管理
需求管理是对【需求基线】进行管理,主要活动:变更控制、版本控制、需求跟踪、需求状态跟踪
4.6.1 需求跟踪
需求跟踪(Requirements Traceability)将单个需求和其他系统元素之间的依赖关系和逻辑联系建立跟踪,这些元素包括各种类型的需求、业务规则、系统架构和构件、源代码、测试用例,以及帮助文件等。
需求跟踪一般采用需求跟踪矩阵做跟进工作,跟踪矩阵将从需求源头一直跟进到最终的软件产品。通过需求跟踪来一步步落实过程。
在反向跟踪表中,每有某个用例满足某个原始需求就在对应格子打“√”。最后若某列无“√”则说明该用例多余(不对应任何用户需求),若某行无“√”则说明该需求被遗漏。正向跟踪表同理。
4.6.2 变更控制
需求变更(Requirement Change)要进行控制,严格防止因失控而导致项目混乱,出现重大风险。
一般情况下,需求变更管理的流程如下:
- 问题分析和变更描述
- 变更分析和成本计算:由CCB(Change Control Board,项目变更控制委员会)负责审批
- 变更实现
需求变更控制流程的⼗⼤步骤:
- 明确问题
- 书⾯申请
- 判断变更需求类别
- 评估变更影响
- 判断变更的紧急级别
- 沟通确认
- 明确解决⽅案
- 审批管理
- 执⾏变更
- 版本控制
5 软件系统建模 ⭐️
软件系统建模(Software System Modeling)可以与逆向工程、需求分析、软件设计等方面相联系。
【例】论软件系统建模方法及其应用
软件系统建模(Software System Modeling)是软件开发中的重要环节,通过构建软件系统模型可以帮助系统开发人员理解系统、抽取业务过程和管理系统的复杂性,也可以方便各类人员之间的交流。软件系统建模是在系统需求分析和系统实现之间架起的一座桥梁,系统开发人员按照软件系统模型开发出符合设计目标的软件系统,并基于该模型进行软件的维护和改进。
请围绕“论软件系统建模方法及其应用”论题,依次从以下三个方面进行论述。
- 概要叙述你参与的软件系统开发项目以及你所担任的主要工作。
- 说明软件系统开发中常用的建模方法有哪几类?阐述每种方法的特点及其适用范围。
- 详细说明你所参与的软件系统开发项目中,采用了哪些软件系统建模方法,具体实施效果如何。
【答】
- 结构化建模⽅法:以过程为中⼼的技术,可⽤于分析⼀个现有的系统以及定义新系统的业务需求。结构化建模⽅法所绘制的模型称为数据流图(DFD)。对于流程较为稳定的系统可考虑结构化建模⽅法。
- 信息⼯程建模⽅法(或数据库建模⽅法):⼀种以数据为中⼼,但过程敏感的技术,它强调在分析和研究过程需求之前,⾸先研究和分析数据需求。信息⼯程建模⽅法所创建的模型被称为实体-联系图(ERD)。主要⽤于数据建模。
- ⾯向对象建模⽅法:将“数据”和“过程” 集成到被称为“对象”的结构中,消除了数据和过程的⼈为分离现象。⾯向对象建模⽅法所创建的模型被称为对象模型。随着⾯向对象技术的不断发展和应⽤,形成了⾯向对象的建模标准,即UML(统⼀建模语⾔)。UML定义了⼏种不同类型的模型图,这些模型图以对象的形式共建⼀个信息系统或应⽤系统。⽬前⽐较常⽤的建模⽅法。
6 系统设计基础 ⭐️⭐️
系统设计是软件开发的重要阶段,可大体分为如下两种设计:
- 外部设计(概要设计):设计各个部分的功能、接口、相互如何关联。
- 内部设计(详细设计):设计具体模块的实现。
6.1 人机界面设计
人机界⾯(Human-Machine Interface,HMI)设计是指⽤户与系统之间架起⼀座桥梁,主要内容包括:定义界⾯形式、定义基本的交互控制形成、定义图形和符号、定义通⽤的功能键和组合键的含义及其操作内容、定义帮助策略等。
黄金三法则:
- 置于用户控制之下
- 以不强迫用户进入不必要的或不希望的动作的方式来定义交互方式
- 提供灵活的交互
- 允许用户交互可以被中断和撤销
- 当技能级别增加时可以使交互流水化并允许定制交互
- 使用户隔离内部技术细节
- 设计应允许用户和出现在屏幕上的对象直接交互
- 减少用户的记忆负担
- 减少对短期记忆的要求
- 建立有意义的缺省
- 定义直觉性的捷径
- 界面的视觉布局应该基于真实世界的隐喻
- 以不断进展的方式揭示信息
- 保持界面的一致性
- 允许用户将当前任务放入有意义的语境
- 在应用系列内保持一致性
- 如过去的交互模型已建立起了用户期望,除非有迫不得已的理由,不要改变它
注:原则上不提倡使用创新的模式吸引用户的眼球!
6.2 结构化设计(SD)
结构化设计(Structured Design,SD)是一种面向数据流的设计方法,目的在于确定软件的结构。
结构化设计的2种设计分类:
- 概要设计【外部设计】:功能需求分配给软件模块,确定每个模块的功能和调⽤关系,形成模块结构图。(完成了架构设计的职能)
- 详细设计【内部设计】:为每个具体任务选择适当的技术⼿段和处理⽅法。
6.2.1 结构化设计原则
结构化设计的原则:
- 模块独⽴性原则(⾼内聚、低耦合)
- 保持模块的⼤⼩适中
- 多扇⼊,少扇出
- 深度和宽度均不宜过⾼
扇入与扇出的定义如图所示:
模块独⽴性的度量:内聚、耦合
6.2.2 内聚与耦合
内聚(Cohesion):衡量模块内部各元素结合的紧密程度,结构化设计的目标为高内聚。
如表所示,从下到上为低内聚到高内聚:
内聚类型 | 描述 |
---|---|
功能内聚 | 完成⼀个单⼀功能,各个部分协同⼯作,缺⼀不可。 |
顺序内聚 | 处理元素相关,⽽且必须顺序执⾏。 |
通信内聚 | 所有处理元素集中在⼀个数据结构的区域上。 (UC矩阵) |
过程内聚 | 处理元素相关,⽽且必须按特定的次序执⾏。 (与顺序内聚唯一区别为不强调时间顺序,不“必须”) |
时间内聚 (瞬时内聚) |
所包含的任务必须在同⼀时间间隔内执⾏。 (在上述内聚的基础上,进一步未规定该时间间隔内具体顺序) |
逻辑内聚 | 完成逻辑上相关的⼀组任务。 (不需要明确规定逻辑) |
偶然内聚 (巧合内聚) |
完成⼀组没有关系或松散关系的任务。 |
耦合(Coupling):度量不同模块间互相依赖的程度,结构化设计的目标为低耦合。
如表所示,从下到上为高耦合到低耦合:
耦合类型 | 描述 |
---|---|
⾮直接耦合 | 两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调⽤来实现的。 (通过第三方实现联系) |
数据耦合 | ⼀组模块借助参数表传递简单数据。 |
标记耦合 | ⼀组模块通过参数表传递记录信息(数据结构)。 |
控制耦合 | 模块之间传递的信息中包含⽤于控制模块内部逻辑的信息。 (例如:控制分支的条件) |
外部耦合 | ⼀组模块都访问同⼀全局简单变量,⽽且不是通过参数表传递该全局变量的信息。 |
公共耦合 | 多个模块都访问同⼀个公共数据环境。 |
内容耦合 | ⼀个模块直接访问另⼀个模块的内部数据;⼀个模块不通过正常⼊⼝转到另⼀个模块的内部;两个模块有⼀部分程序代码重叠;⼀个模块有多个⼊⼝。 |
6.2.3 模块的四个要素
结构化设计中模块的4个要素:
- 输入和输出:模块的输入来源和输出去向都是同一个调用者,即一个模块从调用者那儿取得输入,进行加工后再把输出返回调用者。
- 处理功能:模块把输入转换成输出所做的工作。
- 内部数据:仅供该模块本身引用的数据。
- 程序代码:用来实现模块功能的程序。
模块的接口是模块与其他模块进行交互的部分,所以接口的定义不仅仅属于其模块自身的内部特性,与外部模块也具有相关性。
6.3 ⾯向对象设计(OOD)
面向对象设计(Object-Oriented Design,OOD)是面向对象程序设计(OOP)在软件设计阶段的应用,旨在通过定义和设计对象及其关系来构建软件系统,强调定义软件对象,并使这些对象互相协作来满足用户需求。
面向对象的设计模型包含以包图表示的软件体系结构图,以交互图表示的用例实现图,完整精确的类图,针对复杂对象的状态图和用以描述流程化处理的活动图等。
注意联系OOA中UML图部分。
基本过程:分析模型 -> 设计模型
6.3.1 设计模式 ☀️☀️
设计模式(Design Pattern)着眼于解决某一特定的局部问题,是一种局部解决方案的应用。
例:Java内存管理中的垃圾回收机制。
3大类设计模式:
- 创建型模式:主要用于创建对象,为设计类实例化新对象提供指南。
- 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
- 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
- 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
- 抽象工厂(Abstract Factory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
- 建造者(Builder) 模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
- 结构型模式:主要用于处理类或对象的组合,对类如何设计以形成更大的结构提供指南。
- 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
- 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
- 解决方案:增加一个类作为适配器,转换类的接口到客户端类期望的另一个接口。实现一个适配器类,这个类为系统的其他部分提供了一个不变的方法供调用,为了集成不同商品供应商提供的税率计算类,编写一个适配器类的子类,包含调用购买类所需的代码。该子类将系统的调用映射到某个供应商的税率计算类。如果要更换供应商,那么只需要写一个新的适配器子类,其他保持不变。
- 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
- 装饰(Decorator)模式:动态地给对象增加一些职责,即增加其额外的功能。
- 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
- 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。
- 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
- 行为型模式:主要用于描述类或对象的交互以及职责的分配,对类之间交互以及分配责任的方式提供指南。
- 模板方法(Template Method)模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
- 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
- 解决方案:在具有公共接口的独立类中定义每个计算。可以利用该模式创建各种促销类,它们从同一个超类继承。每个类都有相同名称的标准接口方法,用于根据订单编号计算将要折扣的金额总数。
- 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
- 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
- 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。
- 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行。
- 中介者(Mediator) 模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
- 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
- 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
- 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
- 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
6.3.2 类的分类
- 边界类:API接口(机器接口)、用户界面(人机交互)
- 例:显示屏、窗体、打印机接口、通信协议、对话框、菜单、购物车、报表、二维码
- 控制类:应用逻辑、业务逻辑、数据访问逻辑(均为解决逻辑)
- 例:身份验证器
- 实体类:数据
- 例:学员类、课程类
对象间的关系:组合,聚合,继承等
6.3.3 设计原则
七大设计原则:
- 单⼀职责原则:设计⽬的单⼀的类。
- 开放-封闭原则:对扩展开放,对修改封闭。
- 里⽒替换原则(Liskov Substitution Principle,LSP):⼦类可以替换⽗类。
- 基本思想:一个软件实体如果使用的是一个基类对象,那么一定适用于其子类对象,而且觉察不出基类对象和子类对象的区别,即把基类都替换成它的子类,程序的行为没有变化。反过来则不一定成立,如果一个软件实体使用的是一个子类对象,那么它不一定适用于基类对象。
- 在运用里氏替换原则时,尽量将一些需要扩展的类或者存在变化的类设计为抽象类或者接口,并将其作为基类,在程序中尽量使用基类对象进行编程。由于子类继承基类并实现其中的方法,程序运行时,子类对象可以替换基类对象,如果需要对类的行为进行修改,可以扩展基类,增加新的子类,而无需修改调用该基类对象的代码。
- 依赖倒置原则:要依赖于抽象,⽽不是具体实现;针对接⼝编程,不要针对实现编程。
- 接⼝隔离原则:使⽤多个专⻔的接⼝⽐使⽤单⼀的总接⼝要好。
- 组合重⽤原则:要尽量使⽤组合,⽽不是继承关系达到重⽤⽬的。
- 迪⽶特(Demeter)原则(最少知识法则):⼀个对象应当对其他对象有尽可能少的了解。
7 软件测试 ⭐️⭐️
⾃动化测试:软件测试的⾃动化,即在预先设定的条件下⾃动运⾏被测程序,并分析运⾏结果。总的来说,这种测试⽅法就是将以⼈驱动的测试⾏为转化为机器执⾏的⼀种过程。不适合场景:项⽬周期短,需求变动频繁。常⻅⾃动化测试:单元⾃动化测试、接⼝⾃动化测试、UI⾃动化测试。
7.1 软件测试分类
7.1.1 动态测试与静态测试
软件测试(Software Test)⽅法总体上可以分为动态、静态两大类,如下所示:
- 动态测试:计算机运行
- 白盒测试
- 黑盒测试
- 灰盒测试(结合了⿊盒与⽩盒测试)
- 静态测试:人工监测和计算机辅助分析(并非直接跑源码)
- 桌前检查:自己看代码
- 代码审查:交叉进行
- 代码走查:人工执行代码(阅读,“脑补”结果)
静态测试都是做的【静态分析】,包括如下几个阶段:
- 控制流分析:是否存在没有使⽤的语句/⽆法达到的语句/调⽤并不存在的⼦程序。
- 数据流分析(数据使用分析):突出程序中变量的使用情况,引⽤未定义的变量、对以前未使⽤的变量再次赋值。
- 接⼝分析:检查模块之间接⼝的⼀致性、⼦程序和函数之间的接⼝⼀致性、函数形参与实参的数量、顺序、类型的⼀致性。
- 信息流分析:找出输入变量和输出变量之间的依赖关系(I/O)
- 路径分析:找出程序中所有可能的路径并画在此路径中执行的语句
- 表达式分析:括号不配对、数组引⽤越界、除数为零。
7.1.2 ⽩盒测试与黑盒测试
⽩盒测试与黑盒测试均属于动态测试
- ⽩盒测试【结构测试】(White-box Test):主要用于单元测试阶段,关注内部结构与逻辑。
- 方法:
- 控制流测试【逻辑覆盖测试(语句覆盖最弱,路径测试覆盖最强)】(此处越“强”指测试用例数越多)
- 数据流测试
- 程序变异测试【错误驱动测试】
- 方法:
- ⿊盒测试【功能测试】(Black-box Test):主要用于集成测试、确认测试和系统测试阶段,关注输⼊输出及功能。
- 方法(经常数种混合使用):
- 等价类划分:不同等价类,揭示不同问题;有效等价类/⽆效等价类
- 边界值分析:1<=x<=10,可取×的值为0、1、10和11作为测试数据。
- 错误推测:依靠测试⼈员的经验和直觉。
- 判定表:最适合描述在多个逻辑条件取值的组合所构成的复杂情况下,分别要执⾏哪些不同的动作。
- 因果图:根据输⼊条件与输出结果之间的因果关系来设计测试⽤例。
- 方法(经常数种混合使用):
7.2 软件测试阶段
在V模型中,软件测试贯穿项⽬始终,存在如下几个主要测试阶段:
- 单元测试:依据软件【详细设计】,模块测试,模块功能、性能、接⼝等。
- 集成测试:依据软件【概要设计】,模块间的接⼝。
- 系统测试:依据软件【需求⽂档】,在真实环境下,验证完整的软件配置项能否和系统正确连接。(需配置完整的软硬件环境条件)
- 确认测试:依据软件【需求⽂档】,验证软件与需求的⼀致性。(要求用户参与,因为需要用户确认,故又称验收测试)
- 分类:内部确认测试、α测试、β测试、验收测试
其他特殊测试:
- 回归测试:对变更部分的测试。测试软件变更之后,变更部分的正确性和对变更需求的符合性。
集成测试常使用如下两种方法:
- 一次性组装:风险高
- 增量式组装:测试全面
- 自顶向下:需要桩模块
- 自底向上:需要驱动模块
- 混合式:桩模块和驱动模块都需要
其中,桩模块、驱动模块的作用均为填充下一步操作对应的暂未组装入的模块。例如自顶向下时,被测模块需要调用子模块,但其暂未组装入,因此用桩模块填充此位。自底向上时的驱动模块(改为被父模块调用)、混合式时均使用,与之同理。
由于桩模块、驱动模块均是围绕单一被测模块所定义,且集成测试常紧跟在单元测试之后,因此在实际工作中单元测试也常使用上述测试策略。
7.3 系统测试
系统测试可分为如下几类:
- 功能测试
- 性能测试
- 负载测试:各种工作负载下系统的性能
- 压力测试【测上限】:系统的瓶颈或不能接受的性能点
- 强度测试【测下限】:系统资源特别低/超负荷的情况下运行(系统受限的情况)
- 容量测试【并发测试】:同时在线的最大用户数
- 可靠性测试:正确运行的概率(详见系统可靠性分析与设计)
- 恢复测试:容错能力
- 健壮性测试
- 用户界面测试
- 安全性测试
- 安装与反安装测试
8 系统运⾏与软件维护 ⭐️
8.1 系统转换计划
8.1.1 遗留系统演化策略
在处理遗留系统时,应综合考虑其业务价值与技术水平。有如下几种策略:
- 淘汰策略:遗留系统的技术含量较低,且具有较低的业务价值。对遗留系统的完全淘汰是企业资源的根本浪费,我们应该善于“变废为宝”,通过对遗留系统功能的理解和借鉴,可以帮助新系统的设计,降低新系统开发的⻛险。
- 集成策略:遗留系统的技术含量较⾼,但其业务价值较低,可能只能完成某个部⻔或⼦公司的业务管理。这种系统在各⾃的局部领域⾥⼯作良好,但对于整个企业来说,存在多个这样的系统,不同的系统基于不同的平台、不同的数据模型,形成了⼀个个信息孤岛,对这种遗留系统的演化策略为集成。(打通信息孤岛即可)
- 继承策略:遗留系统的技术含量较低,已经满⾜企业运作的功能或性能要求,且具有较⾼的商业价值,⽬前企业的业务尚紧密依赖该系统。对这种遗留系统的演化策略为继承。在开发新系统时,需要完全兼容遗留系统的功能模型和数据模型。为了保证业务的连续性,新⽼系统必须并⾏运⾏⼀段时间,再逐渐切换到新系统上运⾏。(仅需技术维度升级,业务需求无变化)
- 改造策略:遗留系统具有较⾼的业务价值,基本上能够满⾜企业业务运作和决策⽀持的需要。这种系统可能建成的时间还很短,对这种遗留系统的演化策略为改造。改造包括系统功能的增强和数据模型的改造两个⽅⾯。系统功能的增强是指在原有系统的基础上增加新的应⽤要求,对遗留系统本身不做改变;数据模型的改造是指将遗留系统的旧的数据模型向新的数据模型的转化。(直接拿来)
8.1.2 新旧系统转换策略
- 直接转换:在原有系统停⽌运⾏的某⼀时刻,新系统⽴即投⼊运⾏,中间没有过渡阶段。采⽤这种⽅式时,⼈⼒和费⽤最省,适⽤于系统不太复杂或现有系统完全不能使⽤的场合。但是这种⽅式⻛险⾼。
- 并⾏转换:新系统和旧系统并⾏⼯作⼀段时间,经过这段时间的试运⾏后,再⽤新系统正式替换下现有系统。这种⽅式的好处是⻛险很⼩。在转换期间还可以同时⽐较新旧两套系统的性能,⽽且能够让操作⼈员得到全⾯培训,所以对于⼀些⽐较⼤的信息系统,或者处理过程⽐较复杂、数据⽐较重要的系统。并⾏转换是最常⽤的一种转换⽅式。这种转换⽅式的缺点在于,两套系统并⾏期间要有两组⼈员或两套处理⽅式同时并存,⼈⼒和费⽤消耗⽐较⼤,转换的周期⽐较⻓,⽽且难以控制新旧系统当中数据的变化。所以这就要求要做好转换计划,并且要加强管理。
- 分段转换:直接转换和并⾏转换的结合,也就是分期分批、逐步转换。⼀般⽐较⼤的系统采⽤这种⽅式⽐较合适,它能够保证软件平稳运⾏,费⽤也不太⾼,即将⼤的系统分成多个⼦系统,成熟⼀个⼦系统就切换⼀个⼦系统,核心是分期分批。如此新旧转换,震动⽐较⼩,⽤户⽐较容易接受。但是由于采取的是渐进的⽅式,会导致新旧系统的转换周期⽐较⻓。
8.1.3 数据转换与迁移
从旧数据库中抽取、转换、装载数据至新数据库。
方法:
- 系统切换前通过工具迁移
- 系统切换前采用手工录入
- 系统切换后通过新系统生成
8.2 软件维护
影响软件可维护性的因素:
- 可理解性:通过阅读源代码和相关⽂档,了解软件的功能和如何运⾏的容易程度。
- 可修改性:修改软件的难易程度。
- 可测试性:验证软件程序正确的难易程度。可测试性好的软件,通常意味着软件设计简单,复杂性低。因为软件的复杂性越⼤,测试的难度也就越⼤。
- 可靠性:⼀个软件的可靠性越⾼,需要维护的概率就会越低。
- 可移植性:将软件从⼀个环境移植到新的环境下正确运⾏的难易程度。软件运⾏环境的变化是软件维护的⼀种常⻅情形,可移植性好的软件会降低维护的概率。
软件维护类型:
- 正确性维护【修BUG】:识别和纠正软件错误/缺陷,测试不可能发现所有错误。(改正产生于系统开发阶段而在系统测试阶段尚未发现的错误)
- 适应性维护【应变】:指使应⽤软件适应环境变化【外部环境、数据环境】⽽进⾏的修改。
- 完善性维护【新需求】:为扩充功能和改善性能⽽进⾏的修改。(例如增加新功能)
- 预防性维护【针对未来】:为了适应未来的软硬件环境的变化,应主动增加预防性的新的功能,以使⽤系统适应各类变化⽽不被淘汰。经典实例:【专⽤】改【通⽤】。
9 项目管理
- 盈亏平衡分析 ⭐️
- 进度管理 ⭐️⭐️⭐️
- 软件质量管理 ⭐️⭐️
- 软件配置管理 ⭐️⭐️
9.1 盈亏平衡分析 ⭐️
- 正常情况下:销售额 = 固定成本 + 可变成本 + 税费 + 利润
- 盈亏平衡时:销售额 = 固定成本 + 可变成本 + 税费 (没有利润)
【例】Hyplus网去年卖了20000台电脑,每台售价2500元,固定成本240万,可变成本3000万,税率16%。请计算卖多少台开始盈利。
【解】根据公式可得
- 当前情况:
2500 * 20000 = 2400000 + 30000000 + (2500 * 20000) * 16% + 利润
注意“元”与“万元”单位问题
- 盈亏平衡时
固定成本 = 2400000
- 可变成本占销售额的比例:
可变成本 = (30000000 / (2500 * 20000))销售额 = 0.6销售额
尽管可变成本是可变的,但可变成本占销售额的比例是不变的。固定成本、税费同理。
税费 = 0.16 销售额
- 设盈亏平衡时卖的台数为
A
,则有:2500 * A = 2400000 + (2500 * A) * 0.6 + (2500 * A) * 0.16
- 解得:
A = 4000
- 解得:
9.2 进度管理 ⭐️⭐️⭐️
进度管理/时间管理:为了确保项目按期完成所需要的管理过程。
9.2.1 工作分解结构(WBS)
工作分解结构(Work Breakdown Structure,WBS)是项目管理中的重要工具,实为用于范围管理的结构。如下图所示:
WBS分解的基本要求:
- WBS工作包是可控和可管理的,不能过于复杂。
- 任务分解也不能过细,一般原则WBS的树形结构不超过6层。
- 每个工作包要有一个交付成果。
- 每个任务必须有明确定义的完成标准。
- WBS必须有利于责任分配。
常用WBS工作包进行活动定义,进度管理的完整流程如下所示:
- 活动定义:输入WBS工作包
- 活动排序
- 活动资源估算、活动历时估算
- 专家判断法
- 三点估算法:
(乐观时间 + 4 * 最可能时间 + 悲观时间) / 6
- 功能点估算法
- 自上而下的估算
- 自下而上的估算
- 制定进度计划
- 进度控制
9.2.2 制定进度计划
制定进度计划常使用以下两种方法
9.2.2.1 关键路径法(CPM)
关键路径法(Critical Path Method,CPM)是在制定进度计划时使用的一种进度网络分析技术。沿着项目进度网络路线进行正向与反向分析,从而计算出所有计划活动理论上的最早开始与完成日期、最迟开始与完成日期,不考虑任何资源限制。
- 总时差(松弛时间):在不延误总工期的前提下,该活动的机动时间。
- 自由时差:延误时对后续活动无任何影响的时间。
单代号网络图(前导图法,Precedence Diagramming Method,PDM)是一种用来描述项目活动之间的顺序关系和依赖关系的图表。此处称入度为0的节点为源点,出度为0的节点为终点,持续时间(即松弛时间/总时差)为已知条件。
特点与具体参数意义如下所示(S:Start;F:Finish):
计算所有结点的ES、EF、LS、LF的方法:
- 先按拓扑序列正推:
源点的ES = 0
,其他节点的ES = max{前驱节点的EF}
EF = ES + 持续时间
- 项目的最短工期即为
终点的EF
- 再按逆拓扑序列逆推:
终点的LF = 终点的EF
,其他节点的LF = min{后继节点的LS}
LS = LF - 持续时间
9.2.2.2 Gantt图
甘特图(Gantt)通过条状图来显示项目、进度和其他时间相关的系统进展的内在关系随着时间进展的情况。
用细线表示工作时间安排,用粗线表示实际完成情况。
- 优点:甘特图直观、简单、容易制作,便于理解,能很清晰地标识出每一项任务的起始时间与结束时间,一般适用比较简单的小型项目,可用于WBS的任何层次、进度控制、资源优化、编制资源和费用计划。
- 缺点:不能系统地表达一个项目所包含的各项工作之间的复杂关系,难以进行定量的计算和分析,以及计划的优化等。
9.2.3 进度控制
当活动出现问题时(如工期延误),通常可根据以下几条进行判定对整个项目的影响程度:
- 是否为关键活动:关键活动不得延误
- 偏差是否大于总时差:大于总时差时其可能变成关键路径
- 偏差是否大于自由时差:大于自由时差时会影响后续活动(较为罕见)
两种调整策略:
- 赶工:增加资源
- 快速跟进:活动并行执行
9.3 软件质量管理 ⭐️⭐️
9.3.1 影响软件质量的3组因素
- 产品修改
- 可理解性(我能理解它吗?)
- 可维修性(我能修复它吗?)
- 灵活性(我能改变它吗?)
- 可测试性(我能测试它吗?)
- 产品转移
- 可移植性(我能在另一台机器上使用它吗?)
- 可再用性(我能再用它的某些部分吗?)
- 互运行性(我能把它和另一个系统结合吗?)
- 产品运行
- 正确性(它按我的需要工作吗?)
- 健壮性(对意外环境它能适当地响应吗?)
- 效率(完成预定功能时它需要的计算机资源多吗?)
- 完整性(它是安全的吗?)
- 可用性(我能使用它吗?)
- 风险(能按预定计划完成它吗?)
9.3.2 软件质量控制与质量保证
质量保证(Quality Assurance,QA)一般是每隔一定时间(例如,每个阶段末)进行,主要通过系统的质量审计和过程分析来保证项目的质量。独特工具包括:质量审计和过程分析。(侧重对过程进行分析)
质量控制(Quality Control,QC)是实时监控项目的具体结果,以判断它们是否符合相关质量标准,制定有效方案,以消除产生质量问题的原因。(做测试)
质量保证的主要目标:
- 【事前预防】工作。
- 尽量在刚刚引入缺陷时即将其捕获,而不是让缺陷扩散到下一个阶段。
- 作用于【过程】而【不是最终产品】。
- 贯穿于【所有的活动之中】,而不是只集中于一点。
9.3.3 软件能力成熟度模型集成(CMMI)
能力成熟度模型(Capability Maturity Model,CMM)在软件开发机构中被广泛用来指导软件过程改进。该模型描述了软件成立能力的5个成熟级别,每一级都包含若干个关键过程域(Key Process Areas,KPA)。
CMMI(Capability Maturity Model Integration)分为阶段式和连续式。
阶段式所分的5级组织能力成熟度如下表所示(L1最混乱,L5最成熟):
等级 | 名称 | 特点 |
---|---|---|
L1 | 初始级 | 随意且混乱、组织成功依赖于个人能力 |
L2 | 已管理级 | 项目级可重复【建立了项目级的控制过程】 |
L3 | 已定义级 | 组织级,文档化标准化 |
L4 | 定量管理级 | 量化式管理【过程性能可预测】 |
L5 | 优化级 | 持续优化 |
CMMI连续式的内容本质上与阶段式一致,操控上更为灵活。
需求管理是CMM可重复级中的6个关键过程域之一,其主要目标为:对于软件需求,必须建立基线以进行控制,软件计划、产品和活动必须与软件需求保持一致。
9.4 软件配置管理 ⭐️⭐️
产品配置(Product Configuration)是指一个产品在其生命周期各个阶段所产生的各种形式(机器可读或人工可读)和各种版本的文档、计算机程序、部件及数据的集合。该集合的每一个元素称为该产品配置中的一个配置项(Configuration Item)。
注:配置项由开发过程直接产生,第三方产品操作手册等既有事物不属于配置项
配置项的分类:
- 基线配置项(可交付的工作成果):需求文档、设计文档、源代码、可执行代码测试用例、运行软件所需数据等
- 非基线配置项(项目管理和机构支撑过程域产生的文档):各类计划(如项目管理计划,进度管理计划)、各类报告
注:设备清单不属于配置项!
软件配置管理核心内容包括【版本控制】和【变更控制】。
9.5 软件工具与软件开发环境(SDE)
按软件过程活动将软件系统工具分为:
- 软件开发工具:需求分析工具、设计工具、编码与排错工具、测试工具。
- 需求分析工具:辅助软件需求分析活动,辅助系统分析员从需求定义出发,生成完成的、清晰的、一致的功能规范。按描述需求定义的方法可以分为基于自然语言或图形描述的工具和基于形式化需求定义语言的工具等
- 设计工具:辅助软件设计活动,辅助设计人员从软件功能规范出发,得到相应的设计规范。
- 编码与排错工具:辅助程序员进行编码活动。编码工具辅助程序员用某种程序语言编制源程序,并对源程序进行翻译,最终转换成可执行的代码,主要有编辑程序、汇编程序、编译程序和生成程序等。排错工具用来辅助程序员寻找源程序中错误的性质和原因,并确定其出错的位置,主要有源代码排错程序和排错程序生成程序两类。
- 软件维护工具:版本控制工具(VSS、CVS、SCCS、SVN)、文档分析工具、开发信息库工具、逆向工程工具、再工程工具。
- 软件管理和软件支持工具:项目管理工具、配置管理工具、软件评价工具、软件开发工具的评价和选择。
软件开发环境(Software Development Environment,SDE)是指支持软件的工程化开发和维护而使用的一组软件,由软件工具集和环境集成机制构成。
软件开发环境应支持多种集成机制,根据功能的不同,集成机制可以划分为环境信息库、过程控制与消息服务器、环境用户界面三个部分。
- 环境信息库:软件开发环境的核心,用以存储与系统开发有关的信息,并支持信息的交流与共享。环境信息库中主要存储两类信息,一类是开发过程中产生的有关被开发系统的信息,例如分析文档、设计文档和测试报告等;另一类是环境提供的支持信息,如文档模板、系统配置、过程模型和可复用构件等。
- 过程控制与消息服务器:实现过程集成和控制集成的基础。过程集成时按照具体软件开发过程的要求进行工具的选择与组合,控制集成使各工具之间进行并行通信和协同工作。
- 环境用户界面:包括环境总界面和由它实行统一控制的各环境部件及工具的界面。统一的、具有一致性的用户界面是软件开发环境的重要特征,是充分发挥环境的优越性、高效地使用工具并减轻用户的学习负担的保证。
9.6 项目管理工具
项目管理工具用来辅助软件的项目管理活动。通常项目管理活动包括项目的计划、调度、通信、成本估算、资源分配及质量控制等。一个项目管理工具通常把重点放在某一个或某几个特定的管理环节上,而不提供对管理活动包罗万象的支持。
项目管理工具具有以下特征:
- 覆盖整个软件生存周期
- 为项目调度提供多种有效手段
- 利用估算模型对软件费用和工作量进行估算
- 支持多个项目和子项目的管理
- 确定关键路径,松弛时间,超前时间和滞后时间
- 对项目组成员和项目任务之间的通信给予辅助
- 自动进行资源平衡
- 跟踪资源的使用
- 生成固定格式的报表和剪裁项目报告
注:无法指导软件设计人员按软件生存周期各个阶段的适用技术进行设计工作!
成本估算工具是一种典型的项目管理工具。
9.7 用户文档
用户文档主要描述所交付系统的功能和使用方法,并不关心这些功能是怎样实现的。用户文档是了解系统的第一步,它可以让用户获得对系统准确的初步印象。
用户文档至少应该包括下述5方面的内容:
- 功能描述:说明系统能做什么。
- 安装文档:说明怎样安装这个系统以及怎样使系统适应特定的硬件配置。
- 使用手册:简要说明如何着手使用这个系统(通过丰富的例子说明怎样使用常用的系统功能,并说明用户操作错误是怎样恢复和重新启动的)。
- 参考手册:详尽描述用户可以使用的所有系统设施以及它们的使用方法,并解释系统可能产生的各种出错信息的含义(对参考手册最主要的要求是完整,因此通常使用形式化的描述技术)。
- 操作员指南(若需要有系统操作员的话):说明操作员应如何处理使用中出现的各种情况。
系统文档是从问题定义、需求说明到验收测试计划这样一系列和系统实现有关的文档。描述系统设计、实现和测试的文档对于理解程序和维护程序非常重要。
《系统架构核心知识(2):软件工程》有1条评论