图片来自湖南大学《软件工程导论》课程 PPT
一、软件工程概述
1 软件和硬件的不同
- 硬件
- 人工制造
- 易磨损(硬件磨损后可以使用备件替换)
- 使用标准化组件制造
- 相对简单
- 制造出来后一般不改变
- 软件
- 开发出来的
- 易退化(需求的不断变更是软件退化的根本原因)
- 自定义组件
- 较为复杂
- 开发出来结果后可能会经常改变
2 软件的概念
- 软件 = 程序 + 数据 + 文档
- 程序:按事先设计的功能和性能需求执行的指令序列
- 数据:程序能正常操纵信息的数据结构
- 文档:与程序开发、维护和使用有关的图文材料
3 软件的本质
具有产品和产品交付载体的双重作用
- 作为产品,显示了由计算机硬件体现的计算能力,扮演信息转换的角色
- 作为产品生产的载体,提供了操作系统、网络、软件工具和环境等的基础平台
4 软件的特点
-
无磨损:抽象不可触摸,潜能不受物理因素的限制(但存在退化)
(磨损是什么?)
- 可用失效率来衡量
- 软件抽象不可触摸,不受物理因素的限制——软件不会磨损,但是存在软件退化现象
- 磨损说明了软硬件的不同 软件的缺陷暗示了设计的缺陷或将设计转化为代码过 程中产生的错误,软件维护通常要面对变更请求,比硬件维护更复杂
-
变更:由于易修改,很容易变得极为复杂
5 软件发展的阶段历程
5.1 第一阶段:程序设计阶段
- 时间:计算机诞生后
- 特点:程序设计
- 代表产品:Micrsoft basic、unix、wps1.0
- 软件工作:代码编写
- 软件评估:程序设计=数据结构+算法,编程技巧
5.2 第二阶段:软件工程阶段
- 时间: 大容量、高速度计算机和高级语言出现、操作系统发展、数据库管理系统诞生;
- 特点:软件危机,主要表现在软件开发进度失控, 费用失控可靠性差, 软件难以维护
- 代表产品:OS 360、美国火箭爆炸、Therac-25肿瘤放射线治疗仪
- 软件工作:软件工程系统的、规范的、定量的工程化方法应用于软件
- 软件评估:可读性、可理解性、可测试性和易修改性等软件质量
5.3 第三阶段:软件过程阶段
- 时间:互联网广泛应用后
- 特点:市场变幻莫测、需求日趋复杂、技术日新月异
- 软件工作:流程活动+流程活动各要素 (如人员、方法、产品等)
- 软件评估:多目标函数(软件质量,开发效率,开发成本)
6 软件神话
软件神话就是谬论:
- 如果进度落后,那么增加多的程序员人手则可以赶上进度
- 对目标一般的称述就足以开始构建项目
- 可以容忍项目需求的变化,因为软件是灵活多变的
- 一旦我们编写了一个工作程序,我们就完成任务了
- 直到程序运行,才能评估质量
- 对于一个成功的项目来说,唯一可交付的工作产品就是程序
- 软件工程会让我们写太多文档,并且减缓我们的开发速度
7 软件工程的概念
- 将系统化的、规范的、可量化的方法应用于软件的开发、运行和维护,即将工程化方法应用于软件
- 以及上述方法的研究
7.1 软件工程方法
为构建软件提供技术上的解决方法
7.2 软件工程工具
为过程和方法提供自动化或半自动化的支持
7.3 软件工程的实践
概念、原则、方法和开发工具的集合。
8 软件过程
8.1 定义
软件过程是从软件项目需求定义开始,直至软件经使用后废弃为止的,跨越软件整个生存期内的系统开发、运行和维护等全部活动、动作和任务及相关项的总和。
8.2 内容
5个主要过程、8个支持过程和4个组织过程
- 5个主要过程为:获取过程、供应过程、开发过程、运行过程、维护过程。
- 8个支持过程为:文档编制过程、配置管理过程、质量保证过程、验证过程、确认过程、联合评审过程、审核过程、问题解决过程。
- 4个组织过程为:管理过程、基础设施过程、改进过程、培训过程。
9 软件过程模型
参考资料:https://www.cnblogs.com/jojop/p/11801241.html
9.1 定义
软件过程模型是软件过程中全部活动生命周期结构框架的一种形式化描述,也称为软件生命周期模型或软件生存期模型。
9.2 经典软件过程模型
9.2.1 瀑布模型——惯例过程模型的一种,又叫作生命周期模型
- 概念
- 将软件生命周期分为计划、分析、设计、编码、测试、运行/维护六个阶段
- 软件开发要遵循过程规律,按次序进行
- 每个阶段均有里程碑和提交物
- 工作==以线性方式==进行,上一阶段的输出是下一阶段的输入
- 特征
- 瀑布状:自上而下,相互衔接
- 各阶段及其活动 :多种模型的基本细粒度元素
- 优点
- 简单、易懂、易用
- 为项目提供了按阶段划分的检查点,项目管理比较规范
- 每个阶段必须提供文档,而且要求每个阶段的所有产品必须进行正式、严格的技术审查
- 缺点
- 实际的项目很少遵守瀑布模型提出的顺序。
- 客户通常难以清楚地描述所有的需求。
- 不支持需求变更
- 由于早期的错误可能要等到开发后期的测试阶段才能发现,所以带来严重的后果。
- 到最后部署才知道产品样子,返工成本巨大
- 适用场合
- 需求相当明确、且较稳定
- 开发团队对这一领域熟悉
- 外部不可控因素少
- 小型的清晰项目或长周期的项目
9.2.1.1 V模型
和瀑布模型顺序一样,但是每个阶段都有测试,尽早发现错误
9.2.2 增量模型——惯例过程模型的一种
- 概念
- 软件被作为一系列的增量来进行开发,每一个增量都提交一个可以操作的产品
- 第一个增量往往是核心产品:满足了基本的需求,但是缺少附加的特性
- 客户使用上一个增量的提交物并进行自己评价,制定下一个增量计划,说明需要增加的特性和功能
- 重复上述过程,直到最终产品产生为止
- 优点
- 提高对用户需求的响应:用户看到可操作的早期版本后会提出一些建议和需求,可以在后续增量中调整。
- 人员分配灵活:如果找不到足够的开发人员,可采用增量模型,早期的增量由少量人员实现,如果客户反响较好,则在下一个增量中投入更多的人力
- 可规避技术风险:不确定的功能放在后面开发。
- 缺点
- 加新增量的时候必须不破坏原有已构造好的东西
- 仍然无法处理需求发生变更的情况
- 管理人员须有足够的技术能力来协调好各增量之间的关系
- 适用
- 以迭代的方式运用瀑布模型,人手不够
- 需求被很好理解,项目的边界固定,可以在短时间内创建全功能系统
9.2.3 演化过程模型
9.2.3.1 原型模型——惯例过程模型 中 演化过程模型 的一种(需求仍不明确)
- 内容
- 第一步:原型 弄清需求并探索可行性
- 第二步:开发产品
- 优点
- 快速开发出可以演示的系统,方便了客户沟通。
- 采用迭代技术能够使开发者逐步弄清客户的需求。
- 缺点
- 为了尽快完成原型,开发者没有考虑整体软件的质量和长期的可维护性,系统结构通常较差
- 用户可能混淆原型系统和最终系统,原型系统在完全满足用户需求之后可能会被直接交付给客户使用。
- 特征及适用范围:减少了需求不明确带来的风险
- 适用场景
- (需求不明确)客户提出了软件的一些基本功能,但是没有详细定义输入、处理和输出需求
- 另一种情况下,开发人员可能对算法的效率、操作系统的兼容性和人机交互的形式等情况不确定
9.2.3.2 螺旋模型——惯例过程模型 中 演化过程模型 的一种(风险分析)
- 特征
- 加入了风险分析(与原型模型最主要的区别)
- 迭代演化:识别每个演化层的风险
- 自上而下
- 优点
- 结合了原型的迭代性质与瀑布模型的系统性和可控性,是一种风险驱动型的过程模型。
- 采用循环的方式逐步加深系统定义和实现的深度,同时更好地理解、应对和降低风险。
- 确定一系列里程碑,确保各方都得到可行的系统解决方案。
始终保持可操作性,直到软件生命周期的结束。由风险驱动,支持现有软件的复用。
- 缺点
- 螺旋模型依赖大量的风险评估专家来保证成功。如果有较大的风险没有被发现和管理,肯定会发生问题。
- 软件开发人员应该擅长寻找可能的风险,准确的分析风险,否则将会带来更大的风险
- 适用场景
9.2.4 喷泉模型——面向对象模型的一种
喷泉模型是专门针对面向对象软件开发方法而提出的。“喷泉”一词用于形象地表达面向对象软件开发过程中的迭代和无缝过渡。
- 特征
- 喷泉状:自底向上
- 迭代演化
- 无缝衔接,复用,并行与集成
- 适用范围
9.2.5 专用过程模型
9.2.5.1 基于构件的开发
能够使软件复用,为软件工程师带来极大收益
9.2.5.2 形式化方法模型
-
优点
- 软件工程师可以应用严格的数学符号来说明、开发和验证基于计算机的系统
- 提供了一种机制,使得在软件开发中可以避免一些问题,如歧义性问题、不完整问题、不一致问题等
-
缺点
- 开发非常耗时,成本也很高。
- 只有极少数程序员具有应用形式化方法的背景,因此需要大量的培训
- 对于技术水平不高的客户,很难用这种模型进行沟通。
-
适用场景
- 用来开发高度关注安全的软件。
- 开发软件出错将导致重大经济损失的软件。
10 软件工程师道德规范
公众、客户和雇主、产品、判断、管理、专业、同僚、自身
二、软件需求综述
1 软件项目成功的三个主要因素
2 软件人成功的三个主要因素
- 需求的把握与控制能力
- 良好的沟通能力
- 责任心与承担责任的能力
3 软件工程和需求工程区别与联系
- 软件需求工程属于软件工程的大范畴,是软件工程的一个分支,其主要对象是软件需求。
- 软件工程是求解软件的工程,需求工程是求解软件需求的工程。
- 将软件工程的原理、方法、技术、手段与软件需求的实际紧密结合,并创造性的应用于软件需求领域。
- 除此之外,还要根据软件需求的特点来发展需求工程的理论、方法、技术和工具。
4 需求的定义和意义
-
什么样的陈述可以作为需求?
必要的、无歧义的、可测的、可跟踪的、可测量的
-
什么是需求?
需求就是以一种清晰、简洁、一致且无二义性的方式, 对一个待开发软件系统中各个有意义功能和性能等方面的陈述的一个集合。
需求是对应当执行的任务的规范说明,描述系统的行为特性或属性,是一种对系统开发进程的约束。
-
意义
需求是软件项目和产品的根源,是后续设计、实现、测试、维护等所有活动的依据;需求工作的优劣对产品影响最大。
5 软件需求的三个层次
业务需求
用户需求
-
站在==用户角度==描述的产品的功能和性能的概要
通过实例( use-case )文档予以说明
系统需求
6 软件需求的分类
7 需求工程的内容和过程
定义:所有与需求直接相关的活动。
7.1 需求开发
- 需求描述:编写SRS
- 需求验证:产生经过验证的SRS
7.2 需求管理
以 SRS 为基线,对需求变更进行控制和管理
7.3 需求工程过程:螺旋迭代过程
8 需求工程方法
需求获取的方法(11个)
- 定义需求的开发过程
确定需求的收集、分析、细化和核实的步骤、方法、模板。
- 定义项目前景与范围
前景说明所有涉众对产品目标的达成的共识;
范围定义了需求是否属于某个特定版本的界线。
- 确定用户群
将可能使用产品的用户组,以避免出现某一用户群的需求被忽略的情况。
- 选择用户代表
为每类用户至少选择一位能代表他们需求的、有时间、有热情、有权利参与需求工作的用户代表。
- 建立核心队伍
把同类产品或产品前版本的用户代表召集起来,从他们那里收集目前产品的功能需求和非功能需求。
- 确定用例
从用户代表处收集他们使用软件完成所需任务的描述——用例,讨论用户与系统间的交互方式和对话要求。
- 确定系统事件和响应
列出系统可能发生的外部事件以及对每个事件所期待的响应时间。
- 举行进一步需求获取的讨论
专门的需求获取讨论会可以方便分析员和客户进行合作。
- 观察用户如何工作
观察用户执行业务的过程。画一张简单的数据流程图或业务流程图,描绘出用户什么时候获得什么数据,并怎样使用这些数据进行业务处理。
- 检查问题报告
客户对当前系统的问题报告及补充需求为新产品或新版本提供了大量丰富的改进及增加特性的想法。
- 需求重用
如果客户要求的功能与已有的某产品很相似,则可查看需求是否有足够的灵活性以允许重用一些已有的软件组件。
需求分析的方法(8个)
- 编制关联图
定义系统与外部实体的界限和接口
- 创建开发原型
当开发人员或用户不能确定需求时,可构建一个开发原型。它可使许多概念和可能发生的事更为直观明了。通过评价原型,能更好地相互理解所要解决的问题
- 分析需求的可行性
在允许的成本、性能要求下,分析每项需求实施的可行性,明确与每项需求实现相联系的风险,包括与其它需求的冲突、对外界因素的依赖和技术障碍。
- 确定需求优先级
应用分析方法来确定use-case、产品特性或单项需求实现的优先级别。以优先级为基础确定产品版本应包含的需求和特性。
- 为需求建立模型
需求的图形分析模型是SRS的极好补充说明。这样的模型包括用例图、数据流程图、实体关系图、状态变换图、对话框图、对象类及交互作用图等。
- 编写数据字典
通过建立数据字典,对系统用到的所有数据项和数据结构进行定义。
- 将需求分解到子系统
必须将包括多个子系统的复杂产品的需求分配到各个软件、硬件以及人员子系统和部件中去。
- 应用质量功能调配(QFD)
质量功能调配(QFD)是一种高级系统技术,它将产品功能、属性与对客户的重要性联系起来。QFD将需求分为三类:普通需求、期望需求、兴奋需求。
需求描述方法(SRS)、需求验证方法、获取知识技能方法、需求管理方法、项目管理方法(略)
方法的使用原则
三、需求获取与分析
需求获取与分析是需求工程中最关键、也是最困难的活动
1 需求获取与分析面临的挑战
- 需求的模糊性:说不清→诱导性访谈,如原型
- 需求的隐蔽性:需求是表象,隐藏在话里或不愿说,自己都不知道→深入型观察和挖掘
- 需求的多样性:每个用户只自己如何使用系统,但没有任何人知道系统整体运行情况 → user cases → 统一user cases
- 需求的变化性:随着项目进展开发人员与客户对系统理解的变化;商务与技术环境的变化→过程迭代-敏捷
2 需求获取与分析的过程
3 获取需求的手段(各种方法有什么区别)
3.1 访谈
3.2 观察与挖掘
- 挑战:需求的隐蔽性
- 形式:现场观察,例如:与用户一起工作(敏捷开发);挖掘用户的意图和目标收益
- 案例:扎根蘑菇群;挖掘用户意图(弄匹马)
3.3 User Case
四、需求规格说明
1 软件需求规格说明
- SRS (Software Requirement Specification ) 也称为功能规格说明、产品规格说明、需求文档或 系统规格说明
- 有三个层次的 SRS
- 作用:记录共识、确认共识、完整正确地传递共识给开发人员
- 要求: 完整性 一致性 可阅读性 无二义性 可修改性 可跟踪性 可维护性
- 一般性方法: 套用模板法,最好是根据组织和个人的经验和项目情况, 对模板进行修改,采用应用模板、适用为主; 优化模板、实用为本的原则编写文档。
- 满足 SRS 的一般性要求
- 描述语言包括自然语言、结构化的自然语言(例如标准化的表格模板)、图形化的建模语言(如 UML,见本章课程后续第三部分)
2 用户需求规格说明的撰写
-
用例(User Case)的构成:要求小型化、独立化
◼ 名称
◼ User (用户)
◼ Case(事件/场景): 描述
- User 与系统的交互 ,系统给反馈
- 通过交互,系统为用户提供的功能/价值
- 提供的功能/价值不涉及内部具体实现
◼ 每个用例给优先级
-
用户界面
用户界面的设计编入系统 SRS 中既有好处也有坏处
- 好处:有助于精化需求并使用户对系统有亲和感和现实感,有助于用户需求的表述和交流。
- 坏处:屏幕图像和用户界面构架是系统设计,而不是用户需求,所以对它的关注可能使需求走入歧途。也限制了开发人员的发挥。
- 合理的权衡点:在系统SRS中加入用户界面组件的概念草图,而在设计和实现时并不一定要精确地遵循 这些草图模型。
-
需求的标识
为了保证 SRS 的可跟踪性和可修改性的质量标准, 必须唯一标识每个软件需求。
序列号、层次型编码、层次型文本标签
-
处理不确定的需求
在实现一个需求集之前,必须解决所有 TBD (to be determined) 问题。
3 需求分析建模与统一建模语言UML
3.1 结构化分析方法
3.2 面向对象
- 面向对象的本质特征
- 抽象
将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面
- 封装
把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口
- 继承
从已有类得到继承信息创建新类,子类继承父类属性和方法
- 多态
包括重载和重写,允许相同或不同子类型的对象对同一消息作出不同响应
- 几种著名的面向对象的方法
- Booch,Coad 一 Yourdon,Rumbaugh,Jacobson
- 统一建模语言UML
- UML 是软件界第一个统一的建模语言,该方法结 合了 Booch, OMT 和 OOSE 方法的优点,统一了符号 体系,并从其它的方法和工程实践中吸收了许多经 过实际检验的概念和技术。
- UML 一种面向对象的可视化的通用建模语言,由 图和元模型组成。图是 UML 的语法,而元模型给 出图的含义,是 UML 的语义
- 一个模型、多个视图
- 这些图提供了对系统进行分析、设计、开发不同 阶段多角度描述。
- 面向对象方法的分析建模总览
- 数据模型:类图 CD
- 功能模型:用例图 UCD
- 行为模型:活动图、状态图、顺序图
3.3 用例图
五、需求验证与变更
5.1 需求验证的任务
很重要的一步,如果不进行在后序发现是需求错误的话,会导致成倍的代价。
验证需求文档,发现错误并修改,需要检查:
- 有效性检查:检查不同用户使用功能的有效性
- 一致性检查:需求之间不应该冲突
- 完备性检查:包括所有用户想要的功能和约束
- 现实性检查:能够用现有技术实现
5.2 需求验证的方法(5种)
- 需求评审
- 原型法
- 首先,**确定合适原型(**见“需求获取与分析”章节), 准备需求验证。
- 将需求验证涉及的业务过程或场景定义出来, 以辅助需求验证过程的开展。
- 根据已定义过程和场景,按照原型执行过程, 发现需求的缺陷、问题并记录,以待后续修正。
- 编写测试用例
- 在需求开发阶段不可能真正进行任何测试,因为还没有可执行的软件,然而可以以需求文档为基础编写测试用例
- 编写用户手册
- 系统的运行环境,硬件要求,环境配置
- 系统功能的详细操作过程
- 问题和故障的解决办法
- 自动的一致性分析(如CASE工具)
- 些自动化工具能部分支持需求定义内在的一致性和完备性检查
需求定义是否准确地反映用户需求的验证 在目前还主要依赖于需求评审和原型示范等技术,缺乏行之有效的系统化方法
5.3 需求签约
签约的意义与作用
- 软件产品最大的问题是需求与范围的不确定性、易动性和软件产品(包括中间产品) 的隐蔽性。
- 软件需求管理和软件项目管理的有效手段 是 “签字确认” 。
- 签约一旦生效,至少表明:
- 1️⃣ 需求开发阶段结束。被确认的SRS表述了双方对项目软件 需求的了解,它是软件需求的基线,开发人员将按基线进行系统开发。
- 2️⃣ 此后的需求变更,要在此基线上通过项目定义的变更过程不定期进行。以后的变更可能会使双方重新协商成本、资源和项目进度等。
- 软件需求的签约,是权利、义务和责任的体现,是软件产品基线、变更控制、软件开发和验收的依据,是软件项目最关键的一步,也是人们最不愿面对的地方。
5.4 需求变更管理
六、 敏捷软件开发 (Agile Process, AP)
1 敏捷软件开发宣言
1.1 4条基本价值观
鼓励集中精力重视左边的内容,但并不是完全排除右边的内容
- 个体和交互 胜过 过程和工具
- 人是软件项目获得成功最为重要的因素
- 合作、沟通以及交互能力要比单纯的编程能力更为重要
- 合适的工具对于成功来说非常重要,工具的作用不能被过分夸大
- 团队的构建要比环境的构建重要得多,应首先致力于构建团队
- 个体和交互建设的难度也高于过程和工具
- 可以工作的软件 胜过 面面俱到的文档
- 软件开发的主要目标是交付给用户可以工作的软件而不是文档
- 编制众多的文档需要花费大量的时间,要保持文档和代码同步,要花费更多的时间
- 编写并维护一份系统原理和结构方面的文档,并且是短小的并且主题突出的
- 直到迫切需要并且意义重大时,才来编制文档 —— Martin文档第一定律
- 客户合作 胜过 合同谈判
- 客户不可能做到一次性地将他们的需求完整清晰地表述在合同当中
- 全方位的满足客户需求的有效途径
- 开发团队与客户紧密沟通和协作
- 为开发团队和客户的协同工作方式提供指导的合同是最好的合同
- 成功的项目需要有序、频繁的客户反馈,成功的关键在于和客户之间真诚的协作,经受住变更
- 响应变化 胜过 遵循计划
- 响应变化的能力常常决定着一个软件项目的成败
- 商务环境可能会变化,这会引起需求的变动
- 随着系统逐渐开始运做,项目关系人(包括开发人员与客户)对系统的理解也会发生变化
- 技术随着时间也在变化
- 意义:敏捷 “变更代表机遇” 的重大认识
- 响应变化的有效途径之一是制定灵活可塑的计划
1.2 12条原则
帮助人们更好的理解宣言中表达的基本价值观
其中第 10 条:简单 —— 使未完成的工作最大化的艺术 —— 是根本的
2 敏捷过程——XP极限编程(敏捷过程模型+方法)
XP 的迭代过程框架:
- 提出了 14 项实践(技术方法 )
- 第 5. 结对编程
- 第 8. 持续集成
- 方法:提倡在一天中集成系统多次,而且随着需求的改变,要不断的进行回归测试;持续集成需要良好的软件配置变更管理工具的有效支持
- 作用:可以使得团队保持一个较高的开发速度,同时避免了一次系统集成的恶梦
- 第 12. 简单的设计
- 第 13. 重构
- 指在不改变系统行为的前提下,重新调整、优化系统的内部结构以减少复杂性、消除冗余、增加灵活性和提高性能
3 敏捷过程之一 —— SCRUM(敏捷过程模型+人员)
发展历史:KenSchwaber 和 Jeff Sutherland 提出
3.1 概念
- Scrum 是包括预定义角色和一系列实践的过程框架
- Scrum 是迭代式增量软件开发过程,通常用于敏捷软件开发
- 迭代:开发一部分,就提交一部分,用户就使用一部分,就反馈一部分,我们就修改一部分
- 最有效的反馈就是当用户用这个软件(或其一部分)时给出的意见
- 目的:一定程度上提供敏捷项目进展状况的外部可见性
- 基本假设
- 外部需求模糊而难以理解
- 开发软件如同开发新产品
- 团队生存在一个快速变化且充满竞争的世界
3.2 角色
- 猪(全身投入项目中)
- Product Owner 产品负责人
- ScrumMaster Scrum 团队的服务式领导
- Scrum Team 开发团队
- 鸡(参与冲刺评审、计划并提供反馈)
3.3 3种工件
-
Product Blacklog (产品待办事项列表)
产品待办事项列表是一个排序的列表,包含所有产品需要的东西,也是产品需求变动的唯一来源。
-
Sprint Backlog (Sprint待办事项列表)
迭代待办事项是由Scrum团队成员确定的在迭代期间完成的任务。
-
Sprint Burn-down Chart (燃尽图)
每天由Scrum Master 对迭代中预估的工作剩余量进行计算并绘制成图表,从而生成如下迭代燃尽图。
3.4 5个会议
- Sprint计划会议(Sprint Planning Meeting)
- 每日站会(Daily Scrum Meeting)
- Sprint评审会议(Sprint Review Meeting)
- Sprint回顾会议(Sprint Retrospective Meeting)
- 产品Backlog梳理会议( Product Backlog Refinement)(如果问的是 4 个会议就没有这个)
3.5 过程模型——迭代式增量过程
-
计划体系结构设计
-
按优先级排序形成 Backlog 列表,核心工件:
Backlog 为急待完成的一系列任务,列表条目的体现形式通常为用户故事,包括:未细化的品功能要求、Bugs、缺陷、用户提出的改进、具竞争力的功能及技术升级等,按优先级排序形成Backlog 列表,根据该表和风险评估制订产品交付基线。
-
建立系统体系结构并分解 Backlog 项:
建立系统体系结构(如为已有系统改进,则只作有限分析、调整),将Backlog项按高内聚低耦合的原则分解为一系列问题包(Packets,每个 Packet 是一组对象或构件的集合) ,依据同样原则相应划分若干个开发小组(SCRUM 小组),分配各小组合适的Backlog 项或问题包。建立开发运行环境
-
Sprint
在Sprint中,Scrum团队从产品Backlog中挑选最高优先级的需求进行开发。挑选的需求在Sprint计划会议上经过讨论、分析和估算得到相应的任务列表,我们称它为Sprint backlog。
若干快速迭代的 Sprint (冲刺) 组成:
一个短的迭代周期称为一个Sprint
一个Sprint限定周期为2-4周;
一个Sprint由开发(设计、开发、实施、测试、文档化)、打包(Wrap)、评审(Review)、调整(Adjust) 组成;
每个 SCRUM 小组并行开发且同步完成;
-
交付和巩固
类似于传统方法中的维护和改善:
在每个迭代结束时,Scrum团队将递交潜在可交付的产品增量。一旦根据风险评估结果认为可交付产品时,即进入该阶段。
该阶段的活动包括:组装,系统测试和回归测试(Regression),准备培训材料,完成最终文档。SCRUM 过程认为一个产品的开发将一直持续下去,除非经风险评估后认为应停止。
3.6 SCRUM以上三个过程的特点
-
确定性过程(Defined Process)
可明确描述的、可预测的过程,因而可重复(Repeatable)执行并能产生预期的结果,并能通过科学理论对其最优化
-
经验性过程(Empirical Process)
与确定性过程相反,作为一个黑箱(Black box)处理,通过对黑箱的输入输出不断进行度量,在此基础上,结合经验判断对黑箱进行调控,使其不越出设定的边界,从而产生满意的输出。
SCRUM将开发中的分析、设计、实施视为一个Sprint黑箱,认为应加强黑箱内部的混沌性,使项目组工作在混沌的边沿,充分发挥人的创造力。如将经验性过程按确定性过程处理(如瀑布模型),必将使过程缺乏适应变化的能力
3.7 作为一种迭代式增量过程,SCRUM的过程模型与螺旋模型有何不同
七、统一过程 (Rational Unified Process, RUP)
各种过程模型之间要做比较
1 RUP的定义、内容及特点
定义:统一过程(RUP/UP,Rational Unified Process)是一种以用例驱动、以体系结构为核心、迭代式增量的软件过程模型,由UML方法和工具支持,广泛应用于各类面向对象项目
特点:RUP的开放性、通用性、完善性、多功能性和广泛的适用性
RUP软件过程模型特点:迭代 & 增量 & 并行
2 RUP的软件过程模型
2.1 纵轴
生命周期中的静态结构——九个核心工作流程
- 核心过程工作流程:前 6 个
- 核心支持工作流程:后 3 个
- 表示方法:UML 中:协同图、时序图、活动图;RUP 中:采用活动图(交互 + 状态结果)
- 内容:一套完整的 UML 使用指南
- ① 业务建模:产生的主要工件 :业务模型(业务用例模型+业务对象模型)
- ② 需求:用例模型,用户界面模型
- ③ 分析设计:一个设计模型
- ④ 实现:实施模型(模型元素包括实施子系统和构件)
- ⑤ 测试:测试模型(模型元素包括测试用例、测试过程和测试构件)+ 测试结果
- ⑥ 部署:产品的一个版本+文档培训资料
- ⑦ 配置和变更管理:配置管理计划、变更请求、项目存储库和工作区
- ⑧ 项目管理:商业理由、迭代计划、风险管理计划、质量保证计划及相应的评估文档
- ⑨ 环境:工作流程指南、工具、工具指南
2.2 横轴
生命周期中的动态结构——四个阶段
- 每个阶段:由一次或多次迭代完成
- ① Inception 先启阶段:目标:建立业务用例、确定项目的边界
- ② Elaboration 精化阶段:目标:建立稳定的构架、编制项目计划、淘汰项目中最高风险的元素
- ③ Construction 构建阶段:目标:所有构件和应用程序功能被开发并集成为产品、所有的功能被详尽的测试
- ④ Transition 产品化阶段:目标:将软件产品交付给用户群体
3 比较RUP的生命周期模型与螺旋模型的异同点
相同点:迭代特性 |
重复一系列组成系统生命周期的循环 |
每次循环的结束是向用户交付产品的一个运行版本 |
每个循环由若干次迭代组成 |
每次迭代需要进行风险分析处理 |
每次迭代结束的标志是交付一个增量 |
螺旋模型:每次迭代历经笛卡儿坐标系中四个象限的四个方面活动 |
RUP:每次迭代历经九个核心工作流程中的若干个 |
不同点:螺旋模型 |
RUP |
未给出每次迭代过程结束交付的增量原型的具体要求 |
将整个生命周期划分为四个阶段,明确给出了每个阶段内的若干次迭代过程完成后交付的增量的具体要求,即四个阶段的主要里程碑——生命周期目标里程碑、生命周期构架里程碑、最初操作性能里程碑和产品发布里程碑 |
也未给出不同次迭代在历经的笛卡儿坐标系中四个象限的四个方面活动的内容与重点的不同 |
同时详细阐述了不同阶段中的不同迭代过程历经的九大核心工作流程中活动内容的重点和强度的不同 |
|
提供了对每次迭代过程中不同核心工作流程活动的并行化支持 |
|
RUP的二维生命周期结构对“迭代”意义的体现比螺旋模型更深刻、具体、详尽、全面,更具可操作性 |
4 RUP的优点
5 比较敏捷开发与统一过程在过程模型方面的异同
(略)
八、面向对象和UML
1 面向对象的开发 OOD
- 面向对象的分析、设计和编程是相关的,但是不同的。
- OOA 面向对象分析法 关注开发应用程序领域的对象模型。
- OOD 关心的是开发面向对象的系统模型来实现需求。
- OOP 关心的是使用 OO 编程语言(如 Java 或 C++) 实现 OOD。
2 OOD的特性
- 对象是现实世界或系统实体的抽象,并自我管理。
- 对象是独立的,封装数据和方法。
- 系统功能以对象服务表示。
- 消除了共享数据区域。对象通过消息传递进行通信。
- 对象可以分布,可以按顺序或并行执行。
3 OOD的优势
- 更易于维护。对象可理解为独立实体。
- 对象可能是可重用的组件。
- 对于某些系统,可能有从真实世界的实体到系统对象的明显映射。
4 UML概述
- UML 是软件界第一个统一的建模语言,该方法结 合了 Booch, OMT 和 OOSE 方法的优点,统一了符号体系,并从其它的方法和工程实践中吸收了许多经过实际检验的概念和技术。
- UML 是第三代面向对象的开发方法,是一种面向对象的可视化的通用建模语言,由 图和元模型组成。图是UML的语法,而元模型给 出图的含义,是 UML 的语义
- 一个模型、多个视图
- 这些图提供了对系统进行分析、设计、开发不同 阶段多角度描述。
- 不是软件开发过程或方法,可用于开发周期中所有流程/阶段,跨越不同的实施技术
5 UML用途
- 使用用例和参与者显示系统中的主要功能和边界。
- 使用交互图说明用例实现。
- 使用类图表示系统的静态结构。
- 使用状态图对对象行为进行建模。
- 使用组件和部署图显示物理体系结构的实现。
- 使用构造型增强功能。
6 UML 图表类型
第一种分类
-
结构图(静态)
-
行为图(动态)
- 用例图 :显示了外部参与者所观察到的系统功能
- 序列图
- 协作图
- 状态图
- 活动图
第二种分类
类图和顺序图
1 类图
1.1 类图中的关系
- 依赖(虚线箭头,use a关系,知道其存在)
- 单向关联(一般箭头,强依赖关系)
- 双向关联(实线,互相引用)
- 继承/泛化(三角箭头,指向父类)
- 实现(类指向接口,三角虚线箭头)
- 组合(整体指向部分,整体实心菱形,部分不可以独立存在)
- 聚合(整体指向部分,整体空心菱形,部分可以脱离整体存在)
1.2 类图中的类
- “目”,类名-属性-方法,窗可以为空但不能缺少
- 权限 属性名:类型 [ = 默认值 ]
- 权限 方法名称(参数列表) [ : 返回类型]
其中权限表示为:
- public:+
- protected:#
- private:-
1.3 题目要求
- 属性要5个以上
- 方法要写3个
- 类个数不能少于3个
- 类之间的关系要写正确
- 英文命名,可以打个括号写中文解释
2 顺序图
- 要求:5个交互对象以上
- 对象名:从实现的角度,类名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zqRJF6Oj-1618209073327)(C:\Users\89167\AppData\Roaming\Typora\typora-user-images\image-20210401152104995.png)]
活动图和状态图
1 活动图
1.1 注意事项
- 表达规范、统一(如果线如果是直线就一直是直线)
- 分支要写【条件】,一定要用中括号!
- 要包括 5 个活动以上
- 一律用原矩形框
- 起点终点的画法
- 分支表示选择;分叉表示并行
- 用什么方式分出去,就用什么方式会合
1.2 完整例子
需熟练掌握画法:
2 状态图
2.1 要求
- 5个状态以上
- 圆角矩形
- 注意开始符号和结束符号
- 每个圆角矩形里只需要写状态名字
2.2 状态转移条件
- 事件
- 事件【事件的条件】
- 事件A/事件B
- 【条件】
2.3 示例
九、组件设计
1 什么是好的设计?
- 设计目标
- 将系统分解为组件
- 描述组件功能
- 确定组件之间的关系
- 指定组件接口
- 主要概念和原则(梦幻联动到 < 十三, 3 >)
- 软件设计,具有利弊的编程范式
- 内聚
- 耦合
- 信息隐蔽
- 依赖管理的重要性
- 良好设计的标准
- 良好设计的原则与规则
2 什么是良好的组件设计?
- 准则guideline、规则rules、启发式heuristcs
3 如何应用良好的设计?
4 组件接口
组件接口由几个部分组成:
- 出口:向其他组件提供的服务
- 进口:其他组件所需的服务
- 访问控制:例如受保护/私有/公共(java 中的包访问)
5 分解
通过将大问题拆分为较小的问题来处理复杂性,“分而治之”
5.1 如何分解
- 选择问题的一部分(从整个问题开始)
- 使用设计范式确定本作品中的组件
- 描述组件交互(依赖性、通信间)
- 重复步骤 1 到 3,直到满足某些终止条件
5.2 分解原理
6 组件
6.1 组件可以是
- 一个代码单位,
- 有一个 (或多个) 名称
- 具有可识别的边界 可(重新)
- 由其他组件使用
- 封装数据
- 隐藏不必要的细节
- 可以单独编译
- 封装抽象表示的 SW 实体(包括数据及其操作)
- "工作"分配
6.2 组件接口的组成
- exports 出口:向其他组件提供的服务
- imports 进口:其他组件所需的服务
- Access Control:访问控制,如java中的protected/private/public
7 模块化
模块化系统应构建成可识别的抽象(称为组件)
- 组件应具有指定良好的抽象接口
- 组件应具有高内聚和低耦合性
7.1 模块化的好处
模块化有利于软件质量因素,例如:
- 可扩展性:定义良好的抽象接口
- 可重用性:低耦合、高内聚性
- 可移植性:隐藏计算机依赖关系(限制修改)
模块化对于良好的设计非常重要,因为它:
- 增强以分离关注点
- 使开发人员能够通过分散式软件架构降低整体系统复杂性
- 通过支持多个人员的独立和并发开发,提高可扩展性
7.2 Meyer评估模块化的五项标准
- 可分解性 Decomposability 较大的组件是否分解成更小的组件?
- 可组合性 Composability 较大的组件是否由较小的组件组成?
- 可理解性 Understandability 组件是否单独理解?
- 连续性 Continuity 对规范的少量更改是否会影响本地化和有限的组件数量?
- 保护性 Protection 运行时异常的影响是否局限于少数相关组件,并以预定义的方式处理?
7.3 Meyer模块化的五个规则
- 直接映射:使解决方案的结构与建模问题域的结构兼容
- 很少接口:每个组件都应尽可能少地与其他组件通信,减少依赖 (不要太多依赖)
- 小型接口:如果任何两个组件进行通信,它们应尽可能少地交换信息 (不要太复杂)
- 明确的接口:每当两个组件 A 和 B 通信时,这必须从 A 或 B 的文本中明显或两者同时出现 (不要窃窃私语)
- 信息隐蔽:信息隐藏是增强抽象的一个手段
十、详细设计
1 设计模式六原则
原则 |
含义 |
实现方法 |
开闭原则 Open-Closed Principle (OCP) |
对扩展开放,对修改关闭 |
多使用抽象类和接口 |
依赖倒转原则 Dependency Inversion Principle (DIP) |
高层组件不依赖低层组件 |
尽量使用合成/聚合,而不是使用继承 |
里氏代换原则 Liskov Substitution Principle (LSP) |
基类可以被子类替换 |
使用抽象类继承,不使用具体类继承 |
迪米特法则(最少知道原则)LKP |
一个软件实体应当尽可能少地与其他实体发生相互作用 |
通过中间类建立联系 |
接口隔离原则 Interface Segregation Principle (ISP) |
使用多个隔离的接口,比使用单个接口好 |
建立最小的接口 |
单一职责原则 Single Responsibility Principle (SRP) |
一个类只负责一项职责 |
应该有且仅有一个原因引起类的变更 |
1.1 里氏代换原则(LSP)
-
含义:基类可以被子类替换
-
解释:
- 继承应确保关于超类对象所拥有的属性也适用于子类对象
- 为了让 LSP 保持,并据其一起使用 OCP,使用基类的指针或引用的函数必须能够在不知道的情况下使用派生类的对象。所有的衍生工具必须符合客户对它们所使用的基类的期望行为
-
实现方法:使用抽象类继承,不使用具体类继承
-
通过合同设计
在派生类中重新定义方法时,只能将其先决条件替换为较弱的预置条件,将其后置条件替换为更强的预置条件。(子类比父类要求更少,但做的更多)
Advertised Behavior of an object 对象的播发行为:
- advertised Requirements (Preconditions)(先决条件)
- advertised Promises (Postconditions)(后置条件)
-
OOD 中的 is-a 关系
- LSP 明确表明,在 OOD 中,ISA 关系与行为相关。
- 不是内在的私有行为,而是外在的公共行为;
- 客户端所依赖的行为。
- 为了让 LSP 保持,并据其一起使用"开放-关闭"原则,
- 所有衍生工具必须符合客户端期望他们使用的基类的行为。
-
LSP 是 语义 (Semantics) 和 可替换 (Replacement) 相关的
- 设计前understand
- 必须明确记录每个方法和类的含义和目的,用户理解会导致实际违反 LSP
- 可替换性至关重要
- 每当任何系统中的任何代码引用任何类时,该类的任何未来或现有子类都必须是 100% 可替换的;
- 迟早会有人用子类代替子类,这几乎是不可避免的。
-
LSP 和 可替换性
任何代码都可以合法地调用另一个类方法,即必须能够替换该类的任何子类,而无需修改
-
相关启发式
派生类使用 NOP 方法重写基类方法是非法的,NOP = 无操作
- 解决方案1:反向继承关系
- 解决方案 2:提取通用基类
- 状态差的类
-
(百度)意义
- 防止重写父类方法,出现父类复用性差的情况。
- 程序运行正确性的保证,即类的扩展不会给系统带来新的错误,降低了出错的可能性。因为子类重写了父类方法,在使用多态特性时,程序可能会出现不可预知的错误。
-
(百度)做法
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类的方法覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
-
例子:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nU1rxVcI-1618209073330)(C:\Users\89167\AppData\Roaming\Typora\typora-user-images\image-20210401151524889.png)]
1.2 开闭原则(open-close principle, OCP)
-
OCP的关键:抽象与多态性
-
含义:对扩展开放(模块的行为可以扩展),对修改关闭(模块的源代码不得更改),应编写无需修改即可扩展的模块
-
实现方法:多使用抽象类和接口
-
原则:可维护、可重复使用且健壮。
-
解释:
- 模块的行为可以拓展,但模块的源代码不可以修改;
- 一个类不依赖于一个具体的类,而是依赖抽象类或接口,使用多态。
-
战略关闭(将变与不变的东西隔离开)
- 关闭不完整,但具有战略意义
- 通常,无论模块有多"封闭",总会有某种更改,而该更改不会关闭。
- 使用抽象获取显式关闭
- 使用"数据驱动"方法实现关闭(数据驱动例如配置文件)
- 将易失性政策决策放在单独的位置,如文件
- 最小化未来更改位置
-
相关启发式
1.使所有成员变量都私有,无全局变量!全局变量易“牵一发而动全身”
- 对公共数据的更改始终面临"打开"模块的风险
- 它们可能具有波普尔效应,需要在许多意外位置进行更改
- 错误可能难以完全找到和修复,修复一处可能导致其他位置出现错误。
- 非私有成员可修改
2.RTTI是丑陋和危险的(RTTI = 运行时类型标识)
- 如果模块尝试动态地将基类指针强制转换到多个派生类,则每次扩展继承层次结构时,都需要更改模块
- 通过类型开关或 if-else-if 结构识别它们
- 并非所有这些情况都违反 OCP,当仅用为"过滤器"时(只需绘制一个圆圈)
-
举例:
-
违反 LSP 或 DIP 总是导致违反 OCP,LSP 违规是 OCP 的潜在违规
1.3 依赖倒转原则(DIP)
-
含义:高层模块不依赖底层模块(抽象应该属于高层模块,并由低层模块实现)(百度)程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。当高层的模块依赖于低层的模块时,这些高层模块就很难在不同的环境中复用。但是,当那些高层模块独立于低层模块时,它们就能很简单地被复用了。这正是位于框架设计的最核心之处的原则。
-
实现方法:尽量使用合成/聚合,而不是使用继承
-
解释:
- 高层模块不应依赖低层模块,两者都应该依赖于抽象(在继承层次结构中,基类不应该知道它的任何子类,面向接口编程);
- 抽象不应该依赖于具体(已经详细实现的模块),具体应该依赖于抽象
-
OCP 指出目标,DIP 指出该机制,LSP 是 DIP 的保证
-
相关启发式
1.设计到接口,而不是实现!
- 使用继承避免直接绑定到类:(桥接模式)
- 抽象类/接口:
- 往往变化较少
- 抽象是"铰链点",它更容易扩展/修改
- 不必修改表示抽象的类/接口,但可扩展它们 (OCP)
- 异常
- 有些类不太可能改变; 因此,插入抽象层没有什么好处
- 在这种情况下,可以直接使用混凝土类 如在 Java 或 C++
2.避免传递依赖
-
避免较高级别的层依赖于较低级别的抽象的结构: 例如,策略层最终取决于实用程序层。
-
使用继承和抽象祖先类有效消除传递依赖关系:也是接口所有权的问题
(百度:当只实现第一部分:“依赖抽象”,但不实现第二部分“抽象属于高层模块”时,一种常见的做法是将接口与其实现类放在同一个表示低层抽象的包内)
3.如果有疑问,请添加间接级别
-
实例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfUTYolU-1618209073335)(C:\Users\89167\AppData\Roaming\Typora\typora-user-images\image-20210401151600366.png)]
1.4 迪米特法则(最少知道原则)(LKP)
-
含义:一个软件实体应当尽可能少的与其他实体发生相互作用
-
实现方法:通过中间类建立联系
-
解释:方法不能乱调用,只能调用下面类型(直接 friend)的方法:
- 同一个类中的其他方法
- 传递进来的参数对象的方法
- 在方法中自己实例化的任何对象的方法
- 当前对象内部的组件的方法
-
一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。
-
优势
-
耦合控制
减少数据和通信的耦合
-
信息隐蔽
阻止检索对象的子部分
-
信息限制
限制提供信息的方法的使用
-
接口少
-
明确的接口
显式说明方法中可以使用哪些类
1.5 接口隔离原则(ISP)
- 含义:使用多个隔离的接口,比使用单个接口好
- 实现方法:建立最小的接口
- 解释
1.6 单一职责原则(SRP)
- 含义:一个类只负责一项职责
- 实现方法:应该有且仅有一个原因引起类的变更
十一、构建分析模型
两种分析类型:结构化分析(SA)、面向对象分析(OOA)
1 分析模型的元素
- 基于场景:从用户的视角描述系统;user case、活动图、泳道图
- 面向流:表示数据对象在系统移动时如何转换;数据流图(不考)
- 基于类:三大基本特征:封装、继承、多态;UML类图
- 基于行为:显示了软件如何对外部事件或激励作出响应;顺序图
2 面向对象设计最关键之处:选择类,选择类的6个准则
(教材P110 P128)
- 保留信息::记录潜在类的信息
- 必须的服务:潜在类有一组可改变类属性的操作
- 多个属性
- 公共属性
- 公共操作
- 必须的需求:外部实体,任何系统解决方案运行时所必需的生产或消费信息
2.1 基于类来分析SafeHome的步骤
-
描述属性
-
系统类图
-
定义操作
-
…
十二、构建设计模型 1
1 良好的软件设计应展示
- Firmness(稳定性):程序不应有任何错误来抑制其功能。
- Commodity(适用性):程序应适合其预期目的。
- Delight(令人愉快):使用程序的经验应该是愉快的。
2 设计概念
- 抽象:数据,过程,控制
- 架构:软件的整体结构
- 模式:“传达”一个经过验证的设计解决方案
- 模块化:数据和功能的划分
- 信息隐蔽:接口
- 功能独立性:高内聚和低耦合
- 重构:在不影响行为的情况下改进设计
- 细化:对所有抽象的细节进行细化
3 模式
- 体系结构模式表示软件系统的基本结构组织架构。它提供了一组预定义的子系统,指定了它们的职责,并包括了组织它们之间关系的规则和准则。
- 设计模式提供了一种方案,用于优化软件系统的子系统或组件,或它们之间的关系。它描述了一种常见的通信组件结构,用于解决特定上下文中的一般设计问题。
- 习惯用法是特定于编程语言的低级模式。习惯用法描述了如何使用给定语言的功能实现组件的特定方面或它们之间的关系。
4 为什么模块化modularity
定义:软件被划分为独立命名的、可处理的构件
- 使开发工作更易于规划
- 可以定义和交付软件增量
- 更容易实施变更
- 能够有效地开展测试和调试
- 可以进行长期维护而没有严重的副作用
5 说明解释模块化和软件成本的关系
开发单个软件模块的工作量(成本)随着模块数的增加而下降。给的同样的需求,更多的模块意味着每个模块的规模更小。然而,随着模块数量的增加,集成模块的工作量(成本)也在增加。事实上,存在一个模块数量M可以带来最小的总体软件开发成本。但是我们缺乏成熟的技术来精确地预测M。在进行模块化时,注意保持在M附件,避免不足的模块化或过度的模块化问题。
6 信息隐蔽Information hiding
6.1 定义
通过一系列独立的模块得到有效的模块化,独立模块之间只交流实现软件功能所必需的信息
6.2 特征
每个模块对其他模块都隐蔽自己的设计决策
6.3 信息隐蔽的目的
将数据结构和处理过程的细节隐藏在模块接口之后,用户不需要了解模块内部的具体细节。
6.4 为什么信息隐蔽
加强对模块内过程细节的访问约束以及对模块所使用的任何局部数据结构的访问约束
将信息隐蔽作为系统模块化的一个设计标准将很有用。
- 降低"副作用"的可能性
- 限制本地设计决策的全球影响
- 强调通过受控接口进行通信
- 不鼓励使用全局数据
- 导致封装 - 高质量设计的属性
- 产生更高质量的软件
7 功能独立functional
独立性通过内聚性和耦合性进行评估。
7.1 内聚性cohesion
- 显示了某个模块相关功能的强度
- 一个内聚的模块执行一个独立的任务,与程序的其他部分构件只需要很少的交互
7.2 耦合性coupling
- 显示了模块之间的相互依赖性
- 耦合性依赖于模块之间的接口复杂性、引用或进入模块所在的点以及什么数据通过接口进行传递
8 逐步求精Stepwise Refinement
通过连续化过程细节层进行应用开发,…(略)
9 横切Aspect
…(略)
10 重构
重构是更改软件系统的过程,它不会改变代码 [设计] 的外部行为而是改进其内部结构。
在重构软件时,将检查现有设计的冗余性、未使用的设计元素、低效或不必要的算法、拙劣或不当的数据结构、其他设计不足,修改这些不足以产生更好的设计。
11 设计类
- 用户接口类,定义人机交互
- 业务域类,识别实现某些业务域所必需的属性和服务
- 过程类,管理业务域类的较低级别的业务抽象。
- 持久类,在软件执行后持续存在的数据存储(数据库)。
- 系统类,管理和控制功能,使系统能够在其计算环境和与外部世界之间运行和通信。
12 什么才是组织良好的设计类
- 完整性与充分性 – 完整地封装所有合理预见的存在于类中的属性和方法。
- 原始性 – 每种方法都应该专注于实现某一个服务。
- 高内聚性 – 具有小的、集中的职责,并专注于使用属性和方法来实现职责。
- 低耦合性 – 协作应保持在可接受的最低水平。
13 设计模型的元素
前四个是主要元素。详情看书上P146 P165
- Data 数据设计元素
- Architectural 体系结构:设计元素给人总体的外貌设计
- Component 构件设计元:数据结构、算法;设计原则:开闭原则
- Interface 接口设计元素:用户界面(关键)、外部接口、内部接口
- Deployment 部署设计元素
设计模型的维度
十三、构件级设计
以面向对象的观点来看,构件是协作类的集合。组件级设计定义分配给每个组件的数据结构、算法、接口特征和通信机制。
1 构件设计的基本原则
- 依据合同设计 Design by Contract
- 开闭原则 OCP:模块应打开以进行扩展(+),但关闭以进行修改。
- 可替代性,子类型替换 LSP:子类应可替代基类
- 依赖于抽象 DIP:取决于抽象,不要依赖具体
- 接口分解 ISP:许多特定于客户端的接口优于一个通用接口;接口的粒度要合适:太大的粒度容易导致重用性差;但是粒度也不能太小,太小导致导致容易变化。
2 内聚性
内聚关系意味着单个组件或类只封装彼此之间以及类或组件本身密切相关的属性和操作。
2.1 分类
-
功能内聚
通常应用于操作,当一个模块完成一组且只有一组操作并返回结果。
-
分层内聚
适用于包、组件和类。高层可以访问低层的服务,但低层不能访问高层的服务。
-
通信内聚
访问相同数据的所有操作被定义在一个类中。 通常,这些类只着眼于有关数据的查询、访问和存储。
2.2 方法
- 少使用全局变量
- 少使用类的继承,多用接口隐藏实现的细节
- 模块的功能化分尽可能的单一
3 耦合性
类或组件之间彼此联系程度的一种定性度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。
- 要避免
- 内容耦合:当一个组件暗中修改其他组件的内部数据时发生,这违反了基本的软件设计概念中的信息隐蔽原则
- 谨慎使用
- 需注意
- 常规调用耦合:在面向对象的编程中,某些类型的耦合经常发生。
- 类型使用耦合
- 包含或导入耦合
3.1 方法
- 模块只对外暴露最小限度的接口,形成最低的依赖关系。
十四、用户体验与可用性
1 什么是用户体验
包括终端用户与公司、服务和产品交互的所有方面
- 满足客户的确切需求,无需大惊小怪或觉得麻烦
- 简单和优雅,生产出的产品让人拥有和使用都很愉快
- 远远超出了满足客户的需求,不仅仅是其提供的功能列表
- 高质量的用户体验应是多学科的综合:工程、市场、图形和工业设计、接口设计
2 设计的三个层次:好的设计应同时达到三个维度
该模型基于ABC model (affect, behavior, and cognition). 但添加了新的内容。
- Visceral 直觉设计:由外观解释产品本身,即设计可视性
- Behavioral 行为设计:产品的使用效率与满意度,即使用性的范畴;外表并不重要。理由并不重要。性能。(功能、可理解性、可用性和物理感觉)
- Reflective 反映设计:与产品的合理性与其推理性有关
3 可用性的四个属性和目标(目标通常由以下属性的一部分定义或衡量)
- Effectiveness 有效性:能够完成任务
- Efficiency 高效性:效率高,用户的目标可以准确和全面地完成,通常以任务时间、完成任务所需的工作量来衡量
- Learnability 可学习性:容易用,易上手,指经过培训和花费一定的时间在操作系统上,用户熟练操作系统的能力。
- Satisfaction 满意度:用户对其任务满意度,通常通过书面和口头提问捕获。
4 用户体验和可用性的区别
- 用户体验包含了个体在与产品交互的过程中,对产品的思想、感受和感知等
- 可用性更注重功能
(这后面用户什么的东西就没咋看了)
5 以用户为中心的设计原则
- 产品开发前,用户早期参与,以免后期改动;
- 在产品原型阶段的可用性测试
- 迭代设计
将以用户为中心的设计原则融入产品生命周期
6 是什么造就了成功的产品
- Capability:技术能力,我们的技术能构建什么样的产品
- Viability:生存能力,怎样才能留g住顾客
- Desirability:可取性,客户想要拥有产品
十五、SOA
1 基本思想
-
SOA:Service Oriented Architecture,面向服务的架构,或者说,以服务为基础搭建的企业IT架构
-
SOA中服务(Service)的理念,本质上是一种业务和技术完全分离,业务和技术又能自由组合的思想。它达到了目前软件设计思想的最高境界。
-
面向对象是对面向过程的一次解耦和封装,把逻辑紧密相关的程序结合成独立的对象单元;
面向组件是将面向对象的程序进行进一步封装,发布成独立的组件(与面向对象最大的区别在于通过传输协议来进行远程调用的);
面向服务是对面向组件编程的进一步解耦和封装,业务组件可以自由地绑定各种传输协议。所谓”面向服务”,就是如何实现独立于技术的服务接口。
2 基本要素(三个元素)
-
松散耦合
指相互之间的依赖程度,包括了
【服务】(不同服务的功能不要互相依赖, 相对独立而完整)、
【接口和实现】(J2EE或.NET只需WSDL就可以调用WEB SERVICE的服务接口)、
【业务组件和传输协议】(传输协议和位置的透明)
之间的松散耦合
-
粗粒度
意思是SOA中服务的接口应该比面向对象的编程的API要大一些。
-
位置和传输协议透明(最根本的区别于目前面向组件编程的地方)
目前的一些服务组件都是和特定的应用服务器绑定在一起的,如果某个服务组件的URL位置 修改了,客户端程序就必须要做出相应的修改,此即为位置组件的不透明
- 位置透明:指不论服务组件的实际位置URL如何变化,客户端的调用程序的URL都不需要改变
- 传输协议的透明:指不管服务组件的传输协议如何变化,客户端的调用程序的传输协议都不需要改变。
3 服务架构模式
- 以服务为核心的体系架构,并涵盖服务的整个生命周期,是分层架构:建模-开发-装配-运行-管理。
- SOA的核心理念是业务驱动,采用松耦合的、灵活的体系架构来满足随需应变的业务需求。
- 以服务为核心的体系架构可以提供松耦合、异构的企业级计算环境。
3.1 服务与服务总线
- 最底层的功能性服务,到原子服务和服务构件,到顶层的业务流程服务,目的是最大限度地封装不同的服务,从而达到复用的目的;无论哪一个层次,其核心都是服务。
4 SOA架构的三种角色
- 服务提供者:发布自己的服务,并且对服务请求进行响应。
- 服务注册中心:注册已经发布的web service,对其进行分类,并提供搜索服务。
- 服务请求者:利用服务中心查找所需要的服务,然后使用该服务。
5 SOA架构的工作流程
- 发布操作:为了使服务可访问,需要发布服务描述以使服务使用者可以发现它。
- 查找操作:服务请求者定位服务,方法是查询服务注册中心来找到满足其标准的服务。
- 绑定操作:在检索到服务描述之后,服务使用者继续根据服务描述中的信息来调用服务。
6 SOA的相关标准
- SOAP: 简单对象访问协议 (Simple Object Access Protocol)
- WSDL: Web服务描述语言 WSDL (Web Services Description Language)
- UUDI: 统一描述、发现和集成 (Universal Description, Discovery and Integration)
7 可用性 / 可见性
十六、云计算
1 什么是云计算
- 云是互联网的隐喻,是它隐藏的复杂基础设施的抽象。
- 从工程观点:在分配给大型物理机器的虚拟机上提供服务
- 从商业观点:一种解决大规模应用程序可伸缩性的方法
2 为什么要用云
2.1 背景
某个公司想更新它的设备还是什么容器,发现不够了/或者不用设备的时候又空闲着很浪费。用了云计算有什么好处 为什么要云计算,不用云计算会咋样呢
- 应用程序的不规则负荷,导致预测负荷稳步增长
- 传统IT容量由于资本的原因一般是逐步购买的(很难一次到位)
- (开始分析)大多数组织明显高估或低估他们需要运行其应用程序的资源量,这将导致为基础设施和整体应用交付更高的成本。
- 随着时间的推移,实际负载高度变量
- 期间,有产能过剩、资本铺设闲置、运营成本浪费供电和冷却的服务器
- 期间,由于没有足够的能力而让我们的客户得到一个好的体验
2.2 为什么
- 不必支付硬件,降低成本
- 减少冗余容量的浪费,使资源充分利用
- 按需提供计算容量,确保我们可以随时为高峰期提供足够的IT容量
- 容量可以流的方式快速购买(无需提前订购的服务器),可以减少容量需求消退
3 云计算的基本形式 服务的三种形式
含义,区别,举个例子说明是什么
-
IaaS(基础设施即服务):只提供云计算的基础平台(只提供网络、存储、服务器、虚拟化(没有虚拟化就没有云计算))。如VMware
-
PaaS(平台即服务):在IaaS基础上还提供操作系统、中间件、运行时的组件(团队项目部署属于这个)
提供在其平台上构建和部署自定义应用程序的能力。 它减少了对专有 SaaS 平台的依赖,这些平台通常将用户和组织锁定到平台。如google app engine
-
SaaS(软件即服务):在PaaS的基础上还提供了数据、应用
用于描述通过互联网部署的软件和供应商向订阅者许可应用程序作为"按需服务"。如社交服务FaceBook
-
他们之间的关系就像:
IaaS:提供厨房、炉子、煤气,你可以使用这些基础设施,来烤你的披萨。
PaaS:除了基础设施,还提供披萨饼皮。你只要把自己的配料洒在饼皮上,让他帮你烤出来就行了。也就是说,你要做的就是设计披萨的味道(海鲜披萨或者鸡肉披萨),他人提供平台服务,让你把自己的设计实现。
SaaS:他人直接做好了披萨,不用你的介入,到手的就是一个成品。你要做的就是把它卖出去,最多再包装一下,印上你自己的 Logo。
4 虚拟化的优势
简介:虚拟化 (Virtualization) 是资源的逻辑表示,其不受物理限制约束。
- 效率:将原本一台服务器的资源分配给了数台虚拟化的服务器,有效的利用了闲置资源,确保企业应用程序发挥出最高的可用性和性能。
- 隔离:虽然虚拟机可以共享一台计算机的物理资源,但它们彼此之间仍然是完全隔离的,就像它们是不同的物理计算机一样。因此,在可用性和安全性方面,虚拟环境中运行的应用程序之所以远优于在传统的非虚拟化系统中运行的应用程序,隔离就是一个重要的原因。
- 可靠:虚拟服务器是独立于硬件进行工作的,通过改进灾难恢复解决方案提高了业务连续性,当一台服务器出现故障时可在最短时间内恢复且不影响整个集群的运作,在整个数据中心实现高可用性。
- 成本: 降低了部署成本,只需要更少的服务器就可以实现需要更多服务器才能做到的事情,也间接降低了安全等其他方面的成本。
- 兼容:所有的虚拟服务器都与正常的x86系统相兼容,他改进了桌面管理的方式,可部署多套不同的系统,将因兼容性造成问题的可能性降至最低。
- 便于管理:提高了服务器/管理员比率,一个管理员可以轻松的管理比以前更多的服务器而不会造成更大的负担。
5 虚拟化的种类
- 处理器虚拟化
- 内存的虚拟化
- I/O 的虚拟化
- 网络虚拟化
5.1 处理器的虚拟化
- 敏感指令
- 系统资源:处理器的指令集和寄存器;I/O设备的状态和控制寄存器;
- 影响处理器设备状态和行为的寄存器称为关键资源或特权资源;
- 可以读写关键资源的指令叫做敏感指令(与CPU架构有关);
- 特权级别
- 现代计算机体系结构一般至少有两个特权级,用户态和核心态;
- 除X86外,敏感指令即特权指令,特权指令只能在最高级别(内核态)执行,否则会引发异常。
5.2 内存虚拟化
(略)
5.3 I/O 的虚拟化
(略)
5.4 网络虚拟化
(略)