整理了软工二除了名词解释以外的重点 ww
by 陈欣怡
# 软件工程发展历史
1950s:科学计算;以机器为中心进行编程;像生产硬件一样生产软件。
1960s:业务应用 (批量数据处理和事物计算);软件不同于硬件;用软件工艺的方式生产软件。
1970s:结构化方法;瀑布模型;强调规则和纪律。它们奠定了软件工程的基础,是后续年代软件工程发展的支撑。
1980s:追求生产力最大化;现代结构化方法 / 面向对象编程广泛应用;重视过程的作用。
1990s:企业为中心的大规模软件系统开发;追求快速开发、可变更性和用户价值;web 应用出现
2000s:大规模 web 应用;大量面向大众的 web 产品;追求快速开发、可变更性、用户价值和创新。
# 项目启动
# 如何管理团队
- 建立团队章程
- 持续成功
- 和谐沟通
- 避免团队杀手
# 团队结构有几种?
- 主程序员
- 民主团队
- 开放团队
# 质量保障 / 配置管理
# 质量保障有哪些措施?
- 需求开发 —— 需求评审和需求度量
- 体系结构 —— 体系结构评审和集成测试 (持续集成);
- 详细设计 —— 详细设计评审、设计度量和集成测试 (持续集成)
- 构造阶段 —— 代码评审、代码度量、测试(测试驱动和持续集成)
- 测试阶段 —— 测试、测试度量
*要及时的根据保障计划进行质量验证,质量验证的方法主要有评审、度量、测试三种。
# 配置管理有哪些活动?
- 标识配置项:确定应该被保留的部分,并且给予他们确定标识,包含配置项的特征,包括生产者、基线建立时间、使用者等。
- 版本管理:为配置项赋予版本号,管理分支和多版本情况。
- 变更控制:以可控、一致的方式进行变更处理,包括对变更的评估、协调、批准或拒绝、实现和验证。
- 配置审计:验证配置项的完整性、正确性、一致性和可追踪性。
- 状态报告:反映当前的配置状态。
- 软件发布管理:将配置项发布到开发活动之外,例如发布给客户。
# 需求层次 / 需求类型
# 如何书写用例
用例正常流程:在常见和符合预期的条件下,系统与外界的行为交互序列
名称:
参与者:
触发条件:(可以为空)
前置条件:(可以为空)
正常流程:
- 用户行为 + 系统行为形成的行为交互序列
- 用户:选择、输入、结束……
- 系统:提示、显示、记录、计算、更新……
后置条件:(可以为空)
# 区分需求的三个层次
- 业务需求(Business Requirement)
- 业务需求是高层次的解决方案和系统特性、系统开发的战略出发点、高层次的需求,描述为什么要开发系统。
- Eg. 在系统使用 3 个月后,销售额度应该提高 20%(期望,没有从软件角度进行描述,业务需求)
- 用户需求(User Requirement)
- 执行具体任务的用户对系统所能完成任务的期望,描述了系统能帮用户做什么(直接用户、间接用户)
- Eg. 在系统要帮助收银员完成销售处理
- 系统级需求(System Requirement)
- 需求分析模型:用户对系统行为的期望,每个系统级需求反映了一次外界与系统的交互行为,或者系统的一个实现细节(和用户需求有着很大的区别)
- Eg. 在接到客户经理的请求后,系统应该为客户经理提供所有会员的个人信息。
# 判断需求的类型
功能需求:和系统主要共作相关的需求,即在不考虑物理约束的情况下,用户希望系统所能够执行的活动,这些活动可以帮助用户完成任务。功能需求主要表现为系统和环境之间的行为交互。
- Eg. 在接到客户经理的请求后,系统应该为客户经理提供所有会员的个人信息。
数据需求(属于功能需求的一种,DR):功能需求的补充:如果在功能需求部分明确定义了相关的数据结构,那么就不需要再行定义数据需求。数据需求是需要在数据库、文件或者其他介质中存储的数据描述,通常包括下列内容:
- 各个功能使用的数据信息;
- 使用频率;
- 可访问性要求;
- 数据实体及其关系;
- 完整性约束;
- 数据保持要求。
- Eg. 系统需要存储的数据实体及其关系为图 6-14 的内容。(数据实体及其关系)
- Eg. 系统需要存储 1 年内的销售记录和退货记录。(数据保持)
性能需求:系统整体或系统组成部分应该拥有的性能特征,例如 CPU 使用率、内存使用率等。
- 速度:系统完成任务的时间(所有用户查询必须在 10s 内完成)
- 容量:系统能存储的数据量(系统因该能够存储至少 100 万个销售信息)
- 吞吐量:系统在连续的时间内完成的事务数量(解释器每分钟应该能够至少解析 5000 条没有错误的语句)
- 负载:系统可以承载的并发工作量(系统应该允许 50 个营业服务器同时从集中服务器上进行数据的上传或下载)
- 实时性:严格的实时要求(系统监测到异常时,监视器必须在 0.5s 内发出警报,和故障警报不一样,故障不是系统的正常功能)
质量需求(QA):系统为了满足规定的及隐含的所有要求而需要具备的要素称为质量
- 可靠性:在规格时间间隔内和规定条件下,系统或部件执行所要求能力的能力。(在进行数据的下载和上传中,如果网络故障,系统不能出现故障。能不能检测网络中断,并且进行恢复)
- 可用性:软件系统在投入使用时可操作和可访问的程度或能实现其指定系统功能的概率。(系统的可用性要达到 98%)
- 安全性:软件组织对其程序和数据进行未授权访问的能力,未授权的访问可能是有意,也可能是无意的。(VIP 顾客只能查看自己的个人信息和购买记录)
- 可维护性:软件系统或部件能修改以排除故障、改进性能或其他属性或适应变更了的环境的容易程度,包括可修改性(Modifiability)和可扩展性(Extensibility)。(如果系统要增加新的特价类型,要能够在 2 个人月内完成)
- 可移植性:系统或部件能从一种硬件或软件环境转换至另外一种环境的特性。(集中服务器要能够在 1 人月内从 Window 7 操作系统更换到 Solaris 10 操作系统。)
- 易用性:与用户使用软件所花费的努力及其对使用的评价相关的特性。(使用系统 1 个月的收银员进行销售处理的效率要达到 10 件商品 / 分钟。)
- 往往会有形容词和副词
对外接口:系统和环境中其他系统之间需要建立的接口,包括硬件接口、软件接口、数据库接口等等。
- 接口的用途
- 接口的输入输出
- 数据格式
- 命令格式
- 异常处理要求
- Eg. 注册使用 Google Maps API
约束:进行系统构造时需要遵守的约束,例如编程语言、硬件设施等
- 系统开发及运行的环境(包括目标机器、操作系统、网络环境、编程语言、数据库管理系统等,Eg. 系统使用 Java 语言进行开发)
- 问题域内的相关标准(包括法律法规、行业协定、企业规章等。)
- 商业规则:(用户在任务执行中的一些潜在规则也会限制开发人员设计和构建系统的选择范围)
- Eg. 已过保质期的食品不能销售
- Eg. 顾客可以使用美元付款
# 例题
# 写用例 T1
(1)
以 ATM 存款功能为例
- 业务需求:提供存款功能
- 用户需求:系统允许用户存入现金并记录在对应银行卡中
- 系统级需求:在用户放入现金后,系统应该能够清点现金数额,并在清点完毕后,显示数额,请用户核对
(2)
性能需求:
- 速度:系统应该在 3s 内完成单个操作,查询操作响应速度不得超过 1s
- 负载:系统应该允许地区内所有 ATM 及同时从服务器上进行运作
- 实时性:系统应该在 0.5 秒内同步数据
质量属性:
- 安全性:系统应该保护用户的存取款信息不被非法用户获取;
- 易用性:系统应该保证操作界面容易上手
对外接口:
- 系统与数据库接口:如果发生异常,要抛出异常并回滚
约束:用 java 开发
数据需求:系统需要存储用户 3 年以内的详细存取款记录信息
# 写用例 T2
功能需求,与系统主要功能相关
数据需求,规定了数据描述和数据的输入格式
该功能涉及 2 个用例
- 用例 1:手工创建询价单
- 参与者:采购人员
- 主要流程:
- 采购人员登入系统,输入供应商、产品等信息
- 系统记录供应商、产品、库存等信息
- 采购人员结束创建过程
- 系统生成并展示采购询价单
- 用例 2:自动生成询价单
- 参与者:库管员
- 前置条件:仓库经理已设置产品的再订货规则
- 主要流程:
- 库管员登录系统
- 系统确认权限
- 库管员点击运行排程
- 系统按照再订货规则和销售订单及库存情况自动生成采购询价单,并显示
# 判断需求类型
需求描述 | 需求类别 | 备注 |
---|---|---|
系统需要存储一年内的销售记录 | 数据需求 | - |
系统应该能够存储 3 年的交易数据 | 性能需求 | - |
系统使用之前,需要对收银员进行 10 天的专门培训 | 其他需求(包括硬件需求、人力需求。) | 在交付之前 |
经过 10 天培训的收银员就能够熟练使用系统 | 质量需求(易用性) | - |
反映了用户与系统的交互细节 | 系统需求 | - |
反映了用户与系统的交互 | 用户需求 | - |
在存储设备发生故障时,系统要在 10 秒内发现 | 质量需求(可靠性需求) | 故障是非正常状态,还一种系统需求。 |
在存储设备发生故障时,系统要在 0.5 秒内向用户发出警报 | 功能需求 | 故障不是系统的正常状态 |
检测到病人异常后,监控器必须在 0.5 秒内发出警报 | 性能需求 | - |
该软件管理工具的开发过程自身必须符合 CMMI-4 的评估 | 过程需求 | 是软件自身 |
该软件管理工具软件必须帮助项目管理者进行开发管理工作,以通过 CMMI-4 的评估 | 用户需求 | - |
系统能够为用户提供库存分析报告、商品 / 利润报告和过期商品报告 | 用户需求 | - |
产品在发布 1 年之后内,必须在出版的 A、B、C 三个产品评论刊物中被评为最可靠产品。 | 业务需求 | 相当与一个目的 |
系统必须能够与 Oracle 数据库交互。 | 约束 | Oracle 是系统的一个环境,环境本身在约束部分,比如 Tomcat 等等 |
开发团队需要给出 SRS 文档。 | 过程需求 | - |
使用扫描仪扫描文件,传递回的数据为 pdf 格式文件。 | 对外接口 | 软件和扫描仪之间的交互 |
商品的标识由 0-24 位字母、数字混合组成的字符串。 | 数据需求 | - |
商品标识的类型要能够在 0.5 个人月内更改为长整型。 | 质量需求 | 可移植性 |
# 需求题
# 知识点
# 用例图
用例、参与者、关系、系统边界
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617184315668.png" alt="image-20230617184315668" style="zoom: 25%;" />
# 分析类图(概念类图)
根据用例的文本描述,识别候选类
- 名词分析、行为分析
筛选候选类,确定概念类
- 根据系统需求
- 是否有状态 + 行为
- 只有行为:
- 只有状态:其他概念类的属性
识别关联
继承
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617190122995.png" alt="image-20230617190122995" style="zoom: 25%;" />
依赖
人靠船渡河
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/20200224105438325.png" alt="20200224105438325" />
关联
聚合 - has a
组合 - contains a
实现
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617190442546.png" alt="image-20230617190442546" style="zoom:25%;" />
识别重要属性
# 系统顺序图
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617202807628.png" alt="image-20230617202807628" style="zoom: 33%;" />
# 状态图
# 题型
# 为什么需要需求规格文档?结合实验说明
- 方便交流:软件开发过程中,子任务与人员之间存在错综复杂的关系,存在大量的沟通和交流,所以要编写软件开发中要编写不同类型的文档,每种文档都是针对项目中需要广泛交流的内容。因为软件需求需要进行广泛交流,所以要把需求文档化。
- 跟踪和度量:需求规格说明是在软件产品的角度以系统级需求列表的方式描述软件系统解决方案,书写需求规格说明,可以建立管理控制的基线,方便任务分配,制定工作计划,进行跟踪和度量。
- 过程管理:在实验中,需求规格的重要性不只体现在结果上,还包括中间过程,在书写需求规格过程中,才真正把问题域的问题和分析模型的成果转化为系统级需求,方便小组成员真正明确需求,个人认为在这个阶段包含一部分的需求在发现和完整化。
# 需求示例修改
# 用例选择错误
- 用例粒度
- 不要将用例细化为单个操作,如将用户管理细化为增加、修改和删除,需要联合才能体现业务价值
- 不要将同一个业务目标细化为不同用例,比如特价策略制定和赠送策略制定,合并为销售策略制定
- 将明显不同的业务事件分开,如会员管理用例应该细化为发展会员和礼品赠送
- 用例价值
- 登录、数据验证、连接数据库没有价值,不作为用例
- 是否和系统产生交互
- 顾客不是参与者,不与系统产生交互
# 技术文档撰写错误
- 技术文档写作要点(简洁,精确,易读,易修改)
- 简洁:动词名词 + 辅助词,不要使用复杂长句、形容词和副词。
- 精确:避免歧义。
- 易读(查询):有效使用引言、目录、索引等能够增强文档易读性的方法,使用系统化的方式组织内容信息,提供文档内容的可读性。
- 易修改:使用相同的语句格式组织相关联或相似的信息;使用列表组织独立、并列的信息;使用编号表达繁杂信息之间的关系。引用而不是重复
- 需求书写要点(使用用户术语,可验证,可行性)
- 需求规格说明文档书写要点(充分利用标准的文档模板,保持所以内容位置得当;保持文档内的需求集具有完备性和一致性;为需求划分优先级)
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230618230832033.png" alt="image-20230618230832033" style="zoom: 50%;" />
# 设计功能测试用例
以需求为线索,开发测试用例套件,确定输入 / 输出,开发测试用例。
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230618231039954.png" alt="image-20230618231039954" style="zoom: 50%;" />
# 例题
画用例图
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619213715825.png" alt="image-20230619213715825" style="zoom: 33%;" />
# 软件设计
# 软件设计的核心思想
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619180916831.png" alt="image-20230619180916831" style="zoom:50%;" />
抽象:横向上将系统分解为几个相对简单的子系统以及各子系统之间的关系
分解:纵向上聚焦各子系统的接口(区别于实现,各子系统之间交互的契约),可以分离接口和实现,使得人们更好地关注软件系统本质,降低复杂度
# 软件工程有哪三个层次?各层的主要思想是什么?
高层设计:基于反映软件高层抽象的构建层次,描述系统的高层结构、关注点和设计决策
中层设计:更加关注组成构件的模块的划分、导入 / 导出、过程之间的调用关系或者类之间的协作
低层设计:深入模块和类的内部,关注具体的数据结构、算法、类型、语句和控制结构等体系结构
# 体系结构风格的优缺点
# 主程序子程序
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619180944570.png" alt="image-20230619180944570" style="zoom: 33%;" />
优点:
- 流程清晰,易于理解
- 强控制性
缺点:
- 程序调用是一种强耦合的连接方式,非常依赖交互方的接口规格,这会使得系统难以修改和复用
- 程序调用的连接方式限制了各部件之间的数据交互,可能会使得不同部件使用隐含的共享数据交流,产生不必要的公共耦合,进而破坏它的 “正确性” 控制能力
应用:
- 系统功能依层次分解为多个顺序执行步骤的系统
- 结构化分析(自顶向下或自底向上)建立的软件系统
# 面向对象
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619180955810.png" alt="image-20230619180955810" style="zoom:33%;" />
优点:
- 内部实现的可修改性
- 易开发、易理解、易复用的结构组织
缺点:
- 接口的耦合性
- 标识的耦合性
- 副作用 P155
- 对象的重入问题
- A\B 均使用 C,B 对 C 的修改可能产生对 A 未预期的影响
应用:
- 基于数据分解和组织的软件系统
- 基于抽象类型建立起来的软件系统
# 分层
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619181024015.png" alt="image-20230619181024015" style="zoom:33%;" />
优点:
- 设计机制清晰,易于理解(网络通信协议的分层)
- 支持并行开发
- 更好的可复用性与内部可修改性
缺点:
- 交互协议难以修改
- 性能损失
- 难以确定层次数量和粒度
应用:
- ISO 网络通信模型
- TCP/IP 网络通信模型
# MVC
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619181031716.png" alt="image-20230619181031716" style="zoom:33%;" />
模型、视图、控制分别是业务逻辑、表现、控制的三种不同内容抽象
优点:
1)易开发性
2)视图和控制的可修改性
3)适宜于网络系统开发的特征
缺点:
1)复杂性
2)模型修改困难
# 包的原则
内聚
重用发布等价原则 (REP):
重用的粒度就是发布的粒度
相关联的包一起发布,几个协作类组成一个包
共同封闭原则 (CCP)
- 包中所有类对于同一类性质的变化应该是共同封闭的,一个变化若对一个包产生影响,则对该包中的所有类产生影响,而对于其他包不造成任何影响。
- 包尽可能大,和 CRP 互斥
共同重用原理 (CRP)
- 一个包中的所有类应该是能够共同重用(用到)的
耦合
无环依赖原则 (ADP): 在包的依赖关系图中不能存在环。必须是有向无环图。
修改方式:
- DIP,依赖接口,实现接口
- 分离包
稳定依赖原则 (SDP): 朝着稳定 (别人的修改不影响我) 的方向进行依赖
- 尽可能减少对别人的依赖
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619000347253.png" alt="image-20230619000347253" style="zoom: 25%;" />
稳定抽象原则 (SAP): 包的抽象程度应该和其稳定程度一致
(再根据图理解)
# 体系结构开发集成测试用例
- 大爆炸式集成
- 增量式
- 自顶向下集成
- 自底向上集成
- 三明治式
- 持续集成
- 尽早集成
- 频繁集成
- 持续集成需要用到版本控制工具和持续集成工具
桩模仿的是下层模块,用来测试上层;
而驱动则模仿的是上层模块,用来测试下层。
所以,驱动需要利用下层提供的接口,来实现其模仿的模块的功能
# 包图
分层风格,分为 presentation, logic, data 三层
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617210904543.png" alt="image-20230617210904543" style="zoom:33%;" />
# 逻辑设计
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617210644440.png" alt="image-20230617210644440" style="zoom: 33%;" />
增加登录 logicController
增加 RMI,分离服务端和客户端
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617210951337.png" alt="image-20230617210951337" style="zoom:33%;" />
# 物理设计
- presentation
- 建立界面
- 界面类库包
- 跳转逻辑
mainui
包
- 建立界面
- logic
- 不希望高层直接依赖低层
- 增加
businesslogicservice
包:ui 和 logic 都会依赖,前者调用,后者实现
- 增加
- 一些初始化与业务逻辑层上下文工作
- 增加
utilitybl
包,其他 bl 包均会依赖
- 增加
- 不希望高层直接依赖低层
- data
- 持久化,会导致重复代码
- 增加
databaseutility
包,依赖JDBC
类库包或IO
类库包
- 增加
- 持久化,会导致重复代码
- 层间
- logic 与 data
- 数据问题:将 data 分为客户端的
daraservice
与服务器端的data
,都依赖于RMI
类库包 - 传递问题:
PO
包, persistent object
- 数据问题:将 data 分为客户端的
- presentation 与 logic
- 传递问题:
VO
包, value object
- 传递问题:
- logic 与 data
- 无环依赖原则
- 消除互环
- 实现接口和调用:将 commodity 和 member 的抽象接口放入 sales
- 消除互环
# 进程图
# 关键类图
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617212538885.png" alt="image-20230617212538885" style="zoom: 25%;" />
# 持久化 PO
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617212639834.png" alt="image-20230617212639834" style="zoom: 33%;" />
# 接口
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617212629496.png" alt="image-20230617212629496" style="zoom:33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619002551819.png" alt="image-20230619002551819" style="zoom:33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619002616472.png" alt="image-20230619002616472" style="zoom:33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617212815523.png" alt="image-20230617212815523" style="zoom:33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619001948234.png" alt="image-20230619001948234" style="zoom: 33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619002019713.png" alt="image-20230619002019713" style="zoom:33%;" />
# 题型
# 例题
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/B6560233E0EC284010D15FBE0958E659.png" alt="B6560233E0EC284010D15FBE0958E659" style="zoom:33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/228FCE451618BE49AA24BA64D1763C27.png" alt="228FCE451618BE49AA24BA64D1763C27" style="zoom:33%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/7EAD4AB8E29608669443A5325DFCA9B4.png" alt="7EAD4AB8E29608669443A5325DFCA9B4" style="zoom: 50%;" />
展示层和逻辑层的数据交互用 VO,函数名诸如 addXXXX
getXXXXbyId
逻辑层和数据层的交互用 PO,函数名诸如 get
、 insert
、 find
(都是我猜的)
# 人机交互(界面设计)
# 知识点
简洁设计:
- 7+-2 原则
- 不在一个窗口展示过多信息,功能清晰明确
- 摘要图片优于文字描述
- 不要大菜单,不要过多的信息类别,不要太多的颜色和字体
一致性设计:
- 依据精神模型,让系统中相似的任务有一致的交互机制(按钮位置等等)
低出错率设计:
避免犯错
数值域不可输入字符
友好建议:
提供简洁的指导帮助⽤户消除错误,用户输入错误信息,系统会标注出来,而不是让用户重写整段代码
语言清晰,表达准确,建设性帮助,友好,不应责备
易记性
- 减少用户的记忆负担
- 使用逐层递进的范式展示信息
- 使用直观的快捷方式
- 设置有意义的默认值
所见即所得
使用导航
导航的目的就是为用户提供一个很好的完成任务的入口,好的导航会让这个入口非常符合人的精神模型
全局导航控件包括窗口、菜单、列表、快捷方式、热键等等。
局部导航通过安排布局细节,制造视觉上的线索来提供导航。
反馈
按钮点击等在视觉(声音)上给用户反馈,让用户意识到行为的结果
反馈的目的是提示用户交互行为的结果,但不能打断用户工作时的意识流。对用户思考和反应时间的把握。
协作式设计
人和计算机是人机交互的两方,其中人的因素是比较固定的,一定时期内不会发生大的变化,所以要让两者交互顺畅,就需要让计算机更多地适应人的因素,这也是人机交互设计以用户为中心的根本原因。这种调整计算机因素以更好地适应并帮助用户的设计方式被称作为协作式设计。
** 精神模型:** 就是用户进行人机交互时头脑中的任务模型。人机交互设计需要依据精神模型进行隐喻设计,依据隐喻将控件功能与已知的熟悉事物联系起来,实现界面视觉提示和系统功能之间的知觉联系
差异性:对不同用户群体的任务模型是有差异的,所以对他们的人机交互设计也要有差异。按照用户群体自身的特点,可以将其划分为新手用户、专家用户和熟练用户
# 题型
能够列出 5 个界面设计的注意事项,并加以解释
例子违反了哪些条界面设计原则
分析上图,它们分别体现(或违反)了哪些人机交互设计原则?请详细解释这些原则(10 分)
# 例子
对左图:
- 违反了简洁设计,交互信息过多,摘要图片比描述文字更清晰
- 违反了一致性原则,按钮位置不一致,如 cancel 和 ok 的位置,不符合精神模型(已存在相似系统)
- 违反了低出错率原则,选择的进度条不明显
- 违反了易记性原则,没有清晰的导航或直观的快捷方式,没有减少记忆负担,将所有 certificate 列出,用户不容易记住
- 符合简洁设计原则,模块结构清晰,没有提供过多的信息,符合 7+2 的原则,颜色简单
- 符合一致性原则,符合用户的精神模型,与已有类似的界面相似
- 符合易用性原则,递进式地展示菜单,使用直观的快捷方式,减轻用户的记忆负担
- 所见即所得
# 详细设计
# 知识点
# 详细设计的出发点
软件详细设计是在软件体系结构设计之后进行,以需求开发的结果 (需求规格说明和需求分析模型) 和软件体系结构的结果 (软件体系结构设计方案与原型) 为出发点。
# 职责分配
职责是执行任务(操作职责)或维护某些数据(数据职责)的义务。
- 行为职责通常由方法来履行。
- 数据职责通常由属性来完成。
- 可能会涉及到类之间的协作。
职责分类
- 属性职责:对象的状态
- 行为职责:对象的行为
通过职责建立静态设计模型
职责分配可以从不同的抽象层次开始:职责是可以被分解的,职责分解是组件分解的基础
职责分配可以帮助实现高内聚,低耦合,确保不同模块职责没有重合,当且仅当数据和方法有利于模块职责时才添加。
(关系)依赖 < 关联 < 聚合 < 组合 < 继承
# GRASP 一般职责分配软件模式
- 特点:
- 低耦合:分配一个职责要保证低耦合度
- 高聚合:分配一个职责的时候要保持类的高聚合度
- 信息专家:将一个职责分配给专家 - 拥有履行职责所必须的信息的类
- 创建者:创建规则在后面
- 控制者:控制规则在后面(避免大多数信息由一个类发出、组件相对较小、行为职责和数据绑定、职责单一)
- 拇指原则:当有替代设计选择时,请仔细研究替代方案的内聚和耦合影响,以及未来可能对替代方案的演变压力。选择具有良好内聚性、耦合性和稳定性的替代方案。
- 信息专家:统一提供对外的接口,而不是某一个具体的接口,数据和行为不要分开
- 创建规则:如果有以下情况,则由创建者分配 B 类创建 A 类实例的职责:
- B 聚合了 A 对象
- B 包含了 A 对象
- B 记录了 A 的实例
- B 要经常使用 A 对象
- 当 A 的实例被创建,B 具有传递给 A 的初始化数据(也就是 B 是创建 A 的实例这项任务的信息专家)
- 在有选择的地方,更喜欢 B 聚合或包含 A 对象
# 协作
从小到大,将对象的小职责聚合成大职责
从大到小,将大职责分配给每个小对象
同时运用这两种方法,共同来完成对协作的抽象
绘制顺序图
表达软件的动态模型
# 控制风格
- 集中式控制风格:做决策的只有一个对象
- 委托式控制风格:做出决策的对象不只有一个,职责的分解决定了控制对象的层次。
- 分散式控制风格:无明确的控制对象,每个对象只承担想对较小的职责,完全靠各个对象自治的方式来实现大的职责
可查看书上类图
# 协作的测试
- Mock Object:类间协作的桩程序
- 与体系结构集成的 stub 类型桩程序不同,Mock Object 要求自身的测试代码更简单,不用测试就能保证正确性
# 设计类图
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619002304546.png" alt="image-20230619002304546" style="zoom: 33%;" />
# 详细顺序图
# 例题
# 耦合 / 内聚
# 知识点
判断是哪种耦合 / 内聚,可以接受吗?如何修改?
耦合:内容、公共、重复不可接受,控制、印记可以接受,数据最理想
内聚:偶然和逻辑不可接受,时间、过程、通信可以接受且不可避免,功能和信息最理想
# 例子
# 内聚
偶然内聚:完全不相关
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617150604278.png" alt="image-20230617150604278" style="zoom:33%;" />
逻辑内聚:执行一系列操作,具体操作交给具体模块(如 swtich),解决控制耦合的方法
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 36-16548720493677.png" alt="img" style="zoom: 50%;" />
时间内聚:执行一系列和时间有关的操作,比如构造方法和析构方法
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 37-16548720493678.png" alt="img" style="zoom: 67%;" />
过程内聚:执行一系列与步骤顺序有关的操作
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 38-1676529494850-2214.png" alt="img" style="zoom: 80%;" />
通信内聚:执行一系列与步骤顺序有关的操作,并且这些操作是在相同的数据结构上。
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 39-1676529494850-2215.png" alt="img" style="zoom:50%;" />
功能内聚:模块只执行一个操作或达到一个单一目的
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 40-16548720493689.png" alt="img" style="zoom:50%;" />
信息内聚:模块进行许多操作,各自有各自的入口,相互独立,且在相同的数据结构上完成操作。
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 41-165487204936810.png" alt="img" style="zoom:50%;" />
# 耦合
数据耦合:两个模块的所有参数是同类型的数据项(发送正好)
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 45-1676529494850-2216.png" alt="img" style="zoom:50%;" />
印记耦合:两个模块共享一个数据结构,但是只用了其中一个部分(发送多了)
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 29-165487204936911.png" alt="img" style="zoom: 67%;" />
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 30-1676529494851-2217.png" alt="img" style="zoom:67%;" />
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 44-1676529494851-2218.png" alt="img" style="zoom:50%;" />
控制耦合:一个模块给另一个模块传递了控制信息(除了数据还有控制信号,并且违反了单一职责原则)
- 主要是 case 中不应该出现具体实现的代码,应该抽象成方法
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 43-1676529494851-2219.png" alt="img" style="zoom:50%;" />
重复耦合:一个模块有逻辑上相同的重复代码
公共耦合:模块之间共享全局数据结构
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 32-165487204937013.png" alt="img" style="zoom:50%;" />
<img src="https://eaglebear2002.github.io/2022Spring - 软件工程与计算 II / 软件工程与计算 II-24 - 复习提纲 / 46-1676529494851-2221.png" alt="img" style="zoom:50%;" />
内容耦合:一个模块直接修改另一个模块的内容(成员变量、函数等)
# p226-227 习题
功能内聚
印记耦合,(通信内聚?)
通信内聚,数据耦合
控制耦合
时间内聚,拆成三个函数,在 init 当中调用
# 信息隐藏
# 基本思想
每个模块都隐藏了重要设计决策的实现,因此只有该模块的组成部分才知道详细信息:特别是如果存在所有可能的设计更改的列表,则隐藏假设列表
# 两种常见的信息隐藏决策
- 按职责分解 - 根据需求分配的职责,因为实践表明,需求是经常变化的,频率和幅度都很大;
- 按算法分解 - 内部实现机制,常见的变化主题包括硬件依赖,输入输出形式,非标准语言特征和库,负责的设计和实现,复杂的数据结构,复杂的逻辑,全局变量。数据大小限制等。
# 对例子 ***,说明其信息隐藏程度的好坏
- 封装数据和行为
- 封装内部结构
- 封装对象的引用
- 委托隐藏了与其他对象的协作
- 封装类型信息
- 封装可能存在的变更
# 题型
# 例题
View 负责了展示,Logic 负责了统计求和。Data 负责各个数据的存储。
# 设计规则
# 规则罗列及详解
# 降低隐式耦合
- 全局变量是有害的
- 简洁
- 不要有代码重复
# 降低访问耦合
面对接口编程
接口分离原则(ISP)/ 也叫接口最小化原则
将大的接口拆解成几个小的接口。
这样可以有效避免出现不必要的依赖。
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619232606193.png" alt="image-20230619232606193" style="zoom: 25%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619232624872.png" alt="image-20230619232624872" style="zoom:25%;" />
迪米特法则
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619232649297.png" alt="image-20230619232649297" style="zoom: 25%;" /><img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619232811718.png" alt="image-20230619232811718" style="zoom:25%;" />
# 降低继承耦合
LSP 里氏替换原则
子类型必须能够替换掉基类型而起同样的作用。
保持父类的方法接口不变;保持父类方法的实现语义不变;(不能用 vector 实现 stack)
只要调用一个接口,不论哪种子类或者父类本身,都可以完成相同语义的工作
解决方案:在父类中添加方法或者函数,或者拆分接口
使用组合代替继承
# 提高内聚
- 集中信息和行为
- 单一职责原则
<img src="C:/Users/QUAS/AppData/Roaming/Typora/typora-user-images/image-20230620083444560.png" alt="image-20230620083444560" style="zoom:33%;" />
# 其他
封装 —— 分离接口与实现
含义:
- 将数据和行为同时包含在类中
- 分离对外接口与内部实现
实现细节:
- 封装数据和行为(不要每个私有数据都有 getter 和 setter,也不要暴露存储数据和推导数据 calculateAge)
- 封装内部结构(public Position getPosition 代替 public Position [] getPositions)
- 封装其他对象的引用(新对象的引用返回)
- 封装类型信息(隐藏子类,只知道共性类别)
- 封装潜在变更
OCP 开闭原则
对扩展开放,对修改关闭,添加新的代码而不需要修改原来的代码就能实现变更
只要是发生了需求变更需要修改原有代码,则违反此原则
DIP 依赖倒置
高级模块不应该依赖于低级模块,两者都应该依赖于抽象
为具体类建立抽象接口并分离该接口是中实现 DIP 的基本手段
# 例题
对给定的示例,发现其所违反的原则,并进行修正
# 里氏替换
里氏替换原则例题
(1)指出两个关于继承的设计是否合理?是否违反设计原则?
(2)对两段代码,如果合理,请解释其合理性,如果违反,请解释该原则,并修改
第一个不合理,栈不能继承向量,向量很多方法栈用不到
第二个合理,雇员继承人
# 设计模式
# 如何实现可修改性、可扩展性、灵活性
- 实现的可修改性:涉及到大的场景的修改
- 对已有实现的修改
- 例如:修改现有促销策略
- 实现的可扩展性(DIP & OCP)
- 对新的实现的扩展
- 例如:增加一条新的促销策略(策略模式)
- 实现的灵活性
- 对实现的动态配置
- 例如:动态修改更改某商品对应促销策略
将接口和实现分离的实现方法:
- 通过接口和实现该接口的类完成接口与实现的分离
- 通过子类继承父类,将父类的接口和子类的实现分离
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619213834497.png" alt="image-20230619213834497" style="zoom: 25%;" />
# 模式体现的设计原则
策略模式:
- 减少耦合 - 减少策略的使用类和策略的实现类的直接的耦合
- 依赖倒置 - 策略的使用类依赖的是策略的接口,而非策略的实现类
迭代器:
- 减少耦合 - 减少遍历的使用类和遍历的实现类直接的耦合
- 依赖倒置 - 遍历的使用类依赖的是策略的接口,而非遍历的实现类
# 策略模式
p266
# 抽象工厂模式
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230620081015370.png" alt="image-20230620081015370" style="zoom:33%;" />
# 单件模式
# 迭代器模式
# 构造
# 构造包含的活动
详细设计、编程、测试、调试、代码评审、集成与构建、构造管理
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619174826608.png" alt="image-20230619174826608" style="zoom:25%;" />
# 契约式编程
如果一个函数或方法,在前置条件满足的情况下开始执行,完成后能够满足后置条件。
异常和断言
# 防御式编程
当一个方法与其他方法、操作系统、硬件等外界环境发生交互时,不能保证外界环境都是正确的,外界发生错误时,保护方法内部不受损害。
异常和断言
常见问题有:
- 输入参数
- 其他对象初始化
- 是否为 null
- 网络连接是否正常
# 表驱动
- 数据的保存一定要能够节省计算(核心思想),用空间换取时间
- eg:包括所得税中的速算
- 声明多个一维数组,存储系列同类型的边界条件
- 然后通过 for 循环,统一用一个下标 i 访问所有数组的值
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617234759568.png" alt="image-20230617234759568" style="zoom:33%;" />
# 代码问题
易维护性:
- 缩进表达逻辑结构
- 将相关逻辑组织在一起
- 用空行分割逻辑
- 语句分行
- 命名要规范要有意义
- 要有注释
- 不要硬编码
- 减少重复代码
可靠的代码:
小型任务分解
复杂决策的转化
- 使用新的布尔变量简化复杂决策
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230620001120202.png" alt="image-20230620001120202" style="zoom:25%;" />
- 使用有意义的名词简化复杂决策 (抽象成判断的函数)
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230620001145817.png" alt="image-20230620001145817" style="zoom: 25%;" />
- 表驱动
数据使用
- 变量与命名相符、单变量单目的、限制全局变量、不要用突兀的数字
明确依赖关系(可以写到注释里面 @see)
# 例题
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619174045086.png" alt="image-20230619174045086" style="zoom: 25%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619174224981.png" alt="image-20230619174224981" style="zoom: 50%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230619174255200.png" alt="image-20230619174255200" style="zoom: 25%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/AgAABYrp6SuwGDnqfW9DjKpwd8h6yn3J.png" alt="AgAABYrp6SuwGDnqfW9DjKpwd8h6yn3J" style="zoom:50%;" />
代码缺点:
- 直接通过字符串来返回结果,硬编码不利于修改,复用。
- 即使使用字符串是合理,也应该在 ifelse 中设置 output 的值。再统一调用 writer.print (output)。
# 测试
书写格式:ID 输入 输出
# 黑盒测试
等价类
- 分为若干子集,选取少量具有代表性的数据作为测试用例
边界值
- 错误往往发生在等价类的边界
决策表
状态转换
根据状态转换图,建立测试对象的转换表,状态转换的每一类都应该被设计为测试用例
- 输入:方法 + 当前状态
- 输出
# 黑白盒比较
白盒优点:覆盖率高;发现的缺陷较多
白盒缺点:测试开销大;不能检验需求规格
黑盒优点:测试效率高;可以检验需求规格
黑盒缺点:覆盖率低:发现的缺陷少
# 白盒测试 - 分支覆盖的测试用例设计
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230618000347094.png" alt="image-20230618000347094" style="zoom: 25%;" />
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617221320621.png" alt="image-20230617221320621" style="zoom: 80%;" />
# 语句覆盖
确保测试用例的每一行代码都被覆盖到
# 条件覆盖
每个判断的每个结果都被至少满足一次
# 路径覆盖
确保程序每条独立的路径都被执行一次
# 圈复杂度计算
p316
<img src="https://quasdo.oss-cn-hangzhou.aliyuncs.com/img/image-20230617234548002.png" alt="image-20230617234548002" style="zoom:33%;" />
法一:
法二:
评判:
- 0-5:子程序还不错
- 6-10:简化子程序
- 大于 10:拆分子程序并调用
# 例题
# 软件生命周期模型
# 知识点
# 瀑布模型
瀑布模型是按照软件生命周期模型将软件开发活动组织为需求开发、软件设计、软件实现、软件测试、软件交付和软件维护等活动,并且规定了它们自上而下、相互邻接的次序。
优点:为软件开发活动定义了清晰的阶段划分(包括输入 / 输出、主要工作及其关注点),这让开发者能够以关注点分离的方式更好地进行那些复杂度超越个人能力的软件项目的开发活动。
缺点:
- 对文档的过高的期望具有局限性
- 对开发活动的线性顺序假设具有局限性
- 客户、用户的参与具有局限性:成功的项目开发需要客户、用户从始至终的参与,而不仅仅是一个阶段。
- 里程碑粒度具有局限性:里程碑粒度过粗,基本丧失了 “早发现缺陷早修复” 这一思想
适用于比较成熟,没有技术难点的软件
# 增量迭代模型
增量迭代模型是在项目开始时,通过系统需求开发和核心体系结构设计活动完成项目对前景和范围的界定,然后再将后续开发活动组织为多个迭代、并行的瀑布式开发模型。
少量的不确定性和影响不大的需求变更通过迭代的方式加以解决。
优点:
- 迭代式开发更加符合软件开发的实践情况,具有更好的适用性;
- 并行开发可以帮助缩短软件产品的开发时间;
- 渐进交付可以加强用户反馈,降低开发风险。
缺点:
- 由于各个构件是逐渐并入已有的软件体系结构中的,所以加入构件必须不破坏已构造好的系统部分,这需要软件具备开放式的体系结构。
- 增量交付模型需要一个完备、清晰的项目前景和范围以进行并发开发规划,但是在一些不稳定的领域,不确定性太多或者需求变化非常频繁,很难在项目开始就确定前景和范围。
适用范围:适用于大规模软件系统的开发。
# 演化模型
演化模型将软件开发活动组织为多个迭代、并行的瀑布式开发活动。演化模型能够更好地应对需求变更,更适用于需求变更比较频繁或不确定性较多的领域。
优点:
- 使用了迭代式开发,具有更好的适用性,尤其是其演化式迭代安排能够适用于那些需求变更比较频繁或不确定性较多的软件系统的开发;
- 并行开发可以帮助缩短软件产品的开发时间;
- 渐进交付可以加强用户反馈,降低开发风险。
缺点:
- 无法在项目早期阶段建立项目范围,所以项目的整体计划、进度调度、尤其是商务协商事宜无法准确把握;
- 后续迭代的开发活动是在前导迭代基础上进行修改和扩展的,这容易让后续迭代忽略设计分析与设计工作,蜕变为构建 - 修复方式。
适用与不稳定领域的大规模软件系统开发