Schwertlilien
As a recoder: notes and ideas.

高级软件工程-复习+习题回忆

高级软件工程复习

下面是老师说的考试重点。

  1. Ruby编程语言的一些特征需要了解
  2. 要能读得懂Ruby程序
  3. Git的基本命令操作知道
  4. Rails的MVC工作机理需要清楚,Model, Controller, View各司什么职责明白
  5. BDD的User Story需要会,SMART要求能理解
  6. TDD的Rspec读得懂会补充
  7. 重点:最常用的几种设计模式知道、理解、会用;SOLID原则是什么?什么情况下是违背的。

SOA(Service Oriented Architecture)面向服务架构:所有组件都设计为服务、且服务可以组合的软件架构。

特点:一个服务直接访问另外一个服务的数据时可能出现不稳定。

image-20250105222415157
4

软件质量(Quality Assurance)

软件质量保障(QA):确保软件开发的质量,改进优化过程,提高效率。

一般通过测试来保证软件质量

image-20250105223053228
image-20250105223104016
image-20250105223612569

这个题的24,怎么选

提高开发者生产力:简洁性、合成、重用和工具

4种技术

  1. 通过表达的简洁化:语法更短更易读、抽象级别提高(高级程序设计语言、自动内存管理、动态脚本语言:计算反射和元编程)
  2. 程序合成(Program Synthesis):生成代码以适应情境和删除条件测试
  3. 重用 (Reuse):重用旧代码vs.编写新代码
    • 重用技术(按历史顺序排列)
      • 过程和函数-procedure, function
      • 标准化库(重用单一任务)-standard library
      • 面向对象编程-Object Oriented Porgramming: 重用和管理任务集合
      • 设计模式-Design Pattern: 实现可以不同, 但重用的是通用策略
  4. 自动化和工具 (Automation & Tools)

DRY-Don't Repeat Yourself

在一个系统中,每一知识必须有一个单一的、明确的、权威的表示。

P&D软件过程模型

P&D: 计划与文档

  1. 编码前,项目经理制定计划
  2. 撰写计划各阶段的详细文档
  3. 根据计划来度量进展
  4. 项目的变更必须反映在文档中,并可能反映在计划中
瀑布模型 螺旋模型 Rational统一软件开发过程,RUP
image-20250105224414183 image-20250105224447980 image-20250105224610698
缺点:当客户看到开发出来的产品时,通常想要对软件产品进行改变,这时就会遇到麻烦。 image-20250105224638912 image-20250105224626865
--- image-20250105224545598 image-20250105224620339

P&D需要大量的文件和计划,并依赖于经验丰富的经理。

image-20250105224840820

Aglie敏捷开发

个体与交互 vs过程 & 工具

工作软件vs全面文档化

客户协作vs合同谈判

响应变更vs遵从计划

image-20250105225016936

敏捷强调测试驱动开发(TDD)来减少错误,记录用户故事来验证客户需求,用速度来度量进展。

设计模式:捕捉/刻画重复出现问题的常见结构化解决方法。

Client/Server: 架构级设计模式,Web是C/S架构,面向请求/应答方式。

image-20250105225641483

Ruby/Rails框架中,Rails复杂管理防止篡改cookie

2
image-20250105230001028

三层架构:表示层-逻辑(应用)层-持久层

image-20250105230143422
image-20250105230215458

MVC(Model-View-Controller)

提倡痩视图和控制器、不要在视图中添加功能代码。

image-20250105230256794
image-20250105230313058

image-202501052316506832,比如嵌入式系统

在MVC中,用户可以进行的每个交互都是由控制器中的动作来处理的

Ruby语言中的方法(method)处理这种交互。

image-20250105230935122
image-20250105231000999
image-20250105231028015

Git

使用版本控制系统

命令 说明
checkout 从库中拷贝一个版本的代码
commit 将代码写回仓库

Git基础

命令 说明
git init 创建仓库
git config 配置仓库
git clone <url> 获取一个仓库
image-20250105232206795 将变更录入仓库
git log 查看变更历史
git pushgit pull 与远程仓库同步
git branch <branch_name>git checkout <branch_name> 创建分支
git mergegit rebase (branch 1)在branch2上执行 合并分支
git rest --hard <commit_id> 回退
git revert <commit_id> 撤销

Git配置

Cit配置 配置用户信息 配置文本编辑器 查看配置信息
git config --global / -- local git config --global user.name "John Doe" git config --global core.editor emacs git config --list
--- git config --global user.email johndoe@example.com --- ---

Rails

Rails是使用Ruby语言建立的流行编程框架。

Ruby:现代动态脚本编程语言。

面向对象函数式自动内存管理动态类型mix-in闭包用于重用、元编程、程序合成

Rails遵守:(依赖于Ruby的语言特性:自省和元编程闭包模块(混合)

  1. 约定优于配置:命名遵守某些约定、不需要配置文件
  2. DRY:提取公共功能的开发原则:"在一个系统中,每一知识必须有一个单一的、明确的、权威的表示。"

CRUD: create, read, update, delete

Ruby->Database

ActiveRecord::Base子类化。--将模型连接到数据库+CRUD

image-20250106234738821

ActiveRecordcreate 方法是new方法与save方法的组合。

  • save!操作失败会抛出异常。
image-20250106234905336

Rails解决方案: 开发、测试和生产环境都有自己的数据库。

迁移:用脚本描述更改,可以跨数据库类型进行安全快速移植。

image-20250106235136067
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建迁移
rails generate migration CreateMovies

# 将迁移应用于开发环境
rake db:migrate

# 完成代码测试后,将迁移应用于生产环境,应用迁移还包括在数据库中记录哪些迁移脚本已经用过了
heroku rake db:migrate

# 新模型,创建模型文件
app/models/model.rb

# 更新测试数据库schema
rake db:test:prepare

# 最终部署
heroku rake db:migrate
RUD
image-20250106235806802

Ruby->Routes

image-20250106235958231
image-20250107000020038

Ruby->Views

创建表单---

BDD(行为驱动设计)

BDD:在开发之前开发期间询问有关应用行为的问题,以减少误解。

需求以用户故事的方法记录。

image-20250107000422401

创建用户故事

SMART故事

SMART 说明
Specific 明确:每个场景可测试
Measurable 可度量:已知合理输入,预期结果存在
Achievable 可达成(理想情况:一个迭代下完成)
Relevant 相关性(5个为什么)image-20250107000911118
Timeboxed 时间框(知道何时放弃)

Cucumber测试

通过Cucumber,用户故事成为验收测试和集成测试用例

1
2
3
4
5
# 运行一个功能特征测试
cucumber filename

# 运行所有测试
rake cucumber

绿:通过的步骤

黄:还未实现的

红:失败的--然后步骤是蓝色的

目标:使所有步骤通过

显式/隐式、命令式/声明式场景

显式需求:验收测试的一部分

隐式需求:显式需求的逻辑结果、集成测试

  1. 将电影列表
  2. 电影按时间顺序还是字母顺序排列?

命令式场景:初始用户故事,有许多步骤,指定逻辑顺序,直达所需结果。

如果很多用户故事是命令式,那就不DRY

声明式场景:描述状态而不是序列。(更少的步骤)

声明式步骤:描述应用程序应该处于的状态

命令式步骤:将当前状态改变表示为期望状态的步骤序列

TDD(测试驱动开发)

在代码本身之前,先为代码编写单元和功能测试

Rspec测试被称为specs或者例子

1
2
respec filename
# 运行测试
image-20250108090244624

单元测试-FIRST原则

FIRST 说明
Fast(快) 快速运行测试子集、因为将一直运行它们
Independent(独立) 没有测试依赖于其他测试、远程可以以任何顺序运行任何子集
Repeatable(可重复) 运行N次,得到相同的结果(以帮助隔离bug并启动自动化)
Self-checking(自检查) 测试可以自动检测是否通过
Timely(及时) 与被测试的代码同时编写(使用TDD需要先编写测试)

TDD周期:红-绿-重构

以“始终拥有工作代码”为目标。考虑代码应该完成的一件事(功能)

红:在失败的测试中记录/步骤这种想法

绿:编写尽可能简单的代码使测试通过

重构:与其他测试一起来提炼共性、改进代码。

继续完成代码应该做的下一件事。

接缝(Seam)

接缝:可以唉不改变源代码的情况下改变应用程序行为的位置。

对测试有用:将某些代码的行为与其所依赖的其他代码隔离开来。

image-20250108091402582

每个seam仅为测试中地某些特定行为提供足够地支撑。

Seam概念 说明
存根(stub) 类似should_receive,但没有期望;add_return可选地控制返回值.
模拟(mock) “特技替身”对象,常用于行为验证(让某方法被调用)、字其上为单个方法创建存根.

RSpec

image-20250108091820081

装置/工厂

从何获取真实对象?

装置(Fixture) 工厂(Factory)
说明 静态地将一些已知数据预加载到数据库表中 只创建每次测试所需要的内容动态创建
需求 每次测试之前,db需要擦除和重新载入 根据测试需要,设置helper来快速创建带有默认属性的对象
赞成的原因 真正的静态数据(e.g.永远不变的配置线性),恒容易在一个地方看到所有测试数据 保持测试的独立性:不受它们不关心对象的影响
反对的原因 可能会引入对装置数据的依赖 复杂的关系可能很难建立(但可能表明代码耦合过紧)

测试覆盖、单元测试、集成测试

覆盖度量

覆盖度量 说明
S0 方法覆盖
S1 调用覆盖
C0 语句覆盖
C1 分支覆盖
C1+ 判定覆盖:条件中的美国个子表达式
C2 路径覆盖(苦难,价值如何有很大分歧)
image-20250108092733364

测试与调试

变异测试:在代码中引入故意的错误、是否会有一些测试失败?

模糊测试:1万只猴子向你的代码扔随机输入:1.发现了MS~20% bug,崩溃了~25%的Unix应用工具2.以应用程序不应该被使用的方式来测试它

DU-覆盖率:每一对<define x/use x>执行了吗?

黑盒测试/集成测试:不依赖于对应用程序结构的理解

白盒测试

代码坏味-SOFA

通过捕获哪些白哦是代码坏味的症状。

  1. Short:短的
  2. One:只做一件事
  3. Few:不多的参数
  4. Abstraction:一致的抽象级别

定量:ABC复杂度

Assignment,Brach,Condition赋值+分支+条件,检查ABC复杂度

Agile敏捷开发


P&D

image-20250108085726511

需求抽取:抽取非功能/功能需求

面谈、合作创建场景(快乐/悲伤路径流)、创建用例(UML描述)

需求文档(软件需求规范记录需求)

需求检查:有效性、一致性、完整性、可行性

PD维护

image-20250108111236483

PD中设计模式

将软件需求规范(SRS)分解为问题(任务):

  1. 对每个任务寻找匹配的设计模式、然后是子问题的某事
  2. 设计评审将有所帮助

P&D中测试方法

将软件需求规范(SRS)划分为编程单元、开发人员编写单元代码+执行编程测试。

独立的质量保证(QA)团队进行更改级别的测试:模块、集成、系统、验收测试。

QA集成选项

自顶向下 自底向上 三明治集成
从依赖关系图的顶部开始 从依赖关系图的底部开始 两全其美?
高级功能(UI)很快就能开始工作 没有stub,吧所有的集成在一个模块中 通过自底向上集成一些单元来减少stub构造
构建许多存根Stub让应用程序“工作” 不能看到应用程序工作,知道所有的代码和集成完成 通过自顶向下集成一些单元,让UI可操作

QA团队测试

QA团队进行系统测试:

  1. 完成的应用程序可以运行
  2. 测试非功能需求+功能需求

何时系统测试?--看机构的政策

  • 测试覆盖级别(C0类似)
  • 所有测试要输入好的/坏的数据

最后一步是:用户/客户验收测试(UAT)--确认&验证

性能

可以是验收测试的一部分。PD周期忽略了性能。

版本管理:

image-20250108094249320

SaaS

SaaS:Software as a Service

SaaS通过运行在客户端设备上的瘦程序(浏览器、APP),访问Internet上以服务形式提供的软件(包括数据)。

优点:

  1. 无需安装、不用担心硬件与OS差异
  2. 无需担心数据丢失(数据远程存储)
  3. 便于团队共享和分享数据
  4. 如果数据很大/频繁更改,在中心站点保存一份副本更简单
  5. 软件单一拷贝、单一部署硬件/软件环境

SaaS对基础设施的需求:

  1. 通讯::允许客户与服务互动
  2. 可扩展性:需求波动满足新服务快速引入、增加用户
  3. 可靠性:服务和通信7*24h可用

SaaS类的设计模式

GoF:结构化、创建型、行为型

image-20250108100846478

模式不是单独的类或者库,也不是完整的设计(更像是设计的蓝图)

image-20250108094922290

元模式:把变与不变的东西分开。

  1. 针对接口百年城而不是针对实现编程。
  2. 比起继承,更倾向组合和委托:委托是接口共享、继承是关于实现代码共享。

SOILD面向对象编程原则

动机:将变更的代价最小化。

image-20250108095424916
SOLID原则 说明
单一职责(Single Responsibility, SRP) 一个类应该有且只有一个改变的理由、每一项职责可能是变化的轴心、对一个轴的更改不应该影响其他轴。
开闭(Open/Close, OCP) 类应该对功能扩展开发、对源代码修改关闭。--抽象工厂模式(提炼构造)
里氏替换(Liskov substitution) 子类型可以i替代基类型。
依赖注入(injection of dependencied, DIP) 需求:a依赖于b,但b的接口和实现可以改变,即使功能稳定; 解决方案:“注入”a和b所依赖的抽象接口
迪米特(Demeter,DP) 只和朋友交谈而不是陌生人。1.用委托替换直接方法调用,2.将遍历与计算分离(Visitor模式),3.在不了解实现细节的情况下只关注重要事件 (Observer模式)

观察者模式Observer

实体Observer想hi到何时某些事情发生在实体Subject上。

image-20250108100413028

非功能需求

服务水平目标(SLO,service level oeject)

image-20250108094026951

考试回忆版

哈哈终于考完了,我为期1个多月的考试周终于宣告结束了。

考之前,一直在想,老师会不会根据给的题库然后做一些变动。但实际情况是:完全没有.

让我们说:谢谢老师!

此外,虽然老师给了部分的重点,但是还是和我自己复习的有一些出入,比如,我以为概念应该会考SOLID或者BDD/TDD,像单元测试的SMART,TDD周期的红-绿-重构这些。但其实都没考,反倒是后面出了一个SaaS的概念,但是考前就看了两眼,觉得不会考..

再一个有出入的就是,我以为会考点读Ruby程序给输出的题,毕竟简单,但也完全没有()

所以大家复习的时候,建议还是复习的全面一点,基本上给的题库要全部过一遍,然后根据老师给出重点,再过一遍重要的。因为如果万一没有命中的话,至少之前做过一遍,还是会有印象,至少不会是0分(?)

当然,要是有时间能够全面复习,那就太好辣!

概念题:(20分,5题)

  1. 敏捷开发方法与Scrum方法
  2. DRY(Don't Repeat Yourslef)
  3. Ruby的迭代器:each,collect
  4. 分布式版本控制
  5. 什么是螺旋软件开发模型?它有什么特点?

选择判断: (20分,20题)--好像忘记了一个,问题不大

image-20250110221804060
image-20250110221818216
image-20250110221838186
image-20250110222333893
image-20250110221909408
image-20250110221927025
image-20250110221955744
image-20250110222015045

下面是判断,有些不确定忘记了(2/11左右)。但是可以从出题中窥见大概考点。

  1. BDD和TDD可以结合使用。
  2. 依赖注入原则表示将对象所依赖的外部对象以传递的方式注入。
  3. 软件测试效果的取决如何选择高效的测试用例,以便用尽量少的测试用例覆盖尽可能多的测试情况,从而提高测试效率。
  4. 模块化就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能。
  5. 在聊天系统开发中,开发人员将对用户输入的判断(图片或文字)功能实现在图片聊天模型中,是比较规范的开发。
  6. TDD: 在代码本身之前,先为代码编写单元和功能测试。
  7. 好的单元测试是每个测试只关注逻辑的一个方面,这样有利于排错。
  8. 在Ruby中,实例变量@var是在self(当前对象)中查找的。
  9. 观察者模式在被观察者和观察者之间建立抽象耦合,被观察者会向所有登记过的观察者发出通知。
  10. 软件模块之间的耦合性越强越好
  11. 与应用代码相比,如果测试代码特别简短,倾向于先编写测试

简答题:(40分,5题)

10分
6分
6分
x
image-20250110221733532

设计题: (20分,4题)

8分
x
image-20250110221351299
8分

下面是我自己根据题库做的一些答案,基本保证正确。有不确定的用了不同的颜色笔进行标注。

搜索
匹配结果数:
未搜索到匹配的文章。