我的本科专业也是软件工程这门专业,本科的时候也学过软件工程这门课,只不过当时学的比较浅显,只是了解了一点概念性的知识,选了孟老师的高级软件工程之后,老师不仅能更深入的给我们讲解那些理论知识,而且还非常注重实践操作,将理论与实践相结合。下面是我本学期的一点小小的收获:
高质量需求的特点
有哪些需求类型
- 功能需求:描述所需活动的行为
- 质量需求或非功能需求:描述软件必须具备的一些质量特性
- 设计约束(设计约束): 设计决策,例如选择平台或接口组件
- 过程约束(过程约束):开发过程中技术或资源的限制
需求分析的两类基本方法
- 原型化方法 原型化方法可以很好地整理出用户接口方式,比如界面布局和交互操作过程。
- 建模的方法 建模的方法可以快速给出有关事件发生顺序或活动同步约束的问题,能够在逻辑上形成模型来整顿繁杂的需求细节
获取需求的主要方法
1,采访消费者; 2,与用户一同了解需求; 3,观察现有的系统 4,特定的设计策略 5,头脑风暴
用例满足的四个必要条件
- 它是不是一个业务过程?
- 它是不是由某个参与者触发开始?
- 它是不是显式地或隐式地终止于某个参与者?
- 它是不是为某个参与者完成了特定的业务工作?
用例建模的基本步骤
从需求分析中找到用例
描述用例开始和结束的状态
对用例按照子系统或不同的方面进行分类,描述用例与用例、用例与参与者之间的上下文关系,并画出用例图
进一步逐一分析用例与参与者的详细交互过程,完成一个两列的表格将参与者和待开发软件系统之间从用例开始到用例结束的所有交互步骤都列举出来扩展用例
其中第一到第三步是计划阶段,第四步是增量实现阶段
编写高质量代码的基本方法
- 通过控制结构简化代码(if else/while/switch)
- 通过数据结构简化代码
- 一定要有错误处理
- 注意性能优先的代价
- 拒绝修修补补要不断重构代
统一过程的核心要义是什么
统一过程的核心要义是 用例驱动 、 以架构为中心 、 增量且迭代的过程。用例驱动就是我们根据用例作为驱动软件开发的目标;以架构为中心的架构是就是保持软件架构相对稳定,减小软件架构层面的重构造成的混乱;
模块化的基本原理
模块化是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独立地进行设计和开发。这个做法背后的基本原理是关注点的分离 分解成易解决的小问题,降低思考负担。 每个模块只有一个功能,易于开发,并且bug会集中在少数几个模块内,容易定位软件缺陷,也更 加容易维护。 软件设计中的模块化程度便成为了软件设计有多好的一个重要指标,一般我们使用耦合度和内聚度来衡量软件模块化的程度。
本地化外部接口是什么含义
使用本地化外部接口来提高代码的适应能力, 将我们的代码接口分离出来,写成本地化的外部接口,能更好的帮助我们分离业务之间的关联性,使得代码开发更加高效。
接口的5个基本要素
- 接口的目的
- 接口的前置条件
- 接口的协议规范(如http协议,png图片格式,json数据格式定义etc..)
- 接口的后置条件
- 接口的质量属性(如响应时间)
通用接口定义的基本方法
- 参数化上下文(使用参数传递信息,不依赖上下文环境,即不使用闭包函数)
- 移除前置条件(sum函数中使用数组传递参数,不再限定参数个数)
- 简化后置条件(移除参数之间的关系,使sum返回的是数组全部元素的和)
RESTful API
- GET用来获取资源
- POST用来新建资源(也可以用于更新资源)
- PUT用来更新资源
- DELETE用来删除资源。
耦合度
耦合度依次递增可以分为无耦合、数据耦合、标记耦合、控制耦合、公共耦合和内容耦合
- 数据耦合:在软件模块之间仅通过显式的调用传递基本数据类型即为数据耦合
- 标记耦合:在软件模块之间仅通过显式的调用传递复杂的数据结构(结构化数据)即为标记耦合,这时数据的 结构成为调用双方软件模块隐含的规格约定,因此耦合度要比数据耦合高。但相比公共耦合没有经过显式的调用传递数据的方式耦合度要低
- 公共耦合:•当软件模块之间共享数据区或变量名的软件模块之间即是公共耦合,显然两个软件模块之间的接 口定义不是通过显式的调用方式,而是隐式的共享了共享了数据区或变量名
七大原则
单一职责原则:一个类应该只包含一个单一的职责
接口分离原则:把包含多个功能的接口分隔为多个接口
迪米特法则:每个实体只和它直接的朋友交谈,不和陌生人交谈
开闭原则:好的设计应该对扩展开放,对修改封闭
里氏替换原则:子类应该能替代父类而起到同样的作用
依赖倒置原则:高层模块、低层模块都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象
由于在软件设计中,细节具有多变性,而抽象层则相对稳定,因此以抽象为基础搭建
起来的架构要比以细节为基础搭建起来的架构要稳定得多。
依赖倒置原则在模块化设计中降低模块之间的耦合度和加强模块的抽象封装提高模块
的内聚度上具有普遍的指导意义
组合代替继承:优先考虑组合或者聚合等关联,其次再考虑继承等关系
- 继承复用的缺点:
- 继承复用破坏了封装性:因为继承会将父类的实现细节暴露给子类。
- 父类和子类耦合度高:父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展和维护
- 继承复用限制了复用的灵活性:从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化
- 合成复用的优点:采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能
- 组合或聚合复用维持了类的封装性。因为属性对象的内部细节是新对象看不见的。
- 新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取属性对象的唯一方法是通过属性对象的接口。
- 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与属性对象类型相同的对象。
闭包
函数和函数内部能够访问到的变量(也叫环境)的总和,就是一个闭包
MVC
- Model负责数据的持久化以及业务逻辑处理的实现
- View:视图用来向用户显示信息,它获得来自模型的数据,决定模型以什么样的方式展示给用户
- Controller:控制器是和视图联合使用的,它捕捉鼠标移动、鼠标点击和键盘输入等事件,将其转化为服务请求,然后再传给模型或者视图,接受用户的输入并决定用哪个模型去处理请求,然后再决定用哪个视图来显示返回的数据
应用MVC架构的软件其基本的实现过程
- 控制器创建模型
- 控制器创建一个或多个视图,并将它们与模型相关联;
- 控制器负责改变模型的状态;
- 当模型的状态发生改变时,模型会通知与之相关的视图进行更新。
MVVM的优点
- 低耦合:视图可以独立于Model变化和修改,当View变化的时候,Model可以不变,当Model变化的时候,View可以不变
- 可重用性:可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑
- 独立开发:开发人员可以专注于业务逻辑和数据的开发,设计人员可以专注于页面设计
- 可测试:界面素来是比较难于测试的,测试可以针对ViewModel来写
MVC架构为什么更灵活以及MVVM架构为什么更智能
随着前端页面越来越复杂,用户对于交互性要求也越来越高,jQuery是远远不够的,于是MVVM被引入到Javascript前端开发中。前端有了MVVM的设计思想后,终于实现了前后端工程及数据的彻底分离
依赖视图、执行视图、部署视图、分解视图
- 依赖视图:依赖视图展现了软件模块之间的依赖关系。比如一个模块A调用了另一个模块B,那么我们说模块A依赖模块B。
- 它可以帮我们找到没有依赖关系的软件模块和子系统,以便独立开发和测试,以及可以根据依赖关系确定开发和测试软件模块的先后次序
- 对软件维护也有较大价值,比如它能有效帮助我们理清一个软件模块的变更对其它软件模块带来的影响范围
- 泛化视图:泛化视图展现了软件模块之间的一般化或具体化的关系。
- 泛化视图有助于描述软件的抽象层次,从而有利于软件的扩展和维护
- 执行视图:执行视图展示了系统运行时的时序结构特点,比如流程图、时序图等。执行视图中的每一个执行实体,一般称为组件,都是不同于其他组件的执行实体。如果有相同或相似的执行实体那么就把它们合并成一个。
- 实现视图:实现视图是描述软件架构和源文件之间的映射关系
- 有助于码农在海量源代码文件中找到具体的某个软件单元的实现
- 部署视图:部署视图是将执行实体和计算机资源建立映射关系
- 分解视图:分解是构建软件架构模型的关键步骤,分解视图也是描述软件架构模型的关键视图,一般分解视图呈现为较为明晰的分解结构特点。分解视图用软件模块勾划出系统结构,往往会通过不同抽象层级的软件模块形成层次化的结构。
没有银弹的含义
“在10年内无法找到解决软件危机的杀手锏(银弹)。 软件中的根本困难,即软件概念结构(conceptual structure)的复杂性,无法达成软件概念的完整性 和一致性,自然无法从根本上解决软件危机带来的困境。
简述v模型
V模型也是在瀑布模型基础上发展出来的,我们发现单元测试、集成测试和系统测试是为了在不同层面验证设计,而交付测试则是确认需求是否得到满足。左侧是设计和分析,右侧是对左侧结果的验证。
越到下面,白盒测试方法使用越多,越往上,黑盒测试方法使用越多
简述敏捷宣言的核心思想
- 个体和互动 高于 流程和工具
- 工作的软件 高于 详尽的文档
- 客户合作 高于 合同谈判
- 响应变化 高于 遵循计划
敏捷开发的宗旨
互联网使得知识的获取变得更加容易,很多软件可以由一个小团队来实现。同时,技术更新的速度在加快,用户需求的变化也在加快,开发流程必须跟上这些快速变化的节奏。于是敏捷方法就产生了。
三种耦合(数据耦合-标记耦合-控制耦合-公共耦合-内容耦合)
- 公共耦合:当软件模块之间共享数据区或变量名的软件模块之间即是公共耦合,显然两个软件模块之间的接口定义不是通过显式的调用方式,而是隐式的共享了共享了数据区或变量名。
- 数据耦合:在软件模块之间仅通 过显式的调用传递基本数据类型即为数据耦合。
- 标记耦合:在软件模块之间仅通过显式的调用传递复杂的数据结构(结构化数据)即为标记耦合,这时数据 的结构成为调用双方软件模块隐含的规格约定,因此耦合度要比数据耦合高。但相比公共耦合没有经过显式 的调用传递数据的方式耦合度要低。
看待软件质量的几个角度
- 产品的角度,也就是软件产品本身内在的质量特点;
- 用户的角度,也就是软件产品从外部来看是不是对用户有帮助,是不是有良好的用户体验;
- 商业的角度,也就是商业环境下软件产品的商业价值,比如投资回报或开发软件产品的其他驱动因素。
设计模式
根据设计模式可以完成的任务类型来划分
- 创建型模式:用于描述怎样创建对象,将对象的创建和使用分离(单例模式、原型模式、创建者模式)
- 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构(代理模式、适配器模式、桥接模式、外观模式)
- 行为型模式:用于描述程序在运行时复杂的流程控制(模板方法模式、观察者模式、命令模式)
根据模式是主要用于类上还是主要用于对象上来划分:
- 类模式:用于处理类与子类之间的关系:这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。比如模板方法模式等属于类模式。
- 对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。由于组合关系或聚合关系比继承关系耦合度低,因此多数设计模式都是对象模式。
模板方法模式
模板方法模式定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类 中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。模版方法是继承和重载机制的应用,属于类模式
观察者模式
观察者模式指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,把这种改变广播告知其它多个对象,从而影响其它对象的行为,这样所有依赖于它的对象都得到通知并被自动更新。(又叫发布-订阅模式)
回调函数
回调函数就是一个通过函数指针调用的函数。把函数的指针(地址)作为参数传递给另一个函数,当这个指针调用其所指向的函数时,就称这是回调函数。回调函数不是该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一 方调用的,用于对该事件或条件进行响应。
可重入函数的基本要求
- 所有的数据都由函数的调用者提供
- 使用局部变量来保护全局数据
- 绝不调用任何不可重入函数
- 使用静态数据或全局变量时做周密的并行时序分析,通过临界区互斥避免临界区冲突
- 不返回指向静态数据的指针
函数的可重入性与线程安全之间的关系
- 可重入的函数不一定是线程安全的;可重入的函数在多个线程中并发使用时是线程安全的;但不同的可重入函数(共享全局变量和静态变量)在多个线程中并发使用时会有线程安全问题
- 不可重入的函数一定不是线程安全的
LSP协议
LSP(Language Server Protocol):轻量和快速, 节制的设计;合理的抽象;周全的细 节。 LSP 最重要的概念是动作和位置,LSP 的大部分请求都是在表达”在指定位置执行规定动作“。抽象成请求和回复
版本控制方式:
- 独立文件方式
- 补丁方式
- 中心版本控制系统
- 分布式管理控制系统
团队项目中的分叉合并
SA21225403