花天岑 海苔脆碎碎的 很多引用前人资料
第1、2章 软件工程基础 & 软件工程的发展
软件工程 名词解释
- 应用系统、规范、可度量的方法来开发、运行和维护软件,即将工程应用到软件
- 对(1)中方法的研究
从1950s-2000s之间的特点 简答
- 1950s:科学计算;以机器为中心进行编程;像生产硬件一样生产软件
- 1960s:业务应用(批量数据处理和事务计算);软件不同于硬件;用软件工艺的方式生产软件
- 1970s:结构化方法;瀑布模型;强调规则和纪律
- 它们奠定了软件工程的基础,是后续年代软件工程发展的支撑
- 1980s:追求生产力最大化;现代结构化方法/OOP广泛应用;重视过程的作用
- 1990s:企业为中心的大规模软件系统开发;追求快速开发、可变更性和用户价值;web应用出现
- 2000s:大规模web应用;大量面向大众的web产品;追求快速开发、可变更性、用户价值和创新
第3、4章 项目启动
如何管理团队(实验中采取了哪些办法)
- 建立团队章程
- 持续成功
- 和谐沟通
- 避免团队杀手
团队结构有哪几种
- 主程序员团队
- 主程序员完成总体构思和设计,然后分配任务给其他团队成员,并监督、验收和整合其他成员的工作完成情况
- 优势与缺点都在以主程序员为中心的交流路径
- 民主团队
- 项目经理主要负责管理,围绕着项目的计划进行。没有明确的人作为技术领导,所有团队成员都可以在自己擅长的领域担任技术领导
- 优势 人人能发挥主观能动性 高士气 高工作成就感
- 缺点 交流成本高 工作效率低
- 开放团队
- 团队可以按照自己认为合适的方式进行自我管理 管理员负责清除障碍 不知道工作进展
- 优势 激励主动性 发挥创新能力
- 没有可视度
质量保障有哪些措施(结合实验)
- 需求开发——需求评审和需求度量
- 体系结构——体系结构评审和集成测试(持续集成)
- 详细设计——详细设计评审、设计度量和集成测试(持续集成)
- 构造阶段——代码评审、代码度量、测试(测试驱动、持续集成)
- 测试阶段——测试、测试度量
配置管理有哪些活动(结合实验)
-
标识配置项
哪些需要保存和管理;设定ID等
-
版本管理
赋予初始版本号,变更时更新版本号
-
变更控制
- 提请需求变更 → 接受变更请求 → 变更评估 → 变更决策 → 执行变更 → 验证变更
-
配置审计
确定项目满足需求的功能和物理特征的程度
-
状态报告
对动态演化的配置项及度量取快照
-
软件发布管理
创建和发布可用的产品
第5章 软件需求基础
需求 名词解释
- 用户为了解决问题或达到某些目标所需要的条件或能力
- 系统或系统部件为了满足合同、标准、规范或其他正式文档所规定的要求而需要具备的条件或能力
- 对(1)或(2)中的一个条件或一种能力的一种文档化表述
需求的三个层次
-
业务需求
描述为什么要开发系统
-
用户需求
描述系统能帮用户做什么
-
系统级需求
反映一次外界与系统间的交互行为或一个系统的实现细节
需求的类型
-
需求的图谱
-
软件需求
-
功能需求 FR
不考虑物理约束的情况下,用户希望系统能执行的活动
- UR和SR都可以是功能需求
-
数据需求 DR
每个功能使用的数据信息、使用频率、可访问性要求、数据实体及其关系、完整性约束
-
性能需求 PR
速度、容量、吞吐量、负载、实时性
-
质量需求 QA
可靠性、可用性、安全性、可维护性、易用性
-
对外接口 EI
用户界面、硬件接口、软件接口、网络通信接口
-
约束 C
编程语言、硬件设备
-
第6章 需求分析方法
各种各样的图
- 用例图 UC
- 过程
- 分析目标,确定解决方向
- 寻找参与者
- 寻找用例 参与者的每个目标(目的)
- 细化用例 看具体粒度需求
- 要素:用例、参与者、关系、系统边界
- 过程
上面这个例子里,把会员管理细化成了礼品赠送、发展会员,把库存处理细化成商品出库、商品入库,把特价策略制定、赠送策略制定合并成了销售策略制定
由此引申出用例描述
重点是要体现出参与者与系统的交互 不要涉及系统内部实现
-
分析类图(概念类图/领域模型)
-
基本元素
- 对象 对具体问题域事物的抽象 类的实例
- 类
-
链接 对象之间的物理或业务联系
-
关联 类之间的某种语义联系
聚合是 part of 组合是 has a
这个x..y代表x~y *代表0~无穷
-
继承
-
过程
- 识别候选类
- 确定概念类
- 确定一个候选类为概念类的准则是:依据系统的需求,该类的对象实例的状态与行为是否全部必要
- 识别关联
- 识别重要属性
-
- 系统顺序图(交互图) SD
- 确定上下文环境
- 根据用例描述找到交互对象
- 按照用例描述中的流程顺序逐步添加消息
同步消息指发送后需要对方返回消息,才能进行下一步
异步消息不需要对方返回
组合段中
- opt 表示可选
- loop表示循环 循环条件是[循环条件]
- alt 可选分支 用虚线隔开几个分支 选择条件放在[选择条件]
- 状态图
- 确定上下文环境
- 识别状态
- 建立状态转换
- 补充详细信息,完善状态图
第7章 需求文档化与验证
为什么需要需求规格说明
- 子任务与人员之间存在复杂关系和大量沟通交流
- 在软件产品角度以系统级需求列表的方式描述软件系统解决方案,侧重独立需求和系统处理细节
对给定的需求示例,判定并修正其错误
- 技术文档写作要点:简洁、精确、易读、易修改
- 需求书写要点:使用用户术语、可验证、可行性
对给定的需求示例,设计功能测试用例
第8章 软件设计基础
软件设计 名词解释
关于软件对象的独立于软件实现(程序设计)的设计活动,既指软件对象实现的规格说明,也指产生这个规格说明的过程
软件设计的核心思想
分解与抽象
软件工程设计三个层次 主要思想
-
低层设计
屏蔽程序中复杂数据结构与算法的实现细节
-
中层设计
模块划分隐藏一些程序片段(数据结构+算法)的细节,暴露接口于外界
-
高层设计
部件与连接件是抽象类型定义,配置将它们连接起来
第9、10章软件体系结构基础 & 软件体系结构设计与构建
持续集成
- 好处
- 防止软件开发中出现无法集成与发布的情况。因为软件项目在任何时刻都是可以集成和发布的。
- 有利于检查和发现集成缺陷。因为最早的版本主要集成了简单的stub,比较容易做到没有错误。后续代码逐渐开发完成后,频繁集成又使得即使出现集成问题也能够尽快发现、尽快解决。
- 相关工具链
- 版本控制工具
- 持续集成工具
体系结构
- 部件(Component)+ 连接件(Connector)+ 配置(Configuration)
- 部件承载系统主要的计算与状态
- 连接件承载部件间交互
- 配置定义部件和连接件之间的关联方式,组织成总体结构
体系结构的风格的优缺点
-
主程序/子程序风格
将系统组织成层次结构,包括一个主程序和一系列子程序,主程序是系统的控制器,负责调度各个子程序的执行;子程序又是局部的控制器,负责调度子程序的执行
- pros
- 流程清晰,易于理解
- 强控制性
- cons
- 程序调用是强耦合的连接方式,难以修改和复用
- 不同部件可能使用隐含的共享数据,出现不必要的公共耦合
- pros
-
面向对象式风格
借鉴OO思想组织整个系统的高层结构。基于封装,对象之间协作完成系统任务
- pros
- 内部实现的可修改性
- 易开发、易理解、易复用的结构组织
- cons
- 接口与标识的耦合性
- 副作用
- pros
-
分层风格
分层风格根据不同的抽象层次,将系统组织为层次式结构。每个层次被建立为一个部件,不同部件之间通常用程序调用方式进行连接,因此连接件被建立为程序调用机制。
-
pros
- 设计机制清晰,易于理解
- 支持并行开发
- 更好的可复用性和内部可修改性
-
cons
-
交互协议难以修改
-
性能损失
禁止跨层调用
-
难以确定层次数量和粒度
-
-
-
MVC风格
模型-视图-控制风格以程序调用为连接件,将系统功能组织为模型、视图和控制三个部件。模型封装了系统的数据和状态信息,实现业务逻辑,对外提供数据服务和执行业务逻辑。视图封装了用户交互,提供业务展现,接收用户行为。控制封装了系统的控制逻辑,根据用户行为调用需要执行的业务逻辑和数据更新,并且根据执行后的系统状态决定后续的业务展现。
- pros
- 易开发性
- 适宜于网络系统的开发特征
- 视图和控制的可修改性
- cons
- 模型修改困难
- 复杂性
- pros
体系结构设计过程
- 分析关键需求和项目约束
- 选择体系结构风格
- 进行软件体系结构逻辑(抽象)设计
- 依赖逻辑设计进行软件体系结构(实现)设计
- 完善体系结构设计
- 添加构建接口
- 迭代3-6
包的原则
-
共同封闭原则 CCP
包变大,方便维护者
-
共同复用原则 CRP
包变小,方便复用者
-
重用发布等价原则 REP
重用的粒度 = 发布的粒度(一个包里的模块要重用就全部可重用)
-
无环依赖原则 ADP
包结构是无环图
-
稳定依赖原则 SDP
朝稳定的方向依赖
-
稳定抽象原则 SAP
抽象程度高的包更稳定
物理包图设计
体系结构构建之间接口的定义
-
体系结构开发集成测试用例
-
stub
模拟被代替的模块返回静态值
-
driver
模拟用户操作行为
-
第11章 人机交互设计
可用性 名词解释
包括下面几个:
- 易学性是指新手用户容易学习,能够很快使用系统
- 易记性是指使用过的用户能有效记忆/快速重新学会
- 效率指的是熟练用户使用系统完成任务的速度
- 出错率是指用户在使用系统时,会犯多少错,错误有多严重,以及是否能从错误中很容易地恢复
- 主观满意度是让用户有良好的体验
界面设计(人机交互)原则
- 简洁设计
- 人类的信息处理能力是受限的,遵循7±2原则,即一个人所能同时思考的事项上限在5~9项。人机交互设计同时给用户传递的信息自然也要遵守7±2原则,并且在有效表达交互信息的情况下越简洁越好
- 简洁设计的常见要求是不要使用太大的菜单,不要在一个窗口中表现过多的信息类别,不要在一个表单中使用太多的颜色和字体作为线索,等等。
- 一致性设计
- 用户在使用软件系统的过程中,会为任务建立精神模型。如果一个系统中相似的任务具有完全不一致的交互机制,那么会导致用户精神模型的不一致,造成不必要的麻烦和负担
- 低出错率设计
- 人机交互设计首先要帮助人们避免犯错,尽可能设计不让用户犯严重错误的系统,具体措施包括将不适当的菜单选项功能以灰色显示屏蔽,禁止在数值输入域中出现字母字符,等等。 当错误出现时,系统还要在人机交互中提供简洁、有建设性、具体的指导来帮助用户消除错误。比如,填写表单时如果用户输入了无效的编码,那么系统应该引导他们对此进行修改,而不是要求用户重新填写整个表单。出错信息应当遵循以下4个简单原则[Shneiderman1982]:①应当使用清晰的语言来表达,而不要使用难懂的代码;②使用的语言应当精练准确,而不是空泛、模糊的;③应当对用户解决问题提供建设性的帮助;④出错信息应当友好,不要威胁或责备用户。
- 系统还应该提供错误恢复和故障解决帮助手册
- 易记性设计
- 减少短期记忆负担
- 使用逐层递进的方式展示信息
- 使用直观的快捷方式
- 设置有意义的默认值
- 为不同用户群体提供差异化的交互机制
- 交互性
- 人机交互设计良好的软件系统应该具备一定的“智能”性,能够智能地给用户提供帮助,而不是被动地等待请求
- 导航 反馈
精神模型 差异性
精神模型
用户在人机交互时头脑中的任务模型
- 依据精神模型进行隐喻(metaphor)设计
差异性
新手用户、专家用户、熟练用户
- 为新手提供易学性高的GUI,为专家用户提供效率高的命令好、快捷方式、热键等
导航 反馈 协作式设计
导航
- 主动将产品和服务简明扼要地告诉用户
- 全局结构按照任务模型将软件产品的功能组织起来,并区分不同的重要性和主题提供给不同的用户
- 局部结构通过安排界面布局细节,制造视觉上的线索来给用户提供导航
反馈
- 让用户意识到行为的结果
协作式设计
-
调整计算机因素以更好地适应并帮助用户的设计方式
-
简洁设计
7±2原则,图片比文字清晰
-
易记性设计
自动补全、逐层递进、直观快捷方式、默认值
-
一致性设计
相似任务相似交互,符合精神模型
-
低出错率设计
避免犯错,消除错误
第12章 详细设计概述
详细设计的出发点
需求开发的结果(需求规格说明和需求分析模型)和软件体系结构的结果(软件体系结构设计方案与原型)
职责分配
-
类的职责主要由属性(数据)职责和方法(行为)职责组成
-
职责分配角度来看,复杂职责不可能由一个类完成,所以需要其他类协作
-
GRASP原则(General Responsibility Assignment Software Principle)
-
高内聚
-
低耦合
-
Information Expert
将职责分配给掌握必要信息的类
-
Creator
-
Controller
-
协作
- 从小到大,将小职责聚合形成大职责
- 从大到小,将大职责分配给小对象
控制风格
-
集中式
做决策的只有一个对象
-
委托式
做决策的对象不止一个,分别承担一定职责
-
分散式
无明确控制对象,每个对象只承担相对较小的职责,各个对象自治
给定分析类图、系统顺序图和设计因素描述
- 建立设计类图
- 或者详细顺序图
协作的测试
MockObject
第13章 详细设计中的模块化与信息隐藏
名词解释:解释耦合与内聚
耦合
- 耦合描述的是两个模块之间关系的复杂程度。
- 模块耦合性越⾼,模块的划分越差,越不利于软件的变更和复⽤。
内聚
- 内聚表达的是⼀个模块内部的联系的紧密性。
- 内聚性越⾼越好,越低越不易实现变更和复⽤。
耦合与内聚
对例子**,说明它们之间的耦合程度与内聚,给出理由
信息隐藏
- 基本思想
- 每个模块都承担一定的职责,对外表现一定的契约,并在这份契约下隐藏着只有这个模块知道的设计决策、秘密和决策实现的细节(特别是容易改变的细节)
- 常见的信息隐藏决策
- 根据需求分配的职责
- 内部实现机制
- 对例子**,说明其信息隐藏程度好坏
第14章 详细设计中面向对象方法下的模块化
模块化的原则
-
全局变量有害
-
优先显式表达
-
不要重复
-
面向接口编程
为每个类定义明确的契约(供接口、需接口),按照契约组织理解软件结构
-
Demeter法则 LoD
只和直接的朋友交谈
- 对于对象O的M方法,M只能调用下列对象的方法:O自己、M中参数对象、M中创建的对象、O的成员变量
-
接口分离原则 ISP
将统一的接口匹配为更独立的接口(接口给多了)
-
Liskov替换法则 LSP
子类型必须能替换掉基类型而发挥同样的作用
- 子类方法前置条件 ≤ 基类方法
- 子类方法后置条件 ≥ 基类方法
- 子类方法不变条件 = 基类方法
-
使用组合替代继承
希望复用而又无法满足LSP时
-
单一职责原则 SRP
第15章 详细设计中面向对象方法下的信息隐藏
信息隐藏的含义
需要隐藏的设计秘密
- 职责改变
- 实现改变
封装
-
- 将数据和行为同时包含在类中
- 分离对外接口与内部实现
- 需要封装的典型实现细节
- 数据和行为
- 内部结构
- 其他对象的引用
- 类型信息
- 潜在变更
为变更而设计
- 开闭原则 OCP
- 对“拓展”开放,对“修改”关闭
- 在发生变更时,好的设计只需添加新的代码而不修改原有代码就能实现变更
- 依赖倒置原则 DIP
- 细节依赖抽象而非相反
- 高层模块不应依赖低层模块,而是双方都依赖抽象
第16章 设计模式
如何实现可修改性、可扩展性、灵活性
- 将接口与实现分离
- Java实现
- 接口和实现
- 子类继承父类
- Java实现
- 可修改性:接口实现分离
- 可拓展性:可创建新的子类
- 灵活性:多态
设计模式
-
策略模式
让算法变化独立于使用算法的用户
- 减少耦合、依赖倒置
- pros
- 消除分支选择
- 可动态选择策略
- cons
- 创建对象较多
- Context提供给ConcreteStrategy的可访问成员变量可能过多
-
抽象工厂模式
-
(简单)工厂模式
将创建对象的实现封装在接口下,在改变创建的实现时不会影响客户代码
-
工厂方法模式
通过父类的工厂方法让子类继承工厂接口
- 符合OCP、SRP
-
抽象工厂模式
让类的实例化延迟到子类
- 职责抽象、接口重用
- pros
- 对产品配置更灵活
- 隔离客户和具体实现
- 产品之间有一致性,同一类很容易一起使用
- cons
- 需要提前确定具体产品的种类,变更困难
-
-
单件模式
确保只有一个实例,并提供一个全局访问点
- 职责抽象
- pros
- 避免全局变量
- 节约内存,减少GC
- cons
- 可能浪费资源/线程不安全/同步性能问题
-
迭代器模式
对遍历操作抽象
- 减少耦合、依赖倒置
- pros
- 隐藏内部实现
- 可用多种方式遍历不同结构
- cons
- 类成对增加
给定场景,应用设计模式并写出代码
给出代码,要求用设计模式改写
第17、18章 软件构造与代码设计
构造包含的活动
详细设计、编程、测试、调试、代码评审、集成与构建、构造管理
重构
修改软件系统的严谨方法,它在不改变代码外部表现的情况下改进其内部结构
测试驱动开发
要求程序员在编写一段代码之前,优先完成该段代码的测试代码
结对编程
两个程序员并排工作,协作完成相同的设计、算法、代码或测试
给定代码段,改进/发现问题
- 简洁性/可维护性
- 复杂判定
- 控制结构
- 变量使用
- 语句处理
- How to write unmaintainable code
- 防御与错误处理
单元测试用例的设计
- 契约式设计
- 如果一个函数或方法在前置条件满足的情况下开始执行,完成后能满足后置条件,那么这个函数或方法就是正确、可靠的
- 异常方式、断言方式
- 防御式编程
- 在一个方法与其他方法、操作系统、硬件等外界环境交互时,不能确保外界都是正确的,所以要在外界发生错误时,保护内部方法不受损害
- 表驱动
- 将复杂的决策包装为决策表,然后使用表驱动方式解决
第19章 软件测试
掌握白盒测试和黑盒测试的常见方法,并进行能够优缺点比较 能解释并区别白盒测试三种不同的方法:语句覆盖、分支覆盖和路径覆盖
白盒测试
-
语句覆盖
每一行
-
分支覆盖(不考)
每个判断的每个结果
-
路径覆盖
每条独立的执行路径
-
pros
- 覆盖率高
-
cons
- 覆盖路径成本、开销大
- 只能测试代码,而不知设计
黑盒测试
- 等价类划分
- 边界值分析
- 决策表
- 状态转换
- pros
- 简单
- 用户角度出发
- 基于规格,对应清晰
- cons
- 覆盖率低
给出场景,选择相应测试方法
- 给出功能需求,则写功能测试用例
- 给出设计图,则写集成测试用例(stub & driver)
- 给出方法描述,则写单元测试用例(mock object)
- JUnit
第20、21章 软件交付、软件维护与演化
软件维护的重要性
-
(用户的)问题可能会变化
使得软件需求变化,如果不维护,软件将减小服务用户的作用
-
环境发生改变
依托于特定软硬件环境,需要经常修改以适应
-
软件产品中存在缺陷
或多或少遗留缺陷,必须及时解决
开发可维护软件的方法
-
考虑软件的可变更性
分析需求的易变性;为变更进行设计
-
为降低维护困难而开发
编写详细的技术文档并保持及时更新;保证代码可读性;维护需求跟踪链;维护回归测试基线
演化式生命周期模型
-
初始开发
实现全部/部分需求,重要的是建立一个好的软件体系结构
-
演化
持续增值,演化增量有:预先安排的需求增量、新的变更请求、修正缺陷、用户与开发者互相熟悉而新增的需求
-
服务
不再增加价值,周期性修正已有缺陷
-
逐步淘汰
不再提供服务,不再继续维护
-
停止
开发者不再维护,用户不再使用
用户文档 系统文档
- 用户文档
- 为用户编写参考指南或操作教程
- 参考模式、指导模式
- 系统文档
- 更注重系统维护方面的内容,详细介绍软硬件的配置方式、网络连接方式、安全验证与授权方法、备份与容灾方法、部件替换方法等
逆向工程 再工程
- 逆向工程
- 分析目标系统,标识系统的部件及其交互关系,并使用其他形式或更高层的抽象创建系统表现的过程
- 侧重理解软件
- 再工程
- 检查和改造一个目标系统,用新的模式及其实现复原该目标系统
- 侧重修改软件
第22、23章 软件开发过程模型 软件工程职业基础
软件生命周期模型
- 将软件从生产到报废的生命周期划分为不同阶段,每段有明确的典型输入/输出、主要活动和执行人,各个阶段形成明确、连续的顺次过程
- 生命周期描述了系统的开发活动历史
软件过程模型(要求、特征描述、优缺点)
-
构建-修复模型
-
瀑布模型
按照软件生命周期组织开发活动,规定了自上而下、相互邻接的次序
-
特征
-
允许活动反复和迭代
-
重点在于要求每个活动的结果必须验证
-
文档驱动
按照文档的划分、产生和验证来规划、组织和控制开发活动
-
-
要求
- 需求成熟稳定,内容确定且不变
- 所需技术成熟可靠,没有不确定的技术难点,也没有开发人员不熟悉的技术问题
- 复杂度适中,不至于产生太大的文档负担和过粗的里程碑
-
pros
-
为软件开发活动定义了清晰的阶段划分
这让开发者能够以关注点分离的方式更好地进行那些复杂度超越个人能力的软件项目的开发活动
-
-
cons
-
对文档的过高期望具有局限性
工作量、需求易变
-
对开发活动的先行顺序假设具有局限性
立即验证不现实
-
客户、用户参与具有局限性
仅参与一个阶段
-
里程碑粒度具有局限性
过粗,不能“早发现缺陷早修复”
-
-
-
增量迭代模型
-
特征
-
在项目早期就确定项目的目标和范围,项目需求要比较成熟和稳定
-
少量不确定性和影响不大的需求变更通过迭代的方式加以解决
-
每个迭代的增量需求相对独立,被开发为产品的独立部分交付给用户
-
第一个迭代完成的往往是产品的核心部门,满足基本需求
-
需求驱动
增量需求是模型迭代规划、开发活动组织和控制的主要依据
-
-
要求
- 大规模软件开发,比较成熟和稳定的领域
-
pros
-
迭代开发
更符合软件开发的实践情况,更适用
-
并行开发
可缩短软件产品的开发时间
-
渐进交付
可加强用户反馈,降低开发风险
-
-
cons
- 由于各个构建是逐步并入已有软件体系结构的,加入构建必须不破坏已构造好的系统部分,这需要软件具备开放式的体系结构
- 并发开发规划需要完备、清晰的项目前景和范围,在不确定性太多或需求变化非常频繁的不稳定领域很难实现
-
-
演化模型
-
特征
- 将软件开发活动组织为多个迭代、并行的瀑布式开发活动
-
要求
- 不稳定领域的大规模软件系统
-
pros
-
同增量迭代模型
增量式迭代适用需求变更频繁、不确定性多的软件系统开发
-
-
cons
-
无法在项目早期阶段确定项目范围、整体计划,商务协商难以把握
-
容易退化为构建-修复方式
后续迭代依赖前导迭代,容易忽略分析与设计工作
-
-
-
原型模型
-
特征
- 大量使用抛弃式原型解决需求不确定性
- 得到清晰需求后再按照瀑布模型方式安排后续开发活动
-
要求
- 有大量不确定性的新颖领域
-
pros
- 原型方法加强了与客户、用户的交流,最终产品满意度更好
- 适用非常新颖的领域
-
cons
-
能解决风险,也可能带来新风险
原型成本高
-
不舍得抛弃“抛弃式原型”将使得质量较差的代码进入产品,导致最终产品的低质量
-
-
软件工程知识体系的知识域
- 软件需求、软件设计、软件构造、软件测试、软件维护、软件配置管理、软件管理、软件过程、软件工具和方法、软件质量
- 软件工程职业实践、工程经济学基础、计算基础、数学基础、工程基础