章节概述
重要程度仅次于架构设计,13到22分
软件开发方法
结构化方法:C语言 (面向过程)
面向对象方法:Java语言
面向服务的方法:在对象的基础上进一步粗粒度,松耦合,加上标准化形成的体系
还有一种方法是原型法,该方法一般只用于需求阶段,不是一个全流程的方法论,因此在图中与其他方法分开来。
D(结构化方法,先对最高层次问题进行定义) C(从具体的XXX开始) B(见上图)
软件开发模型
一个开发方法下有很多模型,比如瀑布模型就是结构化方法的模型
适用于需求明确的场景
最大特点是分阶段,每个阶段都有产出物
增量:一块一块补充,比如先画鱼,再画气泡,最后画珊瑚
迭代:逐步补充细节,比如先画轮廓,再画草图,最后上色
特点是风险分析
V模型特点是测试贯穿始终,前面每一个步骤做后面的测试计划
前面所有模型都是结构化模型,喷泉模型是面向对象的模型
速度快,成本低,可靠性高(多处复用)
SDLC:瀑布模型
CBSD:构建组装模型
英文缩写是 UP
(有的地方也称RUP)
用例就是功能块的描述
C:风险分析是螺旋模型的特色
RUP就是 UP 统一过程
B(细化阶段任务概念) A(迭代的特点)
敏捷方法
B 敏捷是小步快跑,适合小团队小项目
BD 见敏捷开发方法中的定义
敏捷开发方法的一种,也是应用最广的一种
Product Backlog:产品待办列表
Sprint Backlog:冲刺待办事项列表
Sprint 4 Weeks:假设的冲刺时间
Daily metting: 日会议 / Sprint burn down:烧尽图 / Sprint review metting:短跑审查会议
逆向工程
BC 基本概念
需求工程
上午1-2分,下午案例题基本会涉及
需求验证产出物:SRS:软件规格说明书
需求基线是评审过后的SRS
A-见上一页PPT,需求管理和需求开发是2个维度,因此不能说是对需求开发的管理,而是对变更控制、版本控制等的管理
B-应该是 需求开发包括:XXXX
C-需求开发还没有到开发成果这一层级
故选D
需求获取
设计要求比如约定基于oracle数据库设计
QFD:质量功能展开(Quality Function Deployment)
需求分析
SA
这里就是一个数据流图,上面是一个总体的,下面是细化的数据流图,也称之为0层图
数据流图的四大要素:数据流、加工、数据存储、外部实体
状态图转换图
ER图
用例图,对象图,通信图,顺序图,活动图都是面向对象的UML图
DFD是数据流图
ER图表示数据模型,故选CD
OOA
面向对象
继承是面向对象编程中的一种机制,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。
泛化是一种面向对象分析与设计中的概念,它描述了一种一般化与特殊化的关系。
从本质上来说,泛化和继承是同一关系的不同视角,继承是从实现的角度描述子类对父类的代码复用,而泛化是从概念模型的角度描述这种关系。
在 UML(统一建模语言)中,泛化关系用一条带空心三角形箭头的直线表示,从子类指向父类。例如,“汽车” 和 “轿车” 之间存在泛化关系,“汽车” 是更一般的概念,而 “轿车” 是 “汽车” 的一个特殊类型。
需求定义
C 概念题,C选项是原型法的适用范围
需求验证
验收标准尽可能提前确认,否则交付扯皮
需求变更
世界上永远不变的是变化
D 按逻辑推断,变更描述之后,变更实现之前一般需要对变更进行分析和成本估算,因此D最合适。
B 常识排除法。
在需求变更以及项目管理等相关场景中,CCB 是 “变更控制委员会(Change Control Board)” 的英文缩写。
变更控制委员会是一个负责审查、评估、批准、推迟或否决项目变更请求的正式组织。其成员通常由项目涉及的多方面利益相关者组成,可能包括项目负责人、客户代表、技术专家、业务分析师、项目经理等。
软件系统建模
系统设计
人机界面设计
A
结构化设计
多扇入:指的是一个模块被多个其他模块调用的情况。多扇入意味着该模块的功能具有较高的通用性和复用性,被多个不同的模块所依赖。这样可以减少重复代码的编写,提高代码的可维护性和开发效率。
少扇出:表示一个模块调用其他模块的数量较少。少扇出有助于降低模块的复杂度和模块之间的耦合度。如果一个模块扇出过多,即调用了大量其他模块,那么这个模块的内部逻辑可能会变得复杂,难以理解和维护。而且,当被调用的模块发生变化时,该模块受到影响的可能性也会增加。
面向对象设计
基本过程
设计原则
要尽可能让其他对象减少了解,那么应该降低该类对属性和方法的访问权限而不是提高,故选C
设计模式
固定的方式解决特定的问题
基本设计决策是高层决策,因此第一空应该是 架构模式(A);底层的模式是 惯用法(B);第三空是和语言(C++)有关,即语言相关,故是惯用法(B)
创建性模式
理解记忆速记关键字,下面是一些增强理解的例子
- 工厂方法模式:想象你经营一家宠物商店,专门售卖不同种类的宠物,比如猫和狗。你定义了一个 “宠物创建方法” 作为通用接口,但不具体说怎么创建。当有顾客想要一只猫时,就有一个 “猫创建器” 来按照这个方法创建猫;要是想要狗,就有 “狗创建器” 来创建狗。这里 “宠物创建方法” 是抽象的,而 “猫创建器”“狗创建器” 是具体的实现,它们决定了创建的具体宠物类型,这就是工厂方法模式。
- 抽象工厂模式:还是这家宠物商店,除了售卖宠物,还销售与宠物相关的配套产品,比如猫有猫窝和猫食,狗有狗窝和狗粮。你可以把宠物和它的配套产品看作是一个产品族。现在有一个 “宠物及用品工厂” 接口,里面规定了生产宠物和生产对应用品的方法。具体的 “猫工厂” 就按照这个接口的要求,生产猫和猫的用品;“狗工厂” 则生产狗和狗的用品。这个模式强调的是创建一系列相关的产品,即一个产品族,这就是抽象工厂模式。
- 构建器模式:比如你要组装一台电脑。电脑由多个部件组成,像主板、CPU、内存、硬盘等。构建器模式就像是一个专业的电脑组装工人,他有一套详细的组装步骤。首先,他会准备好各个部件(相当于创建对象的各个部分),然后按照特定的顺序将它们组装起来(逐步构建对象),最终得到一台完整的电脑。不同的 “组装工人”(具体的构建器)可能有不同的组装方式,但都能完成电脑的组装,这种将对象的构建和表示分离的方式就是构建器模式。
- 原型模式:假设你是一名设计师,设计了一款精美的玩具模型。现在你需要制作多个一模一样的玩具模型。你可以先制作一个原型,然后通过复制这个原型来快速得到多个相同的玩具模型,而不需要重新设计和制作每一个模型。在软件中,原型模式就是通过复制已有的对象实例来创建新的对象,新对象会拥有与原型相同的属性和状态,这样可以提高对象创建的效率。
- 单例模式:想象一家公司的总经理,整个公司只有一个总经理,无论在公司的哪个部门、哪个地方,提到总经理都是指同一个人。在程序中,单例模式就是确保一个类只有一个实例存在,并且提供一个全局访问点来获取这个实例。比如日志记录器,在一个系统中通常只需要一个日志记录器来记录所有的日志信息,使用单例模式就可以保证整个系统中只有一个日志记录器实例,避免了资源的浪费和混乱。
结构性模式
理解记忆速记关键字,下面是一些增强理解的例子
- 适配器模式:你有一家电器店,店里既有国内标准插头的电器,也有国外标准插头的电器。而国内的插座只能适配国内标准插头。为了能让国外标准插头的电器也能在国内插座上使用,你引入了转换插头(适配器)。这个转换插头一端是国外标准插头的接口,另一端是能插入国内插座的接口。通过这个转换插头,就可以让原本不兼容的国外电器和国内插座协同工作了。在软件中,适配器模式就是将一个类的接口转换成客户希望的另一个接口,使原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- 桥接模式:你经营着一家绘画工作室,工作室既可以绘制不同风格的画(比如油画、水彩画),又可以选择不同的画布材质(比如棉布、亚麻布)。如果把绘画风格和画布材质直接绑定在一起,那么每增加一种风格或材质,都需要大量的代码修改。于是你采用桥接模式,将绘画风格和画布材质分离,让它们各自独立变化。通过一个桥梁(抽象类和其实现类的关联),使得不同的绘画风格可以搭配不同的画布材质。比如,油画风格可以在棉布上绘制,水彩画风格也可以在亚麻布上绘制,这样就增加了灵活性和扩展性。
- 组合模式:你在管理一个公司的组织架构。公司由多个部门组成,部门下面又有小组,小组里有员工。你可以把公司看作是一个大的整体(根节点),部门、小组是中间的部分(分支节点),员工是最底层(叶子节点)。使用组合模式,你可以以相同的方式处理公司、部门、小组和员工。比如,你可以对整个公司进行人员统计,也可以对某个部门或小组进行统计,甚至对单个员工进行信息查看。无论是处理单个元素(员工)还是处理组合元素(部门、公司),都可以使用统一的操作方式。
- 装饰模式:你有一家蛋糕店,基础款的蛋糕(被装饰者)很普通。为了吸引顾客,你可以给蛋糕添加各种装饰,比如奶油、水果、巧克力等(装饰者)。每个装饰都可以为蛋糕增加不同的口味和外观。你可以根据顾客的需求,一层一层地为蛋糕添加装饰,而且添加装饰的顺序不同,最终得到的蛋糕也不一样。在软件中,装饰模式就是动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
- 外观模式:你要组装一台电脑,组装电脑需要涉及到很多复杂的操作,比如安装主板、连接电源、安装 CPU、插入内存条等等。对于不熟悉电脑组装的人来说,这些操作很繁琐。于是你开发了一个智能组装设备(外观类),这个设备将所有复杂的组装步骤封装起来,用户只需要按下一个按钮,智能设备就会自动完成所有的组装操作。外观模式就是为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。
- 享元模式:你在开发一个围棋游戏,棋盘上有很多黑白棋子。每个棋子的属性(颜色、形状等)基本相同,只是位置不同。如果为每一个棋子都创建一个独立的对象,会占用大量的内存。使用享元模式,你可以将棋子的公共属性(如颜色、形状)提取出来,共享使用,只在需要时为每个棋子设置不同的位置属性。这样,相同属性的棋子就可以共享同一个对象,减少了内存的占用。享元模式主要用于减少创建对象的数量,以降低内存占用,提高性能。
- 代理模式:你是一位明星,有很多工作邀约,比如广告拍摄、演出活动等。但是你没有时间和精力去处理这些琐碎的事务,于是你聘请了一位经纪人(代理)来帮你处理。经纪人会代替你去和广告商、演出主办方沟通,处理相关的事务,只有在一些重要的决策上才会找你。在软件中,代理模式就是为其他对象提供一种代理以控制对这个对象的访问,代理对象可以在客户端和目标对象之间起到中介的作用。
抽象跟实现分离
组合模式的整体和部分都会实现同一个接口
中介和代理和类似,但是中介是做多方之间的中间人,起建立联系的作用(房产中介)。
代理是将一方的职能给到另外一个人,起中间代理作用(二手房东)。
中国人民银行、中国银联就是起的中介者作用,并不负责具体银行业务,而是起银行间业务对接作用
行为性模式
理解记忆速记关键字,下面是一些增强理解的例子
- 职责链模式:
假设你在一家公司提交了一笔报销申请。这个申请首先会到你的直属主管那里,主管有权限审批一定金额以下的报销,如果金额在他的审批范围内,他就直接处理了;如果金额超出了他的权限,他会把申请转交给部门经理。部门经理同样有自己能审批的金额范围,若在范围内就处理,否则再转交给更高层的财务总监。财务总监也按照类似的方式处理,直到申请被批准或者被驳回。在这个过程中,报销申请就像在一条由不同审批者组成的链条上传递,每个审批者都有自己处理请求的职责,这就是职责链模式。它使得多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。- 命令模式:
想象你在玩一款遥控赛车游戏。游戏里的遥控器就是一个关键部分。每个遥控器上的按钮(比如前进、后退、左转、右转按钮)都对应着一个命令。当你按下前进按钮时,实际上是向赛车发送了一个 “前进” 的命令,赛车接收到这个命令后就会执行前进的动作。在软件中,命令模式就是将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作等。比如在文本编辑软件中,“撤销” 操作就可以看作是执行之前保存的命令对象来恢复之前的状态。- 解释器模式:
你在开发一个简单的计算器程序。用户可以输入一些简单的数学表达式,比如 “2 + 3”“5 - 1” 等。你的程序需要理解这些表达式的含义并计算出结果。为了实现这一点,你可以使用解释器模式。你会定义一些规则来解释这些表达式,比如数字是什么、运算符是什么,以及如何根据这些规则来计算表达式的值。对于输入的 “2 + 3”,程序会按照定义的规则识别出 “2” 和 “3” 是数字,“+” 是加法运算符,然后根据加法的计算规则得出结果是 “5”。解释器模式就是给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。- 迭代器模式:
假设有一个图书馆,里面有很多书架,每个书架上又有很多书。你想要遍历图书馆里的所有书籍,查看每一本书的信息。如果没有一个统一的方式,直接去操作书架和书会很复杂。这时可以使用迭代器模式。你可以为图书馆创建一个迭代器,这个迭代器就像是一个向导,它知道如何按照一定的顺序(比如从第一个书架的第一本书开始,依次往后)去访问每一本书。通过迭代器,你不需要了解图书馆内部书架和书的具体组织方式,只需要使用迭代器提供的方法(比如 “下一本”)就可以方便地遍历所有书籍了。迭代器模式就是提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。- 中介者模式:
想象一个大型的机场调度系统。机场里有很多部门和设备,比如航空公司、塔台、雷达系统、登机口、行李处理系统等。这些部门和设备之间需要进行大量的交互和协调工作。例如,飞机到达后,需要通知行李处理系统去卸载行李,同时要安排登机口让乘客下飞机。如果这些部门和设备之间直接相互通信和协调,会形成非常复杂的网状结构,管理和维护起来很困难。这时引入一个中介者(机场调度中心),所有的部门和设备都只与调度中心进行通信。调度中心负责接收各个部门的信息,并根据这些信息进行统一的协调和安排。比如调度中心根据飞机的到达时间和登机口的使用情况,安排合适的登机口,并通知相关部门做好准备。中介者模式就是用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
解释器模式的一个典型场景是 工作流引擎
理解记忆速记关键字,下面是一些增强理解的例子
备忘录模式
想象你正在使用一款文字处理软件撰写一篇重要的论文。在写作过程中,你不断地对文章进行修改和编辑。有时候,你可能会觉得刚刚的某个版本更好,想要恢复到之前的状态。这时,软件的 “撤销” 功能就派上用场了。每一次你保存文档的一个版本(可以手动保存,或者软件自动定时保存),就相当于创建了一个备忘录,它记录了文档在那个时刻的内容、格式、排版等所有状态信息。当你点击 “撤销” 按钮或者选择恢复到某个历史版本时,软件就会从对应的备忘录中读取信息,将文档恢复到之前的状态。这就是备忘录模式,它允许你在需要时将对象恢复到之前的某个特定状态,就像给对象的状态拍了 “快照” 并能随时还原一样。
观察者模式
假设你是一个社交媒体平台的用户,你关注了很多有趣的博主。这些博主发布新内容(比如文章、视频、图片等)就是一种状态变化。当博主发布新内容后,平台会自动通知所有关注该博主的用户(也就是观察者),用户们就会收到消息提醒,知道有新的内容可以查看了。在这个过程中,博主是被观察的对象(主题),而关注博主的用户就是观察者。观察者们通过 “关注” 这个动作与博主建立了联系,一旦博主的状态(发布新内容)发生变化,观察者们就能及时得到通知并做出相应的反应(查看新内容)。这就是观察者模式,它定义了对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。
状态模式
你正在玩一款冒险类游戏,你的游戏角色有多种状态,比如正常状态、受伤状态、中毒状态、隐身状态等。在不同的状态下,角色的行为和能力是不同的。例如,在正常状态下,角色可以正常移动、攻击敌人;当角色受伤时,移动速度可能会减慢,攻击力也可能下降;如果角色中毒了,生命值会持续减少;而在隐身状态下,敌人可能无法发现角色。游戏程序会根据角色当前所处的状态来决定角色可以执行哪些操作以及如何响应玩家的指令。比如当角色处于隐身状态时,玩家发出攻击指令,游戏会根据隐身状态的规则来处理,可能不会立即暴露角色,而是以某种特殊的方式进行攻击。状态模式就是将对象的不同状态及其对应的行为封装到不同的类中,使得对象在不同状态下能够表现出不同的行为,并且可以方便地在不同状态之间进行切换。
策略模式
你计划在周末去旅行,你需要选择一种合适的出行方式。你有几种选择:可以选择乘坐飞机,这种方式速度快,但费用较高;也可以选择坐火车,它相对便宜,而且能欣赏沿途风景,但耗时可能较长;还可以选择自驾,这样行程更自由,但需要自己开车,会比较累。你根据自己的实际情况(比如时间是否充裕、预算多少、是否喜欢驾驶等)来决定选择哪种出行方式。在这里,每种出行方式就相当于一种策略,你根据不同的条件和需求来选择合适的策略。在软件中,策略模式就是定义一系列算法(就像这里的不同出行方式),将每个算法封装成一个对象,使得它们可以相互替换,这样在运行时可以根据具体情况选择合适的算法来执行,从而提高了软件的灵活性和可维护性。
模板方法模式
你在一家餐厅工作,负责制作不同种类的菜肴,比如意大利面和炒饭。制作意大利面和炒饭的过程有一些相似的步骤,比如都需要准备食材(如蔬菜、肉类等)、烹饪食材、调味等。但是在具体的准备食材种类和烹饪方式上又有所不同。为了提高工作效率,你可以制定一个制作菜肴的通用模板方法。这个模板方法包含了准备食材、烹饪、调味等基本步骤,但是对于准备哪些具体的食材以及如何烹饪等细节部分,留给具体制作意大利面或炒饭的方法去实现。例如,在制作意大利面时,准备的食材可能有意大利面条、番茄酱、肉酱等,烹饪方式是将面条煮熟后与酱料混合;而制作炒饭时,准备的食材有米饭、鸡蛋、火腿等,烹饪方式是先炒鸡蛋和火腿,再加入米饭翻炒。模板方法模式就是在一个抽象类中定义一个算法的骨架,而将一些步骤延迟到子类中实现,子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
访问者模式
假设有一个动物园,里面有各种各样的动物,如老虎、猴子、大象、长颈鹿等。同时,有不同类型的游客来到动物园,比如动物学家、摄影师和普通游客。动物学家会关注动物的习性、品种等专业信息,他们可能会对每一种动物进行详细的观察和记录;摄影师则更关心动物的外观和姿态,寻找最佳的拍摄角度来拍摄动物的照片;普通游客只是简单地欣赏动物,觉得有趣就行。对于动物园里的每一种动物来说,不同类型的游客对它们的操作和关注点是不同的。通过访问者模式,我们可以将不同游客对动物的操作封装到不同的访问者类中。当游客访问某种动物时,动物会根据游客的类型调用相应的访问者类中的方法,从而实现不同游客对动物的不同操作。这样,即使以后增加了新的游客类型(比如动物饲养员),也不需要修改动物类的代码,只需要添加新的访问者类并实现相应的操作即可,提高了系统的扩展性和灵活性。
例题
A 首先排除D,没有这种类型。对象实例化就是产生对象的过程,因此是创建型
D 一个类只有一个实例,典型的单例模式
C 创建自定义对象,所以应该是创建型模式,排除A(外观模式)D(单例模式)。由于提到不确定性,应该更倾向于原型模式
B 对象构建与表示分离,典型的构建器模式
软件测试
测试类型
灰盒测试就是既有白盒测试也有黑盒测试
白盒测试不适合于大型应用测试
白盒测试主要应用在单元测试,黑盒主要应用于功能测试
等价类划分,和样本类似,从一个类里面选区某一个具有代表性的对象进行测试。比如从普卡用户(0-2000)、银卡用户(2000-5000)、金卡用户(5000+)分别选取一个值进行测试,如800,3000,8000。
边界值分析很简单就是取边界情况,比如0,2000,5000,10000
动态测试,是由计算机运行结果来判断的测试。因此桌面检查,代码审查都是人工方式排除,只有A选型符合
由第一空知道动态是哪些后又可以排除法,得到C
测试阶段
A - 虽然说的是单元测试,但是自顶向下的单元测试已经是集成测试了,集成测试中自顶向下需要桩模块,自底向上需要驱动模块,因此该选项正确。
B - 自顶向下需要桩模块
C - 驱动模块用来模拟上层模块
D - 从上到下依次是 驱动模块、被测模块、桩模块,因此桩模块不是用来调用被测模块的。
- 强度测试:重点是长时间维持在高强度或极端条件下,观察系统的稳定性和可靠性,比如系统是否会出现内存泄漏、资源耗尽等问题,侧重于系统的耐久性。
- 负载测试:关注不同负载水平下系统的性能表现,如响应时间、吞吐量、资源利用率等指标的变化,强调的是系统在正常或预期负载范围内的性能特性。
- 压力测试:主要考察系统在超出正常负载,接近或达到极限负载时的行为,目的是找出系统的性能瓶颈、崩溃点或不可接受的性能下降点。
- 容量测试:核心是确定系统能够处理的最大数据量或业务量,例如数据库的最大存储容量、系统能够支持的最大用户数量等,重点在于确定系统的容量极限。
这里第一空是限定条件下看系统运行情况,因此是强度测试A。(压力测试应该是在极限情况下找性能瓶颈)第二空D
面相对象的测试
了解即可,基本没有咋考到
软件调试
原因排除法是从问题原因进行演绎(推测),是正向的。
回溯法是从出错的位置回溯,是反向的。
系统转换计划
了解即可
高水平低价值,为何低价值主要是存在信息孤岛,因此需要打通信息孤岛,需要
集成
(集成到业务中,给其带来价值?)低水平高价值,需要保留其高价值部分,因此需要
继承
其功能模型(DFD)和数据模型(ER图)(不是拿来就用的意思)高水平高价值,只需
改造
其功能模型(DFD)和数据模型(ER图)(增强的意思)
D
系统切换前采用手工录入适用于小数据系统
系统运行与维护
.
增加新功能-完善性维护 A
修正系统错误-改正性维护(正确性维护)D
为未来-预防性维护 C
本文链接: http://www.ionluo.cn/blog/posts/44125bff.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!