当前位置:   article > 正文

(科软)高级软件工程课程总结_科软 高级软件工程

科软 高级软件工程

一、总结与体会

本学期很荣幸选修了的高级软件工程课程。孟老师的课程在软件工程基本概念的基础上,由近及远、由浅入深、全面的讲解了代码中的软件工程的内容。立足于实践,多学多练,有针对性的训练了同学们作为未来程序员的基本功。本课程主要分为:工欲善其事,必先利其器、工程化的编程实战、从需求分析到软件设计、软件科学基础概论、软件危机和软件过程五个部分。

工欲善其事,必先利其器

  • Typing
  • VSCode
  • Git
  • Vim
  • 正则表达式

工程化的编程实战

  • 代码规范和代码风格
  • 编写高质量代码的基本方法
  • 模块化软件
  • 接口
  • 可重入函数和线程安全
  • 软件质量

从需求分析到软件设计

  • 获取需求
  • 需求分析和建模
  • 面向对象分析
  • 关系数据模型软件设计

软件科学基础概论

  • 软件是什么
  • 设计模式
  • 软件架构
  • 软件质量

软件危机和软件过程

  • 软件危机
  • 软件过程模型
  • PSP和TSP
  • CMM/CMMI
  • 敏捷方法
  • DevOps

二、重要知识总结

  • 1.高质量需求的特点:
    正确的、一致的、无二义性、完整的、可行的、无与主要目标不相关的需求、可描绘的、可测试的

  • 2.有哪些需求类型:
    功能需求:根据所需活动描述所需行为
    质量需求或非功能性需求:描述软件必须具备的一些质量特征
    设计约束:设计决策,例如平台或接口组件的选择
    过程约束:对可用于构建系统的技术或资源的限制

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

  • 4.用例满足的四个必要条件:
    必要条件一:它是不是一个业务过程?
    必要条件二:它是不是由某个参与者触发开始?
    必要条件三:它是不是显式地或隐式地终止于某个参与者?
    必要条件四:它是不是为某个参与者完成了有用的业务工作?

  • 5.统一过程的核心要义是什么:
    统一过程(UP,Unified Process)的核心要义是用例驱动(Use case driven)、以架构为中心
    (Architecture centric)、增量且迭代(Incremental and Iterative)的过程。

  • 6.模块化的基本原理
    模块化(Modularity)是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独
    立地进行设计和开发。
    背后的基本原理:关注点分离:

  • 7.本地化外部接口是什么含义
    使用本地化外部接口来提高代码的适应能力, 将我们的代码接口分离出来,写成本地化的外部接
    口,能更好的帮助我们分离业务之间的关联性,使得代码开发更加高效。

  • 8.接口的5个基本要素:
    接口的目的;
    接口使用前所需要满足的条件,一般称为前置条件或假定条件;
    使用接口的双方遵守的协议规范;
    接口使用之后的效果,一般称为后置条件;
    接口所隐含的质量属性。

  • 9.通用接口定义的基本方法:
    参数化上下文
    移除前置条件
    简化后置条件

  • 10.依赖倒置原则的含义及其应用价值
    依赖倒置原则的定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。应用于:模块化设计

  • 11.MVC架构为什么更灵活以及MVVM架构为什么更智能
    MVC: Model 和 View 没有耦合关系,通过 Controller 关联起来,可以根据需求上的变化灵活设计 Model 和 View,方便程序员扩展功能。
    MVVM: View 和 Model 之间没有联系,通过 ViewModel 进行交互,视图的数据的变化会通过ViewModel 直接修改数据源而不需要写代码更新数据源,数据源数据的变化也会通过ViewModel 立即反应到 View 上,不需要写更新 View 的代码。

  • 12.执行视图、部署视图、分解视图等

(1)执行视图
执行视图展示了系统运行时的时序结构特点,比如流程图、时序图等。执行视图中的每一个执行实体,一般称为组件(Component),都是不同于其他组件的执行实体。如果有相同或相似的执行实体那么就把它们合并成一个。
(2)部署视图
部署视图是将执行实体和计算机资源建立映射关系。这里的执行实体的粒度要与所部署的计算机资源相匹配,比如以进程作为执行实体那么对应的计算机资源就是主机,这时应该描述进程对应主机所组成的网络拓扑结构,这样可以清晰地呈现进程间的网络通信和部署环境的网络结构特点。当然也可以用细粒度的执行实体对应处理器、存储器等。部署视图有助于设计人员分析一个设计的质量属性
(3)分解视图
分解是构建软件架构模型的关键步骤,分解视图也是描述软件架构模型的关键视图,一般分解视图呈现为较为明晰的分解结构(breakdown structure)特点。分解视图用软件模块勾划出系统结
构,往往会通过不同抽象层级的软件模块形成层次化的结构。
(4)依赖视图
•依赖视图展现了软件模块之间的依赖关系。比如一个软件模块 A 调用了另一个软件模块 B,那么我们说软件模块 A 直接依赖软件模块 B。如果一个软件模块依赖另一个软件模块产生的数据,那么这两个软件模块也具有一定的依赖关系。
•依赖视图在项目计划中有比较典型的应用。比如它能帮助我们找到没有依赖关系的软件模块或子系统,以便独立开发和测试,同时进一步根据依赖关系确定开发和测试软件模块的先后次序。
•依赖视图在项目的变更和维护中也很有价值。比如它能有效帮助我们理清一个软件模块的变更对其他软件模块带来影响范围。
(5)泛化视图
•泛化视图展现了软件模块之间的一般化或具体化的关系,典型的例子就是面向对象分析和设计方法中类之间的继承关系。值得注意的是,采用对象组合替代继承关系,并不会改变类之间的泛化特征。因此泛化是指软件模块之间的一般化或具体化的关系,不能局限于继承概念的应用。
•泛化视图有助于描述软件的抽象层次,从而便于软件的扩展和维护。比如通过对象组合或继承很容易形成新的软件模块与原有的软件架构兼容。
(6)实现视图
•实现视图是描述软件架构与源文件之间的映射关系。一般我们通过目录和源文件的命名来对应软件架构中的包、类等静态结构单元,这样典型的实现视图就可以由软件项目的源文件目录树来呈现。
•实现视图有助于码农在海量源代码文件中找到具体的某个软件单元的实现。实现视图与软件架构的静态结构之间映射关系越是对应的一致性高,越有利于软件的维护,因此实现视图是一种非常关键的架构视图。
(7)工作分配视图
工作分配视图将系统分解成可独立完成的工作任务,以便分配给各项目团队和成员。工作分配视图有利于跟踪不同项目团队和成员的工作任务的进度,也有利于在个项目团队和成员之间合理地分配和调整项目资源,甚至在项目计划阶段工作分配视图对于进度规划、项目评估和经费预算都能起到有益的作用。

  • 13.没有银弹的含义
    工程专家们所找到的各种方法都是舍本逐末,它们解决不了软件中的根本困难,即软件概念结构(conceptual structure) 的复杂性,无法达成软件概念的完整性和一致性,自然无法从根本上解决软件危机带来的困境
  • 14.简述v模型、瀑布模型、原型化瀑布模型、螺旋模型
  • V 模型 也是在瀑布模型基础上发展出来的,我们发现单元测试、集成测试和系统测试是为了在不同层面验证设计,而交付测试则是确认需求是否得到满足。也就是瀑布模型中前后两端的过程活动具有内在的紧密联系,如果将模块化设计的思想拿到软件开发过程活动的组织中来,可以发现通过将瀑布模型前后两端的过程活动结合起来,可以提高过程活动的内聚度,从而改善软件开发效率。
  • 瀑布模型(Waterfall Model)是第一个软件过程开发模型,对于能够完全透彻理解的需求且几乎不会发生需求变更的项目瀑布模型是适用的。瀑布模型是一个过程活动的顺序结构,没有任何迭代,而大多数软件开发过程都会包含大量迭代过程。瀑布模型不能为处理开发过程中的变更提供任何指导意义,因为瀑布模型假定需求不会发生任何变化。由此看来,瀑布模型将软件开发过程看作类似于工业生产制造的过程,而不是一个创造性的开发过程。工业生产制造的过程就是没有任何迭代活动,直接产出最终产品。瀑布模型视角下的软件开发过程也一样,只有等待整个软件开发过程完成后,才能看到最终软件产品。
  • 原型化瀑布模型:瀑布模型会将整个软件开发过程中的众多风险积累到最后才能暴露出来,为了尽早暴露风险和控制风险,在瀑布模型的基础上增加一个原型化(prototyping)阶段,可以有效将风险前移,改善整个项目的技术和管理上的可控性。在需求分析阶段,原型可能是软件的用户接口部分,在设计阶段,原型可能是软件架构的关键部分。
  • 螺旋模型 是一种演化软件开发过程模型,兼顾了快速原型的迭代的特征以及瀑布模型的系统化与严格监控。螺旋模型最大的特点在于引入了其他模型不具备的风险管理,使软件在无法排除重大风险时有机会停止,以减小损失
  • 15.常用的设计模式

单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,典型的应用如数据库实例。
原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例,原型模式的应用场景非常多,几乎所有通过复制的方式创建新实例的场景都有原型模式。
建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。主要应用于复杂对象中的各部分的建造顺序相对固定或者创建复杂对象的算法独立于各组成部分。
代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。代理模式是不要和陌生人说话原则的体现,典型的应用如外部接口本地化将外部的输入和输出封装成本地接口,有效降低模块与外部的耦合度。
适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。继承和对象组合都可以实现适配器模式,但由于组合关系或聚合关系比继承关系耦合度低,所以对象组合方式的适配器模式比较常用。
装饰(Decorator)模式:在不改变现有对象结构的情况下,动态地给对象增加一些职责,即增加其额外的功能。装饰模式实质上是用对象组合的方式扩展功能,因为比继承的方式扩展功能耦合度低。装饰模式在 Java 语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。
外观(Facade)模式:为复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。比如线程池、固定分配存储空间的消息队列等往往都是该模式的应用场景。
策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。策略模式是多态和对象组合的综合应用。
命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。模版方法是继承和重载机制的应用,属于类模式。
职责链(Chain of Responsibility)模式:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。通过这种方式将多个请求处理者串联为一个链表,去除请求发送者与它们之间的耦合。
中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是“网状结构”,它要求每个对象都必须知道它需要交互的对象。如果把这种“网状结构”改为“星形结构”的话,将大大降低它们之间的“耦合性”,这时只要找一个“中介者”就可以了。在软件的开发过程中,这样的例子也很多,例如,在 MVC 框架中,控制器(C)就是模型(M)和视图(V)的中介者,采用“中介者模式”大大降低了对象之间的耦合性,提高系统的灵活性。
观察者(Observer)模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为,这样所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。

  • 16.简述敏捷宣言的核心思想

个体和互动 高于 流程和工具
工作的软件 高于 详尽的文档
客户合作 高于 合同谈判
响应变化 高于 遵循计划
(尽管右项有其价值,我们更重视左项的价值。)

  • 17.编程:写一个menu里面自定义查找结点的测试代码
    给Linktable增加Callback方式的接口,需要两个函数接口,一个是call-in方式函数,如SearchLinkTableNode函数,其中有一个函数作为参数,这个作为参数的函数就是callback函数,如代码中Conditon函数。

在这里插入图片描述
在这里插入图片描述

  • 18.git
    git指令(查看workspace状态、将workspace推到index):
    git status
    git add [FILES] # 把文件添加到暂存区(Index)
    git commit -m “wrote a commit log infro” # 把暂存区里的文件提交到仓库
    git快速合并与-no-diff的区别: (git checkout master/git merge --no-ff [子分支名])
    默认的合并方式为"快进式合并”(fast-farward merge),会将分支里commit合并到主分支里,合并成一条时间线,与我们期望的呈现为一段独立的分支线段不符,因此合并时需要使用–no-ff参数关闭"快进式合并"(fast-farward merge)。
  • 19.vscode快捷键

打开文件夹(Ctrl/⌘+O)和关闭文件夹工作区(Ctrl/⌘+K F)
新建文件(Ctrl/⌘+N)、关闭文件(Ctrl/⌘+W)、编辑文件和保存文件(Ctrl/⌘+S)
文件内搜索(Ctrl/⌘+F)
关闭所有文件(Ctrl/⌘+K W)
关闭已保存的文件(Ctrl/⌘+K U)
Ctrl+/用于单行代码注释和取消注释,Alt+Shift+A用于代码块注释和取消注释。
Ctrl/⌘+Shift+E 文件资源管理器
Ctrl+Shift+G 源代码管理
Ctrl/⌘+Shift+F 跨文件搜索
Ctrl/⌘+Shift+D 启动和调试
Ctrl/⌘+Shift+P查找并运行所有命令
Ctrl/⌘+Shift+M查看错误和警告
Ctrl/⌘+Shift+X 管理扩展插件
Ctrl+`切换集成终端

  • 20.正则表达式
    捕获组:
    可能搜索的某些模式在字符串中多次出现,手动重复这些正则表达式是浪费时间的。有一个更好的方法可在你的字符串中有多个重复子串时进行指定,那就是capture groups 捕获组。
    用括号(and)可以定义capture groups 捕获组,用于查找重复的子串,即把会重复的模式的正则表达式放在括号内。
    要指定重复字符串的出现位置,可以使用反斜杠“\”,然后使用数字。该数字从 1 开始,并随着用括号定义的捕获组数量而增加。比如\1 来匹配前面通过括号定义的第一个捕获组。
    使用 capture groups 捕获组来匹配字符串中连续出现三次的数字,每个数字由空格分隔,如(\d+)\s\1\s\1。

  • 21.异步调用(promise、wait之类的),给代码写执行结果

  • 22.liskov替换原则
    Liskov替换原则(Liskov Substitution Principle,LSP)继承必须确保超类所拥有的性质在子类中仍然成立(Inheritance should ensure that any property proved about supertype objects also holds for subtype objects)。通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。Liskov替换原则如今看来其价值也大大折扣,因为为了降低耦合度我们往往使用对象组合来替代继承关系。反而是Liskov替换原则不推荐的多态成为诸多设计模式的基础。

  • 23.画时序图
    在这里插入图片描述

  • 24.职责链模式

在这里插入图片描述

void handleRequest(string s){ 
	if(由当前handler处理){ 
		dosth 
	}else{
		handler.getNext().handleRequest(s) 
	} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 25.观察者模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 26.可重入函数
    可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。
    不为连续的调用持有静态数据;
    不返回指向静态数据的指针;
    所有数据都由函数的调用者提供;
    使用局部变量,或者通过制作全局数据的局部变量拷贝来保护全局数据;
    使用静态数据或全局变量时做周密的并行时序分析,通过临界区互斥避免临界区冲突;
    绝不调用任何不可重入函数。
  • 27.软件中的一些特殊机制

回调函数:
回调函数是一个面向过程的概念,是代码执行过程的一种特殊流程。回调函数就是一个通过函数指针调用的函数。把函数的指针(地址)作为参数传递给另一个函数,当这个指针调用其所指向的函数时,就称这是回调函数。回调函数不是该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
多态:
多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。多态是实例化变量可以指向不同的实例对象,这样同一个实例化变量在不同的实例对象上下文环境中执行不同的代码表现出不同的行为状态,而通过实例化变量调用实例对象的方法的那一块代码却是完全相同的,这就顾名思义,同一段代码执行时却表现出不同的行为状态,因而叫多态。简单的说,可以理解为允许将不同的子类类型的对象动态赋值给父类类型的变量,通过父类的变量调用方法在执行时实际执行的可能是不同的子类对象方法,因而表现出不同的执行效果。
闭包:
闭包是变量作用域的一种特殊情形,一般用在将函数作为返回值时,该函数执行所需的上下文环境也作为返回的函数对象的一部分,这样该函数对象就是一个闭包。
异步调用:
Promise对象可以将异步调用以同步调用的流程表达出来,避免了通过嵌套回调函数实现异步调用。

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
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

匿名函数:
lamda函数是函数式编程中的高阶函数,在我们常见的命令式编程语言中常常以匿名函数的形式出现,比如无参数的代码块{ code },或者箭头函数 { x => code },如下使用Promise对象实现的计时器就用到了箭头函数。

  • 28.微服务架构
    在模块化思想的指导下目前主要有两种软件架构模式,即传统单体集中式(Monolithic)架构与微服务(Microservice)架构,传统单体集中式架构是相对于新型的微服务架构而言的。
    由一系列独立的微服务共同组成软件系统的一种架构模式;
    每个微服务单独部署,跑在自己的进程中,也就是说每个微服务可以有一个自己独立的运行环境和软件堆栈;
    每个微服务为独立的业务功能开发,一般每个微服务应分解到最小可变产品(MVP),达到功能内聚的理想状态。微服务一般通过RESTful API接口方式进行封装;
    系统中的各微服务是分布式管理的,各微服务之间非常强调隔离性,互相之间无耦合或者极为松散的耦合,系统通过前端应用或API网关来聚合各微服务完成整体系统的业务功能。
    RESTful API
    REST即REpresentational State Transfer的缩写,可以翻译为”表现层状态转化”。有表现层就有背后的信息实体,信息实体就是URI代表的资源,也可以是一种服务,状态转化就是通过HTTP协议里定义的四个表示操作方式的动词:GET、POST、PUT、DELETE,分别对应四种基本操作:
    GET用来获取资源;
    POST用来新建资源(也可以用于更新资源);
    PUT用来更新资源;
    DELETE用来删除资源。

参考资料

孟宁:代码中的软件工程

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/202270
推荐阅读
相关标签
  

闽ICP备14008679号