高级软件工程课程总结报告

        转眼间,一个学期的高级软件工程(以下简称高软)课程已经结束,虽然因为疫情原因一直未能线下上课,但是在网络授课的条件下,我仍旧收益良多,感念颇深,同时也承蒙孟宁老师一个学期以来的讲授与教学。由于我本科的专业是物联网工程,虽然同属于计算机类学科,但是真正接触到软件工程相关的思想还是在研究生阶段,又或者说是通过孟老师的高软课程,才对软件工程的各种方法和思想有了更加系统、细微的认识。第一次接触到孟老师的课程,虽然隔着屏幕,但丝毫感受不到距离感,只感受到孟老师在介绍高软课程时带来的轻松幽默的氛围,极大加深了我对这门课程的兴趣和关注,比起其他课程的各种抽象公式或者生硬的概念,高软这门课程是对软件工程方法的总结、软件工程思想的灌注以及软件工程规范的讲述,结合孟老师轻松愉悦的授课风格,总能在不知不觉中习得很多知识。下面具体阐述一下我这个学期以来的课程总结。

1.工欲善其事必先利其器

        首先是在第一章节的内容中学习到很多十分实用的内容,孟老师称之为“工欲善其事必先利其器”,从打字typing速度的训练,到强大的IDE——VS Code的使用,从vim的输入技巧和正则表达式的巧妙利用,到git仓库的推拉上传,循序渐进地讲述了许多实战利器和“神技”,这也是身为一名程序员所必须具备的技巧,尤其是学习了git的使用技巧后,我也可以将自己编写过的项目上传到GitHub仓库中,实现了个人仓库的管理。

git笔记:

1、git本地版本库的基本用法:

- git init # 初始化一个本地版本库
- git status # 查看当前工作区(workspace)的状态
- git add [FILES] # 把文件添加到暂存区(Index) 
- git commit -m "wrote a commit log infro” # 把暂存区里的文件提交到仓库
- git log # 查看当前HEAD之前的提交记录,便于回到过去
- git reset —hard HEAD^^/HEAD~100/commit-id/commit-id的头几个字符 # 回退
- git reflog # 可以查看当前HEAD之后的提交记录,便于回到未来
- git reset —hard commit-id/commit-id的头几个字符 # 回退

2、git远程版本库的基本用法:
- git clone命令官方的解释是“Clone a repository into a new directory”,即克隆一个存储库到一个新的目录下。
- git fetch命令官方的解释是“Download objects and refs from another repository”,即下载一个远程存储库数据对象等信息到本地存储库。
- git push命令官方的解释是“Update remote refs along with associated objects”,即将本地存储库的相关数据对象更新到远程存储库。 
- git merge命令官方的解释是“Join two or more development histories together”,即合并两个或多个开发历史记录。
- git pull命令官方的解释是“Fetch from and integrate with another repository or a local branch”,即从其他存储库或分支抓取并合并到当前存储库的当前分支。

vim笔记:

1、移动光标

- h 或 向左箭头键(←)    光标向左移动一个字符
- j 或 向下箭头键(↓)    光标向下移动一个字符
- k 或 向上箭头键(↑)    光标向上移动一个字符
- l 或 向右箭头键(→)    光标向右移动一个字符
2、删除

- x, X    在一行字当中,x 为向后删除一个字符 (相当于 [del] 按键), X 为向前删除一个字符(相当于 [backspace] 亦即是退格键) (常用)
- nx    n 为数字,连续向后删除 n 个字符。举例来说,我要连续删除 10 个字符, 『10x』。
- dd    删除游标所在的那一整行(常用)
- ndd    n 为数字。删除光标所在的向下 n 行,例如 20dd 则是删除 20 行 (常用)
- d1G    删除光标所在到第一行的所有数据
- dG    删除光标所在到最后一行的所有数据
- d$    删除游标所在处,到该行的最后一个字符
- d0    那个是数字的0 ,删除游标所在处,到该行的最前面一个字符
3、复制与粘贴

- yy    复制游标所在的那一行(常用)
- p, P     p为将已复制的数据在光标下一行贴上,P则为贴在游标上一行! 举例来说,我目前光标在第 20 行,且已经复制了 10 行数据。则按下 p 后, 那 10 行数据会贴在原本的 20 行之后,亦即由 21 行开始贴。但如果是按下 P 呢? 那么原本的第 20 行会被推到变成 30 行。 (常用)
- nyy      n 为数字。复制光标所在的向下 n 行,例如 20yy 则是复制 20 行(常用)
- y1G    复制游标所在行到第一行的所有数据
- yG    复制游标所在行到最后一行的所有数据
- y0    复制光标所在的那个字符到该行行首的所有数据
- y$    复制光标所在的那个字符到该行行尾的所有数据
4、复原与重做

- u    复原前一个动作。(常用)
- [Ctrl]+r    重做上一个动作。(常用) 
5、基本搜索

- /word    向光标之下寻找一个名称为 word 的字符串。例如要在档案内搜寻 vbird 这个字符串,就输入 /vbird 即可! (常用)
- ?word    向光标之上寻找一个字符串名称为 word 的字符串。
6、基本搜索替换

- :n1,n2s/word1/word2/g    n1 与 n2 为数字。在第 n1 与 n2 行之间寻找 word1 这个字符串,并将该字符串取代为 word2 。(常用)
- s是substitute的简写,表示执行替换字符串操作
- g(global)表示全局替换;c(comfirm)表示操作时需要确认;i(ignorecase)表示不区分大小写
- :1,$s/word1/word2/g 或 :%s/word1/word2/g    从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 。(常用)
  :1,$s/word1/word2/gc 或 :%s/word1/word2/gc    从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 。     

正则表达式笔记:

1、通配符的基本用法

“.”表示任意一个字符;“?”表示前一个字符是否存在,也就是存在 0 次或 1 次;“+”表示前一个字符出现一次或多次;“*”表示前一个字符出现 0 次、1 次或多次。

2、字符集匹配

- 快捷方式\w 匹配字母数字[A-Za-z0-9_ ]。这个character sets 字符集匹配大小写字母加数字。注意,这个character sets 字符集还包括下划线字符“_”。
- 快捷方式\W 搜索\w 的相反方向。需要注意相反的模式使用大写字母。此快捷方式与[^A-Za-z0-9_]相同。
- 快捷方式\d 搜索数字字符集[0-9]。
- 快捷方式\D查找非数字字符,等于字符集[^0-9]。
3、贪婪匹配和懒惰匹配

- greedy 贪婪匹配。找到符合正则表达式模式的字符串的最长可能部分,并将其作为匹配返回。

- lazy 懒惰匹配。找到符合正则表达式模式的字符串的最小可能部分。
4、使用捕获组复用模式
用括号(and)可以定义capture groups 捕获组,用于查找重复的子串,即把会重复的模式的正则表达式放在括号内。要指定重复字符串的出现位置,可以使用反斜杠“\”,然后使用数字。该数字从 1 开始,并随着用括号定义的捕获组数量而增加。

2.工程化编程实战——代码中的软件工程

        依我个人看法,软件工程大体上分为系统分析、系统设计、系统编码、系统测试以及系统的维护等几个阶段,在孟老师的课程中,除了第一章的准备工作之外,其余章节基本上都围绕着系统分析、系统设计和系统编码等阶段来展开,第二章其实涉及到很多模块化设计的内容,这一部分应当属于系统设计阶段,孟老师从编写高性能代码的角度,阐述了“好代码”的定义以及在性能优先策略的背后隐藏着何种代价,另外还介绍了模块化设计的好处,我认为模块之间的耦合度以及模块内的内聚度,是系统设计阶段需要考虑的十分重要的问题,在系统设计中如果模块粒度过大,那么它的可重用性自然就会较差,与其他模块的耦合度也会降低;相反,如果模块的粒度过小,那么系统整体的复杂性又会加大,模块之间产生相互调用的次数也会增大,一大直观的体现就是模块内的扇出率提高,因此,如何设计较为通用的接口,而又不至于使得接口过于泛化,是系统设计阶段应当考虑的一个重要问题,接口设计妥当,具有逻辑结构清晰的程序库,可以避免重复”造轮子“的情况,也可以避免后续代码重写或者做其他修改的过程中,出现的”牵一发而动全身“的尴尬局面。

1、接口与耦合度之间的关系

- 公共耦合:当软件模块之间共享数据区或变量名的软件模块之间即是公共耦合,显然两个软件模块之间的接口定义不是通过显式的调用方式,而是隐式的共享了共享了数据区或变量名。
- 数据耦合:在软件模块之间仅通过显式的调用传递基本数据类型即为数据耦合。
- 标记耦合:在软件模块之间仅通过显式的调用传递复杂的数据结构(结构化数据)即为标记耦合,这时数据的结构成为调用双方软件模块隐含的规格约定,因此耦合度要比数据耦合高。但相比公共耦合没有经过显式的调用传递数据的方式耦合度要低。

2、微服务

由一系列独立的微服务共同组成软件系统的一种架构模式;
每个微服务单独部署,跑在自己的进程中,也就是说每个微服务可以有一个自己独立的运行环境和软件堆栈;
每个微服务为独立的业务功能开发,一般每个微服务应分解到最小可变产品(MVP),达到功能内聚的理想状态。微服务一般通过RESTful API接口方式进行封装;
系统中的各微服务是分布式管理的,各微服务之间非常强调隔离性,互相之间无耦合或者极为松散的耦合,系统通过前端应用或API网关来聚合各微服务完成整体系统的业务功能。

3、可重入函数

可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反,不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用局部变量,要么在使用全局变量时保护自己的数据。

可重入函数的基本要求:

- 不为连续的调用持有静态数据;

- 不返回指向静态数据的指针;

- 所有数据都由函数的调用者提供;

- 使用局部变量,或者通过制作全局数据的局部变量拷贝来保护全局数据;

- 使用静态数据或全局变量时做周密的并行时序分析,通过临界区互斥避免临界区冲突;

- 绝不调用任何不可重入函数。

什么是线程安全:

- 可重入的函数不一定是线程安全的,可能是线程安全的也可能不是线程安全的;可重入的函数在多个线程中并发使用时是线程安全的,但不同的可重入函数(共享全局变量及静态变量)在多个线程中并发使用时会有线程安全问题;

- 不可重入的函数一定不是线程安全的。

 3.从需求分析到软件设计

       第三章又会涉及到系统分析和系统设计阶段的内容,从需求分析到软件设计,孟老师幽默地讲述了获取需求的重要性,令我印象深刻的就是PPT里面那个”准确获取需求并不容易“的漫画,我认为需求分析永远是软件工程的重中之重,如果不了解软件设计的目标,那么后续的功能也不会是用户所期望的。这一章节的后半部分介绍了软件设计的重要思想,在学习敏捷统一过程中,我也学会了瀑布模型和V模型等软件开发过程以及时序图的设计,当然无论是何种模型,把需求分析放在开发阶段最靠前的位置,是最普遍的做法。

1、需求分析的两类基本方法

- 原型化方法(Prototyping)和建模的方法(Modeling)是整理需求的两类基本方法。
- 原型化方法可以很好地整理出用户接口方式(UI,User Interface),比如界面布局和交互操作过程。
- 建模的方法可以快速给出有关事件发生顺序或活动同步约束的问题,能够在逻辑上形成模型来整顿繁杂的需求细节。

2、用例

用例(Use Case)的核心概念中首先它是一个业务过程(business process),经过逻辑整理抽象出来的一个业务过程,这是用例的实质。什么是业务过程?在待开发软件所处的业务领域内完成特定业务任务(business task)的一系列活动就是业务过程。

在准确理解用例概念的基础上,我们可以进一步将用例划分为三个抽象层级:

- 抽象用例(Abstract use case)。只要用一个干什么、做什么或完成什么业务任务的动名词短语,就可以非常精简地指明一个用例;

- 高层用例(High level use case)。需要给用例的范围划定一个边界,也就是用例在什么时候什么地方开始,以及在什么时候什么地方结束;

- 扩展用例(Expanded use case)。需要将参与者和待开发软件系统为了完成用例所规定的业务任务的交互过程一步一步详细地描述出来,一般我们使用一个两列的表格将参与者和待开发软件系统之间从用例开始到用例结束的所有交互步骤都列举出来。

用例建模的基本步骤:

- 第一步,从需求表述中找出用例,往往是动名词短语表示的抽象用例;
- 第二步,描述用例开始和结束的状态,用TUCBW和TUCEW表示的高层用例;
- 第三步,对用例按照子系统或不同的方面进行分类,描述用例与用例、用例与参与者之间的上下文关系,并画出用例图;
- 第四步,进一步逐一分析用例与参与者的详细交互过程,完成一个两列的表格将参与者和待开发软件系统之间从用例开始到用例结束的所有交互步骤都列举出来扩展用例。
- 其中第一步到第三步是计划阶段,第四步是增量实现阶段。

3、统一过程

统一过程(UP,Unified Process)的核心要义是用例驱动(Use case driven)、以架构为中心(Architecture centric)、增量且迭代(Incremental and Iterative)的过程。用例驱动就是我们前文中用例建模得到的用例作为驱动软件开发的目标;以架构为中心的架构是后续软件设计的结果,就是保持软件架构相对稳定,减小软件架构层面的重构造成的混乱;增量且迭代体现在下图中。

敏捷统一过程的四个关键步骤

- 第一,确定需求;
- 第二,通过用例的方式来满足这些需求;
- 第三,分配这些用例到各增量阶段;
- 第四,具体完成各增量阶段所计划的任务。

4、对象交互建模

对象交互建模的基本步骤

- 找出关键步骤进行剧情描述(scenario)
- 将剧情描述(scenario)转换成剧情描述表(scenario table)
- 将剧情描述表转换成序列图的基本方法
- 从分析序列图到设计序列图
- 一个完整用例的对象交互建模

4.软件科学基础概论

        第四章是系统设计和系统编程相关的内容,相对于上一章来说,显得更为具体。我在上学期研修了软件体系结构这门课程,其中就有设计模式和软件架构相关的内容,在这一章节中,又涉及到了相关的内容。可能在平时的代码实践中,没有刻意的去关注自己写的代码到底用到了何种设计模式,但是往往最容易被人忽视的点却极为重要,就以模板方法模式为例,我写过的项目中就曾用到过这种设计模式,流程基本相同的两套方法,仅仅是使用到的一些中间过程不同,例如网络传输方式分别采用JDK自带的socket和Netty传输方式,那么这一部分的内容就可以用模板方法来构造,只需要将通用的模板编写好,再分别定义两种不同的模块来完成这两种传输方式的过程即可。在编程中使用到的设计模式非常多,最常见的就有单例模式和工厂模式,但是其他常用的设计模式应当也要广为了解,因为很可能在实际的项目中,这些设计模式就会成为自己解决方案的模板,应对特定的设计问题,需要使用相对应的设计决策,设计模式就为此而生。除了设计模式外,这一章节还包含了非常重要的软件架构方案MVC和MVVM,这两种在项目创建中使用非常广泛,尤其是学习了Java的同学可能已经在项目中使用到了SpringMVC的架构,通过这一章节的学习,能够更加清晰地认识到使用这种架构的好处,它将业务非常清晰地抽象为三个层次,灵活而又便于理解。

1、回调函数

回调函数是一个面向过程的概念,是代码执行过程的一种特殊流程。回调函数就是一个通过函数指针调用的函数。把函数的指针(地址)作为参数传递给另一个函数,当这个指针调用其所指向的函数时,就称这是回调函数。回调函数不是该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

2、闭包

闭包是变量作用域的一种特殊情形,一般用在将函数作为返回值时,该函数执行所需的上下文环境也作为返回的函数对象的一部分,这样该函数对象就是一个闭包。

更严谨的定义是,函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在JavaScript中,每当函数被创建,就会在函数生成时生成闭包。

3、异步调用

Promise对象可以将异步调用以同步调用的流程表达出来,避免了通过嵌套回调函数实现异步调用。

Promise对象的基本用法

Promise对象实际上是对回调函数机制的封装,也就是通过then方法定义的函数与resolve/reject函数绑定,简化了回调函数传入的接口实现,在逻辑上也更加通顺,看起来像是个同步接口。
4、设计模式

- 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例。

- 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

- 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。

- 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

- 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

- 装饰(Decorator)模式:在不改变现有对象结构的情况下,动态地给对象增加一些职责,即增加其额外的功能。

- 外观(Facade)模式:为复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。

- 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。

- 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。策略  模式是多态和对象组合的综合应用。

- 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

- 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

- 职责链(Chain of Responsibility)模式:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

- 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

5、设计原则

- 开闭原则(Open Closed Principle,OCP)
- Liskov替换原则(Liskov Substitution Principle,LSP)
- 依赖倒置原则(Dependence Inversion Principle,DIP)
- 单一职责原则(Single Responsibility Principle,SRP)
- 迪米特法则(Law of Demeter,LoD)
- 合成复用原则(Composite Reuse Principle,CRP)

6、MVC架构

MVC即为Model-View-Controller(模型-视图-控制器),MVC是一种设计模式,以MVC设计模式为主体结构实现的基础代码框架一般称为MVC框架,如果MVC设计模式决定了整个软件的架构,不管是直接实现了MVC模式还是以某一种MVC框架为基础,只要软件的整体结构主要表现为MVC模式,我们就称为该软件的架构为MVC架构。

MVC中M、V和C所代表的含义如下:

Model(模型)代表一个存取数据的对象及其数据模型。

View(视图)代表模型包含的数据的表达方式,一般表达为可视化的界面接口。

Controller(控制器)作用于模型和视图上,控制数据流向模型对象,并在数据变化时更新视图。控制器可以使视图与模型分离开解耦合。

7、MVVM架构

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点:

- 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
- 可测试。界面素来是比较难于测试的,测试可以针对ViewModel来写。
 

5.软件危机和软件过程

        最后一章是关于系统设计的内容,孟老师以软件危机为起点,讲述了软件危机的根本原因,以及“没有银弹”的现实痛点,接着介绍了软件开发过程中常见的过程模型、团队与项目的关系以及CMM/CMMI软件评估框架等内容,从开发过程、团队合作和软件评测这三个角度对整体软件过程进行阐述,也使我对软件开发有了更加系统的理解。

1、没有银弹

 “在10年内无法找到解决软件危机的杀手锏(银弹)。 软件中的根本困难,即软件概念结构(conceptual structure)的复杂性,无法达成软件概念的完整性 和一致性,自然无法从根本上解决软件危机带来的困境。

2、软件的生命周期

- 分析。分析阶段的任务是需求分析和定义,分析阶段一般会在深入理解业务的情况下,形成业务概念原型。

- 设计。设计阶段分为软件架构设计和软件详细设计,前者一般和分析阶段联系紧密,一般合称为“分析 与设计”;后者一般和实现阶段联系紧密,一般合称为“设计与实现”。

- 实现。实现阶段分为编码和测试,其中测试又涉及到单元测试、集成测试、系统测试等。

- 交付。交付阶段主要是部署、交付测试和用户培训等。

- 维护。维护阶段一般是软件生命周期中持续时间最长的一个阶段,而且在维护阶段很可能会形成单独 的项目,从而经历分析、设计、实现、交付几个阶段,最终又合并进维护阶段。

3、分阶段开发

- 增量开发(Incremental development)。增量开发就是从一个功能子系统开始交付,每次交付会增加一些功能,这样逐步扩展功能最终 完成整个系统功能的开发。

- 迭代开发 (Iterative development)。迭代开发是首先完成一个完整的系统或者完整系统的框架,然后每次交付会升级其中的某个功能子系统,这样反复迭代逐步细化最终完成系统开发。

4、敏捷宣言

- 个体和互动 高于 流程和工具

- 工作的软件 高于 详尽的文档

- 客户合作 高于 合同谈判

- 响应变化 高于 遵循计划

尽管右项有其价值,我们更重视左项的价值。

        在高软课程中,我不仅学到了软件工程的重要方法和思想以及软件开发的总体流程,还在实战中提高了自己的编程能力,我也会在今后的学习生涯中利用课程中学到的重要知识,提高自己的软件工程思想,最后非常感谢孟宁老师一个学期以来的授课指导,也感谢孟老师编著的《代码中的软件工程》对我课程学习的帮助!

        姓名:马云飞,学号:356,参考资料  代码中的软件工程 https://gitee.com/mengning997/se

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值