01软件工程概述
- 软件产品:通用产品和定制化产品
- 软件工程的基本关注点:质量、成本、创新、时间
- 用户期望:产品质量 & 个性化
- 软件开发的几个阶段:玩具阶段、尝试阶段、原型阶段、产品阶段
- 软件危机
- 工程特点
02软件开发技能-软件演化与配置管理
- 软件演化对软件工程的影响
- 配置管理:版本管理、系统构建、变更管理、发布管理(配置管理是软件开发能力成熟的基本要求)
①版本管理:意义、术语(代码线、基线、主线)、主要任务、集中式与分布式版本控制系统及其各自优势
②系统构建:主要功能(概述,分别介绍了构建脚本功能、开发、构建、部署功能、持续集成功能)
03个人开发技能-代码质量
- 代码问题报告:bug、vulnerability、code-smell举例、问题总结
- 代码质量:含义、几个方面(代码风格、代码逻辑、代码设计等)
- 代码风格
- 代码逻辑:
- 控制代码复杂度:控制代码长度、控制嵌套语句的层数
- 控制代码重复率:提取公共部分进行方法或类封装;提取抽象类或接口;使用模板类或模板方法
- 高质量子程序:承担单一而明确的职责(功能内聚);良好的子程序命名;控制子程序的长度;仔细考虑子程序的参数(不要把参数用作工作变量)
- 防御式编程:基本思想是子程序不应该由于传入错误的数据(由外部接口或其他子程序传入)而被破坏; 程序员可以决定自己的程序逻辑但无法决定用户或其他子程序提供什么样的输入; 但仍要竭尽所能保护自身程序的正确运行
注:消除深层嵌套的代码实例未打印
- 防御编程:
应对不可控的外部输入:
- 断言:用断言处理不应该发生的状况
- 错误处理代码:用错误处理代码来处理预期会发生的情况
错误处理的更高层次的考虑:
- 异常:将代码中的错误或异常事件传递给调用方代码的一种手段
- 错误处理代码:
隔栏机制:让隔栏部分处理不干净的数据,而让内部代码处理干净的数据,这样大部分的代码无需再担负检查错误数据的任务。
04个人开发技能-测试驱动的开发
- 单元测试:
测 单个方法/函数 ; 对象行为;
要点:是开发者的测试; 应该尽可能自动化; 隔离依赖
好的单元测试:状态无损;基本单元;可重复;覆盖性;独立性;自动化
四阶段:建立;执行;验证;拆卸
- 依赖和测试替身
- 测试用例选取策略:划分测试; 基于指南的测试
- 交叉测试
- 测试先行:具备可行性;精确的程序规格说明;方便衡量开发进度;提高测试效率
- 测试驱动的开发
05软件过程与团队合作-软件过程与敏捷开发
- 基本的软件开发活动:
- 规格说明(需求)
- 设计和实现
- 确认(测试)
- 演化(维护)
- 软件过程:敏捷 vs 计划驱动
- 过程模型:
- 瀑布模型:属于计划驱动,规格说明、开发、确认和演化是独立的过程阶段
- 增量式开发:可以是计划驱动或敏捷的,常见为二者的混合,规格说明、开发和确认等活动不是分离的而是交织在一起的
增量式开发比瀑布模型的三个优势:
①降低了实现需求变更的成本,交织瀑布模型,重新分析和修改文档的工作量要少很多。
②在开发过程中更容易得到客户对于已开发的开发工作的反馈意见,客户可以对演示版本进行评价,并可以看到已经实现了多少需求,客户通常会感觉从软件设计文档中判断项目进度会很难
③即使并未将所有的功能包含在其中,也使得在早期向客户交付和部署有用软件成为可能,与瀑布模型相比,客户可以更早的使用软件并从中获得价值。
- 统一过程模型:预定义多个开发阶段,每个阶段包含多次迭代,每次迭代都包含多个开发活动
- 敏捷过程特点:客户需求(场景故事)驱动; 认识到有效的计划都是短期的 ;迭代地开发软件同时强调构造活动(设计与实现交织) ;频繁交付可运行的软件增量; 根据变化进行适应变化和进行适应性修改,强调适应非预测
06软件过程与团队合作-团队合作与协作
- 软件开发协作:①代码评审与结对编程; ②问题追踪系统 ③开源软件的社会化合作
- 代码评审:①含义; ②代码评审的准备和前提条件 ; ③代码评审过程→评审这进一步还应考虑哪些问题?代码评审检查表
- 结对编程:含义;好处和坏处;不间断的代码评审
- 问题(issue)
问题追踪系统:含义;主要功能;
Bug/issue的生命周期和状态
Pull/request开发模式
07软件设计-软件设计概述
- 软件设计:
①内容:数据设计;体系结构设计;接口设计;
组件级设计(组件内的类与类之间关系定义,局部的数据结构、算法设计
②承上启下:承上:满足需求 启下:实现和测试的基础
③目标:功能性方面:完整实现功能需求;
非功能性方面:充分实现质量需求
④基本原则 ⑤设计决策
⑥设计思想:
体系结构 ; 分解;
抽象:数据抽象、过程抽象;
逐步精化:抽象使得设计者在考虑高层设计时能够忽略过程和数据的底层细节;精化使得设计者能够逐步揭示底层的细节,得到更加具体的解决方案
风格和模式; 模块化;
信息隐藏:限制局部设计决策的全局影响;降低副作用发生的可能性;强调模块/组件/类间通过受控的接口进行通信;不鼓励使用全局数据
功能独立:衡量标准:内聚度、耦合度
重构
08软件设计-面向对象软件设计
- 组件:①是一种系统组成部分,②模块化、可部署、可替换 ③内部封装了实现 ④对外暴露一组接口
面向对象视角的组件:是由一组相互协作的类组成
通过细化的组件设计满足体系结构设计中对组件的要求。
- 面向对象设计步骤:①识别设计类 ②明确设计类职责和协作 ③细化设计类内部细节
- 不同类型的类:①来自问题领域的类:业务对象;业务过程
②位于接口上的类:用户界面;硬件接口;软件接口
③来自基础设施的类:资源管理;进程通信
- 类的职责分配:
①关注点分离:每个类有自己明确的职责
②相对独立性:高内聚;低耦合
③粒度合理:避免过于集中或过于分散
④考虑未来可能的扩展:共性抽象;保持灵活性
- 内聚:一个模块保持单一意图的程度;内聚意味着单个组件或类
内聚的类型:功能内聚;层次内聚;通信内聚;顺序内聚;过程内聚;时间内聚;功用内聚
- 耦合:组件或类之间相互联系的程度;
避免:内容耦合;
小心:共用耦合;控制耦合;
知晓调用耦合;类型使用耦合;包含或引入耦合
- 面向对象设计原则:
开闭原则:对扩展开放,对修改封闭
Liskov替换原则:子类对象应该可以替换父类对象出现的地方
依赖转置原则:依赖于抽象(抽象类、接口)而非具体
接口隔离原则:不要强迫客户模块依赖他们不会使用的接口,多个服务于特定请求方的接口好过一个通用接口
- 面向对象类设计的描述:
静态结构模型:泛化(继承)、使用/被使用、组合等
动态交互模型:对象发出的服务请求的序列、由这些对象交互所触发状态变化
- UML类模型:
类:类名、属性、方法
类间关系:①关联(定义两个或多个类之间的一种静态结构关系)
②依赖:是一种较弱的关联关系,一个类 依赖于另一个类协作完成任务,关联关系只在一定时间段内存在
③整体/部分(组合、聚合):组合是整体与部分之间往往存在的包含关系,整体完全拥有部分;聚合是整体与部分之间往往不存在物理的包含关系,部分可以加入或退出
④泛化/特殊:(继承): ⑤实现
- 动态交互模型:描述相关对象如何通过相互协作实现特定场景的执行;可以使用uml顺序图或通信图来表示
09软件设计-设计模式
- 设计模式是针对共性设计问题的一种参考解决方案,是对一系列相似设计方案的本质和共性抽象,,因此具有通用性。
- 共性设计问题存在良好的参考方案:易理解、易修改、易扩展
- 设计模式四要素:有意义的模式名字;解释模式何时适用的问题描述;解决方案描述;应用该模式的效果以及其中所涉及的权衡决策
- 设计模式举例:
- 观察者模式:观察者(负责显示逻辑);被观察者(负责数据管理);
(被观察者和观察者解耦,观察者可灵活增加(开闭原则))
设计模式背后的原则:①单一职责原则 ②Liskov替换原则;③依赖倒转原则 ④迪米特原则 ⑤合成复用原则
- 单例模式:确保一个类只有一个实例并为其提供全局的访问入口;保持接口 、继承等面向对象特性;
应用举例:网站计数器、任务管理器、回收站
- 组合模式:将对象组织成表示整体部分层次的树状结构,同时使客户端代码可以统一处理对象以及对象的组合
应用举例:文件系统目录结构、组织结构、画图工具中的图形组合
- 策略模式:对算法的行为(具体处理策略) 进行抽象, 使得客户端代码不再依赖于具体的算法而是依赖于抽象的策略, 在此基础上可以方便地对算法族进行管理。
复合图形(CompositeFigure)的 布 局 依 赖 于 抽 象 的Layouter。
优点: 将算法与其使用环境分离
1) 算法可以独立被复用
2) 避免了客户端代码中的多重条件选择语句
3) 可灵活实现布局算法替换, 还可以通过继承AbstractLayouter增加新的布局算法。
10软件设计-设计框架
- 框架是带有一组插入点的骨架:经过适配调整以后可以支持不同的特定问题需要;插入点上可以继承问题特定的类或功能。
- 构件(如图书处理、打印构件)、模式(如组合模式、观察者模式)、框架(如struct、jhotDraw)
①软件构件(关键词:调用)。:针对特定功能提供可复用的实现,开发人员在自身已有的实现方案基础上调用构件实现局部功能和具体功能(如邮件发送),有自己的实现并通过接口提供访问。特定应用实现调用软件构件实现局部功能,构件对系统整体设计影响不大。
②设计模式(关键词:实例化):一种抽象的设计思想,往往体现为参考设计方案(如用UML图表示),本身并没有代码实现,需要针对具体问题、参考其设计思想进行实现。反映的是抽象的设计思想,且只关注于某个局部设计问题,其中的类都是与特定应用无关的抽象角色,没有实现代码。 →特定应用实现对设计模式中的角色机器关系进行实例化,得到特定用的设计和实现→基于设计模式的实例化实现,其中的类都是针对特定应用的设计类,存在对应的实现代码。
③软件框架(关键词:扩展):本身包含相对完整的设计以及核心实现,提供扩展和定制能力,开发人员针对特定应用的实现通过扩展点插入框架中,一般由框架来调用形成完整的应用实现。。例子:JHOTDRAW.有相对完整的设计,有自己的实现代码。特定应用通过框架的扩展点(如抽象、接口)扩展特地应用的实现,最终与框架实现融为一体。
- jhotDraw的设计模式
①组合模式:AbstractCompositeFigure 使用List<Figure>属性表示对于子图形的包含关系(组合关系) , 在drawFigure()方法中对List<Figure>进行遍历(扮演客户端代码的角色) 。
优点:为树形结构的面向对象实现提供了一种灵活的设计方案
1) 清楚地定义分层次的复杂对象
2) 客户端可以一致地处理复合对象和原子对象
3) 方便扩展新的复合或原子对象
②观察者模式:事件处理器EventHandler类是观察者; AbstractFigure类是被观察者,内 部 维 护 了 一 个 观 察 者 的 列 表(listenerList),在发生变化时通知当前注册的事件处理器。
优点:表示层(观察者) 和数据逻辑层(被观察者) 相分离
1) 被观察者和观察者之间建立一个抽象的耦合, 被观察者不依赖于具体的观察者
2) 被观察者对观察者进行广播通信, 简化了一对多的系统设计
③策略模式:对算法的行为(具体处理策略) 进行抽象, 使得客户端代码不再依赖于具体的算法而是依赖于抽象的策略, 在此基础上可以方便地对算法族进行管理。
复合图形(CompositeFigure)的 布 局 依 赖 于 抽 象 的Layouter。
优点: 将算法与其使用环境分离
1) 算法可以独立被复用
2) 避免了客户端代码中的多重条件选择语句
3) 可灵活实现布局算法替换, 还可以通过继承AbstractLayouter增加新的布局算法。
共性:都是以设计抽象为基本手段,都很好的实践了开闭原则
11软件设计-演化式设计
- 软件演化:软件必须不断演化以保持“有用性”;软件演化花费巨大
- 冰山形成的原因
- 敏捷开发中的演化:一方面是传统的缺陷或需求/环境变化驱动的演化;另一方面是迭代式开发自身带来的演化性
- 两种实施设计的方式:事先计划的设计 vs 演化式设计 各自的问题
- 在计划和演化式设计之间取得平衡:重构
- 重构:消除代码的坏味道
重复代码、长方法、发散式变化、霰弹式修改
12软件设计-软件体系结构
- 软件体系结构:是高层设计结构、反映软件解决方案的高层分解;
包括:一组软件组件、软件组件的外部属性、软件组件之间的关系、全局的实现约定
- 软件体系结构的内容:
- 软件组件
表⽰软件系统⾼层分解的结构元素
可以是简单的程序模块或类,也可以是复杂的⼦系统
还可以包含扩展的数据库、中间件等
- 软件组件的外部属性
功能性属性,例如接⼝、交互协议
⾮功能性属性,例如响应时间、吞吐量
- 软件组件之间的关系
静态结构关系
动态交互关系
运⾏时部署关系
- 全局的实现约定
需要在系统全局作出约定的实现技术决策
例如:实现语⾔、异常处理策略、共享资源的使⽤⽅式、包和⽂件的命名⽅式等
影响最终的系统组件集成
- 软件体系结构的作用
- 非功能性质量与体系结构设计决策
- 软件体系结构的多视图
- MVC体系结构:
- 几种不同的体系结构模式
①分层体系结构:分层、系统级的,将系统组织为多个层次,每个层次对上提供服务层间接口通常会保持稳定
一般不允许跨层,只能由下而上,不能由上而下
-
-
- 优点:层次只要接口不变,可以整个替换
- 缺点:失去对细节的把握,无法进行正常的优化。分层的访问会有性能的问题,需要一层一层将命令进行实现
- 为什么分层体系结构为什么效率低?
-
硬件特性已经不可见了,分层带来的抽象会使得分层的效率低,
②知识库体系结构:共用一个数据库:例如:集成开发环境IDE的知识体系结构
系统及数据在中心知识库中进行管理,组件之间通过共享知识库中数据的方式进行交互。
没有一个中心的控制,全部将信息对中心构件进行交互
适用于人工智能,不存在很强的过程控制,流程性很强的系统不应该使用知识库体系结构
③客户端-服务器(c/s)体系结构(clients-server)
以数据库为中心的客户端-服务器体系结构
系统的通用核心功能被组织为一组服务,多个客户段通过网络共享这些服务。
与B/s browser-server 浏览器-服务器体系结构的区别及优缺点:
-
- b-s升级便利 c-s需要区分不同的平台
- b-s跨平台的能力比较强
- c-s需要有一个应用程序,不能跨平台
- b-s不需要区分平台,只需要在浏览器上进行,b-s的交互能力较为弱, c-s在本地启用,交互能力比较强
- 以后b-s成为主流
- c-s的升级不便利 b-s不需要考虑升级问题
- 由于以前的b-s的交互能力差,而现在b-s的交互能力很强大了,所以它比c-s更占优势
④管道-过滤器体系结构:每个流程的步骤不便,但是流程过程可以改变以改变整个系统的逻辑
一个收款系统的管道-过滤器体系结构
处理组件(过滤器)负责进行数据处理,连接器(管道)负责组件间的数据流动
特点:松耦合,适合做批处理(处理一批数据),交互能力弱,在管道中间不能跟用户交互,管道之间不能中断,需要将处理解决之后才能继续进行下一步处理
管道过滤器是平行的,只是通过管道相连。管道之间的顺序可以进行调整
- 软件体系结构的uml描述:静态结构
①包图:可以是需求的包、组件或模块。表示包和包之间的依赖关系。
②组件图:服务类接口和请求类接口,服务类接口提供服务,组件与组件之间的接口依赖
- Uml描述:动态交互
顺序图:交互方,顺序图与场景相关 顺序图针对交互场景来画,有明确的交互场景,参与本次交互场景的组件参会出现在顺序图中。 虚线-时间线,还未参与交互过程 激活条-时间线,组件在交互过程中已经被激活
实线性箭头表示异步,实三角箭头表示同步 。以组件为单位描述顺序图的交互方
Wait() 异步可以模拟同步,
- UML描述:部署结构
部署图:不同设备的部署方式
- 系统建模及uml图
- 上下文模型:通常显示环境包括多个其他的自动化系统。然而这种模型没有显示环境中的系统与所描述的系统之间关系的类型。外部系统可能会产生提供给系统的数据或者消费来自系统的数据等。所有这些关系都有可能影响所定义的系统的需求和设计,必须加以考虑。所以简单的上下文模型可以和其他模型例如业务过程模型一起使用。
代表uml图:活动图
- 交互模型:①用户交互,其中包含用户输入和输出;②所开发的软件和环境中的其他系统之间的交互
③软件系统内部不同构件之间的交互。
用户交互模型可以帮助识别用户需求,建模系统间的交互可以突出可能出现的系统通信。
代表uml图:用况图、顺序图
- 结构模型:按照构成系统的构件以及他们之间的关系显示系统的组织。结构模型可以是描述系统设计组织的静态模型也可以是描述系统执行时的组织的动态模型。
代表uml图:类图
- 行为模型:是关于系统在运行时的动态行为的模型,这种模型描述了当系统对来自环境的激励进行相应时发生什么或者应该发生什么,激励可以是数据或者事件。
①数据驱动的建模:数据流图(可以用uml中的活动图来表示)
②事件驱动的建模:状态图
③模型驱动的工程:它是一种软件开发方法,其中开发过程的主要产物是模型而非程序。
代码大全
- 在软件架构层面上可以通过把整个系统分解为多个子系统来降低问题的复杂度。
- 一个程序中的设计层次:①系统首先被组织为子系统; ②子系统进一步被分解为类 ③类又被分解为子程序和数据 ④每个子程序的内部也需要 进行设计
2437



被折叠的 条评论
为什么被折叠?



