写在前面
2022年春我学习了孟宁老师的《高级软件工程》课程,以下对这学期的知识内容和感想做一个回顾总结。
学号姓名:399thg
其他实验博客连接:
参考资料:
《代码中的软件工程》 https://gitee.com/mengning997/se
首先,《高级软件工程》这门课程和其他课程不同的地方在于,其他课程绝大多数只会教纯理论的知识,而《高级软件工程》还会交一些实操性的内容和工具,就比如VSCode、Vim、Git等工具,这些在工程领域都是用的比较多的。在此之前我只知道git的几个极少数的命令,由于不知道原理使用起来经常报错,在上完课后,学会了git的结构和基本概念,用起来就得心应手,我想这也是呼应了课程标题中的那句话:“工欲善其事,必先利其器”。
其次,《高级软件工程》这门课程就像是个大熔炉,不仅会教大家软件设计的方法和过程,包括需求分析、设计、编程、测试和维护的全部内容,而且还涵盖了前端、后端、数据库等相关知识,前端比如说javascript、vue,后端和数据库就有Golang、Mongodb等,让我对整个软件体系结构有了一个整体的认识,特别是在这个前后端分离、微服务框架盛行的时代下,在每个人分工明确各施其职的工作环境中,对自己的方向要有深度的同时,对其他方向和技术有一个基本的了解同样不可或缺。
最后,我觉得《高级软件工程》让我收获最大的,是对软件工程的有了更深层次的理解。在此之前,也就是上学期我们工程实践团队在写项目的时候,没有系统性的软件设计方法,在做项目过程中遇到了各种各样的问题,现在回想起来,要是上学期就选高软课程就好了。软件工程,涵盖了软件生命周期中所有的工程方法、技术和工具,包括需求分析、设计、编程、测试和维护的全部内容,即完成一个软件产品所必备的思想、理论、方法、技术和工具。我在这方面做得还不够,这也是我需要在后面的学习和工作中需要不断进行总结反思改进的地方。
最后的最后,感谢孟宁老师一学期课程的教导,孟老师授课由浅入深,引人入胜,时刻抓住我们的听课兴趣,使我对一个软件工程有了整体性的认知,也祝孟宁老师工作顺利,万事顺意!
文件操作
Ctrl + O #打开文件夹/工作区
Ctrl + KF #关闭文件夹/工作区
Ctrl + N #新建文件
Ctrl + W #关闭文件
Ctrl + KW #关闭所有文件
Ctrl + KU #关闭所有已保存的文件
其他
Ctrl + / #单行注释
Ctrl + Shift + A #多行注释
Ctrl + Shift + E #文件资源管理
Ctrl + Shift + F #跨文件搜索
Ctrl + Shift + D #启动和调试
Ctrl + Shift + M #查看错误警告
Ctrl + Shift + X #管理扩展文件
Ctrl + ` #切换终端
git status #查看当前工作区(workspace/branch)
git log #查看当前head之前提交的记录,便于回溯
git reflog #查看当前head之后提交的记录,便于前进
git reset --hard commit-id #回退
git init #初始化一个本地版仓库
git add [files] #将文件添加进缓存区
git commit -m “mesage” #将文件添加进本地repo
git clone #克隆一个仓库到本地目录下
git fetch #查看远程仓库是否更新,更新就爬过来
git push # 将本地仓库的信息推送到远程仓库
git merge # 合并两个或多个仓库
git pull #从其他存储分支抓取或合并到当前分支
建议团队项目的每一个开发者都采用的工作流程大致如下:
• 1 克隆或同步最新的代码到本地存储库;
• 2 为自己的工作创建一个分支,该分支应该只负责单一功能模块或代码模块的版本控制;
• 3 在该分支上完成某单一功能模块或代码模块的开发工作;
• 4 最后,将该分支合并到主分支。
1.快进式合并(默认) git merge
2.git merge --no-ff
区别:
git merge
A---B---C feature
/ master
D---E---F
git merge --no-ff
A---B---C feature
/ \
D---E---F-----------G master
--no-ff
会让 Git 合并成一个新的提交对象,再改变head指向对象,而快进合只是把head指针置为featuregit branch #查看分支
git checkout #切换分支
git checkout -b mybranch #创建并切换
git branch # 基于某个分支上开出新分支
rebase命令用来合并之前提交(commit)的记录,log 记录将来更容易回顾参考,用 git rebase 重新整理一下提交记录。
•git rebase -i [startpoint] [endpoint]
通配符==.== 匹配任意一个字符
例如hu.来匹配hug huh hut等
通配符==+== 匹配出现一次或多次的字符
hahhhhh可以使用hah+来匹配
通配符==*== 匹配0次或者多次出现的字符
通配符==?== 检查前一个元素是否存在 colou?r
* | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。 |
---|---|
+ | 匹配前面的子表达式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 。? 等价于 {0,1}。 |
. | 匹配除换行符(\n、\r)之外的任何单个字符 |
[xyz] 表示匹配xyz中任意一个字符
[^xyz] 表示匹配未包含的任意字符
[a-z] 匹配字符范围
[^a-z] 负字符范围
快捷方式1:\w搜索字母数字
快捷方式2:\d搜索数字
快捷方式2:\D搜索非数字
例如titanic
- 贪婪匹配t[a-z]*i 则匹配titani
- 懒惰匹配t[a-z]*?i 匹配ti
?紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的.
查找开头的 Ricky 则为^Ricky,查找结尾的 found 则为/found$
我们在搜索的某些模式在字符串中多次出现,手动重复这些正则表达式是浪费时间的。
用括号(and)可以定义capture groups 捕获组,用于查找重复的子串,即把会重复的模式的正则表达式放在括号内。
例如我们匹配字符串中连续出现三次的数字,每个数字由空格分隔
原本要写成:\d+\s\d+\s\d+
现在写成: (\d+)(\s)\1\2\1
从第一行到最后一行,将word1替换成word2
:%s/word1/word2/g
想在当前文件中将所有的HTML标题标签中h改为大写H则正则表达式为:1
$s///g
1.匹配如下规则
([a-zA-Z]){2,}\d*|\1*\d{2,}
模块化(Modularity)是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独 立地进行设计和开发。
基本原理是关注点的分离 (SoC, Separation of Concerns) 分解成易解决的小问题,降低思考负担,容易定位软件缺陷,减少出错的情形。
模块化的指标:耦合度和内聚度
耦合度是指软件模块之间的依赖程度,可分类为紧密耦合、松散耦合和无耦合
一般在软件设计中我们追求松散耦合。
内聚度是指一个软件模块内部各种元素之间互相依赖的紧密程度。
理想的内聚是功能内聚,也就是一个软件模块只做一件事,只完成一个主要功能点或者一个软件特性。
1.KISS原则
2.使用本地化外部接口来提高代码的适应能力
3.不要和陌生人说话原则
4.先写伪代码的代码结构更好一些
接口就是互相联系的双方共同遵守的一种协议规范,在我们软件系统内部一般的接口方式是通过定义一组API函数来约定软件模块之间的沟通方式。
在面向过程的编程中,接口一般定义了数据结构及操作这些数据结构的函数;而在面向对象的编程中,接口是对象对外开放(public)的一组属性和方法的集合。函数或方法具体包括名称、参数和返回值等。
微服务使用模块化的思想,每个微服务单独部署,跑在自己的进程中,每个微服务为独立的业务功能开发,一般每个微服务应分解到最小可变产品,达到功能内聚的理想状态。
RESTfulAPI
•GET用来获取资源;
•POST用来新建资源(也可以用于更新资源);
•PUT用来更新资源;
•DELETE用来删除资源。
•参数化上下文:使用参数传递信息,不依赖上下文环境
•移除前置条件
•简化后置条件
• 所有数据都由函数的调用者提供;
• 使用局部变量,或者通过制作全局数据的局部变量拷贝来保护全局数据;
• 使用静态数据或全局变量时做周密的并行时序分析,通过临界区互斥避免临界区冲突;
• 绝不调用任何不可重入函数。
需求就是对用户期望的软件行为的表述;
获取需求就是需求分析师通过关注用户的期望和需要,从而获得用户期望的软件行为,然后对其进行表述的工作;
需求分析是在获取需求的基础上进一步对软件涉及的对象或实体的状态、特征和行为进行准确描述或建模的工作。
1.原型化方法
原型化方法可以很好地整理出用户接口方式(UI,User Interface),比如界面布局和交互操作过程。
2.建模的方法
建模的方法可以快速给出有关事件发生顺序或活动同步约束的问题,能够在逻辑上形成模型来 整顿繁杂的需求细节。
用例是经过逻辑整理抽象出来的一个业务过程。
什么是业务过程?在待开发软件所处的业务领域内完成特定业务任务的一系列活动就是业务过程。
统一过程是用例驱动、以架构为中心、增量且迭代的过程。
用例驱动就是我们前文中用例建模得到的用例作为驱动软件开发的目标;
以架构为中心的架构是后续软件设计的结果,就是保持软件架构相对稳定,减小软件架构层面的重构造成的混乱;
S系统:有规范定义,可从规范派生————矩阵操纵矩阵运算
P系统:需求基于问题的近似解,但现实世界保持稳定————象棋程序
E系统:嵌入现实世界并随着世界的变化而变化(大多数软件都属于这个类型)————预测经济运行方式的软件(但经济尚未被完全理解)
闭包一般用在将函数作为返回值时,该函数执行所需的上下文环境也作为返回的函数对象的一部分。
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Promise对象实际上是对回调函数机制的封装,也就是通过then方法定义的函数与resolve/reject函数绑定,简化了回调函数传入的接口实现,在逻辑上也更加通顺,看起来像是个同步接口。
var promise = new Promise(function(resolve, reject) {
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) { // resolve(value)
// success
}, function(value) { // reject(error)
// failure
});
设计模式的本质是面向对象设计原则的实际运用总结出的经验模型。
目的是包容变化,即通过使用设计模式和多态等特殊机制,将变化的部分和不变的部分进行适当隔离。
正确使用设计模式具有以下优点:
设计模式由四个部分组成:
根据作用对象分两类:
执行过程
在MVVM中,用户直接与V交互,通过VM将变化传递给M,然后M改变之后通过VM将数据传递给V,从而实现解耦。
耦合:
克隆,完整地借鉴相似项目的设计方案,甚至代码,只需要完成一些细枝末节处的修改适配工作。
重构,构建软件架构模型的基本方法,在参考已有的软件架构模型的基础上逐步形成系统软件架构的一种基本建模方法。
工程专家们所找到的各种方法都是舍本逐末,它们解决不了软件中的根本困难,即软件概念结构(conceptual structure)的复杂性,无法达成软件概念的完整性和一致性,自然无法从根本上解决软件危机带来的困境
分析、设计、实现、交付和维护五个阶段
软件过程又分为描述性的过程和说明性的过程。
V模型也是在瀑布模型基础上发展出来的,我们发现单元测试、集成测试和系统测试是为了在不同层面验证设计,而交付测试则是确认需求是否得到满足。
也就是瀑布模型中前后两端的过程活动具有内在的紧密联系,如果将模块化设计的思想拿到软件开发过程活动的组织中来,可以发现通过将瀑布模型前后两端的过程活动结合起来,可以提高过程活动的内聚度,从而改善软件开发效率。这就是V模型。
V模型是开始一个特定过程活动和评估该特定过程的过程活动成对出现,从而便于软件开发过程的组织和管理。
CMM/CMMI用于评价软件生产能力并帮助其改善软件质量的方法,成为了评估软件能力与成熟度的 一套标准,它侧重于软件开发过程的管理及工程能力的提高与评估,是国际软件业的质量管理标准。