软件工程知识点总结——第一、二部分

考试题型:选择题(20),名词解释(12),简答题(30),综合题(38)
注:以下资料来自各种渠道进行筛选整理的!!!

目录

福州大学软件工程2022年考后回忆

名词解释(喵的,我们这次要写英文全称,所以建议看看)

  1. RMMM
  2. 统一过程
  3. 依赖倒置
  4. 重构

简答题

  1. 说说你对顺序图和状态图的使用的看法?
  2. 面向对象测试,就是两个类继承自一个类,基类已经经过充分的测试,问两个子类要怎么测试?
  3. 主观材料题,第一问是从社会、法律、环境、安全等等方面分析项目的可行性,第二问是问你要做这个软件你打算采用什么团队结构,比如随机式组织、开放式组织、封闭式组织。
  4. 公司发现用户的需求不明确,所以在开始时故意报低价,在后面需求变更时再报高价,你觉得道德吗?

综合题

  1. 给一个商品表,问你要实现上面的话,类图要怎么设计。第二问,现在打算做618促销活动,要怎么修改上一题的类图,使它以后添加其他促销活动(比如双十二促销活动)时比较合理,然后新设计的类图满足哪些面向对象的原则。
  2. 挣值分析
  3. 给一段程序,画程序流图(注意不是程序结构图),写出独立路径,再写测试用例
  4. 给一段描述,画出用例图,画类图,再写第0层数据流图和第1层数据流图

第零部分 概述

软件工程知识点总结——第零部分

第一部分 软件过程

第3章 软件过程结构

软件过程定义:
  为创建高质量软件所需要完成的活动、动作和任务的框架。

软件过程与软件工程的区别:
  软件过程定义了软件工程化中采用的方法,但软件工程还包含该过程中应用的技术——技术方法和自动化工具。软件工程是由有创造力、有知识的人完成的,他们根据产品构建的需要和市场需求来选取成熟的软件过程。

3.1 通用过程模型

过程流类型:
线性过程流——从沟通到部署顺序执行五个框架活动
在这里插入图片描述
迭代过程流——在执行下一个活动前重复执行之前的一个或者多个活动
在这里插入图片描述
演化过程流——采用循环的方式执行各个活动,每次循环都能产生更为完善的软件版本
在这里插入图片描述
并行过程流——将一个或者多个活动与其他活动并行执行
在这里插入图片描述

3.4 过程模式

过程模式的定义:
  过程模式描述了软件工程工作中遇到的过程相关的问题,明确了问题环境并给出了针对该问题的一种或者几种可证明的解决方案。

Ambler过程模式模板:
模式名称:应清楚地表达该模式在软件过程中的含义,比如,技术评审。
驱动力(目的):模式使用环境及主要问题,以明确主要难点。
类型步骤模式(定义框架活动)、任务模式 (定义软件工程动作或任务)、阶段模式(定义框架活动序列){ ps:阶段模式是有序列的步骤模式的集合,步骤模式包括若干个任务模式 }
启动条件:模式应用前需满足的前提条件(输入) 。需要明确:
  (1)在此之前,整个开发组织或者开发团队内已有哪些活动?
  (2)已有哪些软件工程信息或是项目信息?
  (3)过程的进入状态是什么?
问题:描述模式将要解决的具体问题。
解决办法:描述如何成功实现模式。
结束条件:描述模式成功执行之后的结果(输出)。模式结束时需要明确:
  (1)必须完成哪些开发组织或是开发团队相关的活动?
  (2)过程的结束状态是什么?
  (3)产生了哪些软件工程信息或是项目信息?
相关模式:列举与该模式直接相关的其它过程模式。
已知应用实例:说明该模式可应用的具体实例。(什么场合使用)
具体示例:
回归测试过程模式
模式名称:回归测试 (指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误)。
目的:构造一种测试的过程。
类型:任务模式。
启动条件:在模式启动之前必须满足以下三个条件:(1)原来的测试用例;(2)更新后的软件;(3)针对更新部分的新测试用例。
问题:要测试模块。
解决方法:先用原来的测试用例测试软件,再用新测试用例测试软件。
结束条件:完成测试的软件。
相关模式:测试、单元测试、系统测试。
已知应用实例:更新软件后建议使用

第4章 过程模型

4.1 惯用过程模型

惯用过程模型的概念
目标:使软件开发更加有序。
  所有的软件过程模型都支持通用框架活动,但是每一个模型都对框架活动有不同的侧重。也称软件生存周期模型

4.1.1 瀑布模型

瀑布模型
定义
  将软件生存周期的各项活动规定为依固定顺序连接(瀑布般)的若干阶段工作:即从用户需求规格说明开始,顺序地通过沟通、策划、建模、构建和部署过程,最终提供完整的软件和持续的技术支持。又称为经典生命周期
前提
  需求必须是 准确定义相对稳定的
特点
  各个阶段间具有顺序性和依赖性;
  推迟实现的观点:前面步骤完成后才考虑实现;
  质量保证的观点:每一阶段都需要有文档以及经过评审;
问题
  瀑布模型需要明确的客户需求,但客户难以准确表达所有需求。
  得到可执行程序的时间太迟,滞后的缺陷导致陷入困境。
  可能导致一些阻塞,浪费过多等待时间。
  过于理想化,难以应对开发过程中的各种不确定因素。
变体
  V模型——瀑布模型与V模型没有本质区别,V模型提供了一种将验证确认动作应用于早期软件工程工作中的方法。
在这里插入图片描述

4.1.2 增量模型

增量模型
在这里插入图片描述

定义
  增量模型综合了线性过程流和并行过程流的特征:随着时间的推移,增量模型在每个阶段运用线性序列;每个线性序列以一种演化过程流的方式生产出软件的可交付增量。以迭代方式运用瀑布模式。
前提
  需求不明确迫切需要为用户迅速提供一套功能有限的软件产品,然后在后续版本中再进行细化和扩展功能。
特点
  运用增量模型时,第一个增量往往是核心产品(core product),能够满足基本的需求,但是许多附加的特性(一些是已知的,一些是未知的)没有提供。客户通过使用该核心产品进行详细评价,并根据评价结果制定下一个增量计划。这份增量计划说明了需要对核心产品进行的修改,以便更好地满足客户的要求,也说明了需要增加的特性和功能。
问题
  把用户需求转化为功能递增的不同版本可能比较难 (很多时候各个功能联系紧密,难以完全分开)
  难以确定所有版本共需的公用模块。(通常在进行设计时会先考虑设计公用模块,但是每一个增量只考虑局部的设计,因此,全局的公用模块很难确定)
变体
  迭代式开发——迭代式开发是增量式开发的一种变体,不同于传统的增量开发(每次提交一个构件),迭代式开发开始提交所有的模块(部分模块有待优化),在其后的阶段逐渐优化。

在这里插入图片描述

4.1.3 演化过程模型

演化过程模型
定义
  演化模型是迭代的过程模型,每次迭代产生软件的一个更完整的版本。
前提
  开发过程中,业务和产品需求经常变化
  严格的交付时间使得开发团队不可能圆满完成软件产品,但是必须交付功能有限的版本以及应对竞争或商业压力;
  往往很好地理解了核心产品需求,但是系统扩展的细节问题却没有定义。
问题
  首先,由于构建产品的迭代周期数目不确定,原型开发(和其他更加复杂的演化过程)给项目计划带来了困难。大多数的项目管理和估算技术是基于活动的线性布局,所以并不完全适用于演化软件过程。
  其次,演化模型没有确定演化的最快速度。如果演化的速度太快,完全没有间歇时间,项目肯定会陷入混乱;反之,如果演化速度太慢,则会影响生产率。
  再次,演化模型侧重灵活性和可延展性,而不是高质量。这种说法听起来很惊人。演化模型优先追求开发速度,而不是零缺陷

原型开发
在这里插入图片描述

定义
  原型开发模型开始于沟通。软件开发人员和利益相关者进行会晤,定义软件的整体目标,明确已知的需求,并大致勾画出以后再进一步定义的东西。
  迅速策划一个原型开发并进行建模(以快速设计的方式)。快速设计要集中在那些最终用户能够看到的方面,比如人机接口布局或者输出显示格式。
  快速设计产生了一个原型。
  对原型进行部署,然后由利益相关者进行评价。根据利益相关者的反馈信息,进一步细化软件的需求。
  在原型系统不断调整以满足各种利益相关者需求的过程中,采用迭代技术,同时也使开发者逐步清楚用户的需求。
前提
  客户:提出了一些基本功能,但未详细定义输入、处理和输出需求;
  开发人员:可能对开发运行环境、算法效率、操作系统的兼容性和人机交互等情况不确定。
问题
  1.利益相关者看到了软件的工作版本,却未察觉到整个软件是随意搭成的,也未察觉到为了尽快完成软件,开发者没有考虑整体软件质量和长期的可维护性。当开发者告诉客户整个系统需要重建以提高软件质量的时候,利益相关者会不愿意,并且要求对软件稍加修改使其变为一个可运行的产品。因此,软件开发管理往往陷入失效。
  2.作为一名软件工程师,软件开发人员为了使一个原型快速运行起来,往往在实现过程中采用折衷的手段。他们经常会使用不合适的操作系统或程序设计语言,仅仅因为当时可用和熟悉。他们也经常会采用一种低效的算法,仅为了证明系统的能力。时间长了,软件开发人员可能会适应这些选择,而忽略了这些选择其实并不合适的理由,结果造成并不完美的选择变成了系统的组成部分的情况。

螺旋模型
在这里插入图片描述

定义
  风险驱动的软件开发模型,采用循环的方式,逐步加深系统定义和实现的深度(原型开发的迭代性质);确定一系列里程碑,确保利益相关者都支持系统解决方案(瀑布模型的系统性和可控性);第一圈一般开发出产品的需求规格说明,接下来开发产品的原型系统,并在每次迭代中逐步完善,开发不同的软件版本;项目经理还会调整完成软件开发需要迭代的次数;
前提
  开发大型系统和软件;需要把控风险;


4.2 专用过程模型

  专用过程模型具有传统过程模型的一些特点,但是专用过程模型往往应用面较窄而专一,只适用某些特定的软件工程方法。

4.2.1 基于构件的开发

构件开发模型
概念
  本质上是演化模型,具有多螺旋模型的特点,利用迭代方式构件软件;与演化模型不同,基于构件开发模型采用预先打包的软件构件开发应用系统;
内容:
  建模和构建活动开始于识别可选构件。这些构件有些设计成通用的软件模块,有些设计成面向对象的类或软件包。不考虑构件的开发技术,基于构件开发模型由以下步骤组成(采用演化方法):
  1. 对于该问题领域研究和评估可用的基于构件的产品。
  2. 考虑构件集成的问题。
  3. 设计软件架构以容纳这些构件。
  4. 将构件集成到架构中。
  5. 进行充分的测试以保证功能正常。
优点
  能够使软件复用,减少项目开发费用,缩短开发周期

4.2.2 形式化方法模型

形式化方法模型
概念
  形式化方法模型的主要活动是生成计算机软件形式化的数学规格说明,使得软件开发人员可以应用严格的数学符号来说明、开发和验证系统。
优点
  应用数学分析的方法,歧义性问题、不完整问题、不一致问题等都能够更容易地发现和改正。在设计阶段,形式化方法是程序验证的基础,使软件开发人员能够发现和改正一些往往被忽略的问题。
缺点
  开发非常耗时,成本也很高;
  只有极少数程序员具有应用形式化的背景,需要大量的培训;
  对于技术水平不高的客户,很难用这种模型进行沟通。
应用
  高度关注安全性的软件(飞行器、医疗设施、经济领域)

4.3 统一过程

  由Booch、Jacobson及Rumbaugh提出,注重于客户沟通以及从用户的角度描述系统,强调软件体系结构的重要性
   统一过程认识到与客户沟通以及从用户的角度描述系统并保持该描述的一致性的重要性。
特点
  用例驱动,以架构为核心,迭代并且增量。

4.3.1 UML——统一建模语言

  UML包含了大量用于面向对象系统建模和开发的符号。到了1997年,UML已经变成了面向对象软件开发的实际标准。
  UML提供了支持面向对象软件工程实践必要的技术,但它没有提供指导项目团队使用该技术时的过程框架。接下来的几年中,Jacobson,Rumbaugh和Booch建立了统一过程模型,这是用UML进行面向对象软件工程的框架。目前,统一过程和UML广泛应用在各种各样的面向对象项目中。

4.3.2 统一过程的阶段

  统一过程(UP,Unified Process)有5个阶段,分别是起始阶段、细化阶段、构建阶段、转换阶段和生产阶段。有可能在构建、转换和生产阶段的同时,下一个软件增量的工作已经开始。这就意味着五个UP阶段并不是顺序进行,而是阶段性地并发进行

在这里插入图片描述

1.起始阶段(inception phase)
  包括客户沟通和策划活动。通过与利益相关者协作定义软件的业务需求,提出系统大致的架构,并制定开发计划以保证项目开发具有迭代和增量的特性。
  该阶段识别基本的业务需求,并初步用用例描述每一类用户所需要的主要特征和功能。此时的体系架构仅是主要子系统及其功能、特性的试探性概括。
  随后,体系结构将被细化和扩充成为一组模型,以描述系统的不同视图。策划识别各种资源,评估主要风险,制定进度计划,并为其在软件增量开发的各个阶段中的应用建立基础。

2.细化阶段(elaboration phase)
  包括沟通和通用过程模型的建模活动。细化阶段扩展了初始阶段定义的用例,并扩展了体系结构用以包括软件的五种视图——用例模型、需求模型、设计模型、实现模型和部署模型。
  在某些情况下,细化阶段建立了一个“可执行的体系结构基线”,这是建立可执行系统的“第一步”。
  体系结构基线证明了体系结构的可实现性,但没有提供系统使用所需的所有功能和特性。
  另外,在细化的最终阶段将评审项目计划以确保项目的范围、风险和交付日期的合理性。该阶段对项目计划进行修订。

3.构建阶段(construction phase)
  与通用软件过程中的构建活动相同。构建阶段采用体系结构模型作为输入,开发或是获取软件构件,使得最终用户能够操作用例。
  为达到上述目的,要对需求模型和设计模型加以完善,以反映出软件增量的最终版本。软件增量(例如发布的版本)所必须要求的特性和功能在源代码中实现。
  随着构件的实现,对每一个构件设计并实施单元测试。另外,还实施了其他集成活动(构件组装和集成测试)。
  用例被用来导出一组验收测试,以便在下个UP阶段开始前执行

4.转换阶段(transition phase)
  包括通用构建活动的后期阶段以及通用部署(交付和反馈)活动的第一部分
  软件被提交给最终用户进行Beta测试,用户反馈报告缺陷及必要的变更。
  另外,软件开发团队创建系统发布所必要的支持信息(如用户手册、问题解决指南及安装步骤)。
  在转换阶段结束时,软件增量成为可用的发布版本。

5.生产阶段(production phase)
  与通用过程的部署活动一致
  在该阶段,监控软件的持续使用,提供运行环境(基础设施)的支持,提交并评估缺陷报告和变更请求。

4.4 产品和过程

  如果过程很薄弱,则最终产品必将受到影响。但是对过程的过分依赖也是很危险的。所以产品(创造力、个性)和过程(按部就班,标准,流程)的二象性已经成为保留推动软件工程不断进步的创造性人才的一个重要因素

第4章 思考题

1.请描述三个适用于瀑布模型的软件项目。
答:
  图书馆管理系统、学生信息管理系统、销售系统。(ps:大部分只要需求明确且需求相对稳定的软件系统都可以使用瀑布模型)

2.请描述三个适用于原型模型的软件项目。
答:
  一个位于火车站的交互式火车车次查询系统、Android可视化编程软件、图像编辑软件。(ps:人机交互和/或复杂计算机图形软件应用程序一般适用于原型模型开发)

3.如果将原型变成一个可发布的系统或者产品,应该如何调整过程?
答:
  将原型变成一个可发布的系统或产品,软件工程师和客户需要满足和定义软件的总体目标,识别已知的任何要求,对整体轮廓进一步的强制定义。

4.请描述三个适用于增量模型的软件项目。
答:
  文字处理软件、五子棋游戏、IT技术交流社区。(ps:大部分软件都可以满足增量模型,尤其是游戏)

5.可以合用几种过程模型吗?如果可以,请举例说明。
答:
  过程模型可以合用,比如开发图像编辑软件,可以先采用原型开发,设计出大体的软件界面,后面在采用增量模型,一步一步添加相关功能。

6.开发质量”足够好“的软件,其优点和缺点是什么?也就是说 当我们追求开发速度胜过产品质量的时候,会产生什么后果?
答:
  开发质量“足够好”的软件可能会碰到死亡线(截止时间),但质量会是比较好的。当追求开发速度超过了产品的质量,这可能会导致许多缺陷,该软件可能需要更多的测试,设计和实施工作。需求定义的不是很清楚,可能需要不断地改变。甚至可能导致无法检测到重大的项目风险,造成不必要的事故。

7.请描述三个适用于基于构件模型的软件项目。
答:
  外卖APP、银行管理系统、微博。(ps:大部分功能可以划分为模块的软件都可以用基于构件的开发模式,尤其是包含实名认证和定位的软件)

8.我们可以证明一个软件构件甚至整个程序的正确性,可是为什么并不是每个人都这样做?
答:
  这是可能的用数学技术来证明软件组件,甚至整个程序的正确性。然而,对于复杂的程序,这是一个非常耗时的过程。

9.统一过程和UML是同一概念吗?解释你的答案。
答:
  不是,统一过程是软件工程开发的一种软件过程,而UML是一种建模语言,是一种表示方法。

第5章 敏捷开发

5.1 什么是敏捷

敏捷开发的定义:
  它是一种软件开发方法论,可以应对客户快速变更的需求。它强调以人为核心,采用迭代的方式,循序渐进地开发软件

5.2 敏捷及变更成本

  软件开发的传统方法中(有几十年的开发经验作支持),变更的成本费用随着计划的进展成非线性增长
  敏捷的拥护者认为,一个设计良好的敏捷过程“拉平”了变更成本曲线,使软件开发团队在没有超常规的时间和费用影响的情况下,在软件项目后期能够适应各种变化。
  敏捷过程包括增量交付。当增量交付与其他敏捷实践耦合时,例如连续单元测试及结对编程,引起变更的费用会衰减。
  虽然关于拉平曲线的程度的讨论仍然在进行,但是证据表明,敏捷变更费用显著降低。
在这里插入图片描述

5.3 什么是敏捷过程

敏捷过程的定义:
  基于敏捷原则进行的软件开发过程,视为敏捷过程。所谓“基于”,是指充分考虑,而不是全部包含。

敏捷过程的三大假设

  1. 提前预测需求或变化很难,预测优先级也存在困难;
  2. 理论上讲,是先有设计,后有构建。但实际上这两步是交替反复的,因为设计者是人,不是神;
  3. 从客观角度和软件开发的经验来讲,软件开发的几大要素(分析、设计、构建和测试)都要不断的调整、变化,而这正是敏捷的内涵。
5.3.1 敏捷原则

敏捷原则

  1. 我们最优先要做的是通过尽早、持续地交付有价值的软件来使客户满意。
  2. 即使在开发的后期,也欢迎需求变更。敏捷过程利用变更为客户创造竞争优势。
  3. 经常交付可运行软件,交付的间隔可以从几个星期到几个月,交付的时间间隔越短越好。
  4. 在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。
  5. 围绕有积极性的个人构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。
  6. 在团队内部,最富有效果和效率的信息传递方法是面对面交谈。
  7. 可运行软件是进度的首要度量标准。
  8. 敏捷过程提倡可持续的开发速度。责任人(sponsor)、开发者和用户应该能够保持一个长期的、恒定的开发速度 。
  9. 不断地关注优秀的技能和好的设计会增强敏捷能力。
  10. 简单是必要的。
  11. 最好的架构、需求和设计出自于自组织团队。
  12. 每隔一定时间,团队会反省如何才能更有效地工作,并相应调整自己的行为。

★并不是每一个敏捷模型都同等使用这12项原则,一些模型可以选择忽略(或至少淡化)一个或多个原则的重要性。

5.4 极限编程(XP)

  使用的最为广泛的敏捷过程。
三个特点

  1. 是一些相互关联的准则和惯例的集合;
  2. 追求变更曲线平坦化;
  3. 适合于小团队、高风险的项目
5.4.1 极限编程过程

极限编程过程
  XP使用面向对象方法作为推荐的开发范型,它包含了策划、设计、编码和测试4个框架活动的规则和实践。

策划:
  建立一系列描述待开发软件必要特征与功能的“故事” (故事:由客户谈论系统应该完成什么功能,然后用通俗的自然语言,使用自己的语汇,将其写在卡片上);
  评估每一个故事,并给出以开发周数为度量单位的成本;
  客户和XP团队共同决定如何对故事分组,并置于将要开发的下一个发行版本中(下一个软件增量);
  形成关于一个发布版本的基本承诺;
  对有待开发的故事进行排序:(1)所有选定故事 (下一个增量)将在几周之内尽快实现;(2)具有最高权值的故事将移到进度表的前面并首先实现;(3)高风险故事将首先实现。
  在第一个版本发布之后,XP团队计算项目的速度。项目速度由第一个发行版本中实现的客户故事个数来决定。
  项目速度将用于: (1) 帮助估计后续发行版本的发布日期和进度安排;(2) 确定是否对整个开发项目中的所有故事有过分承诺。一旦发生过分承诺,则调整软件发行版本的内容或者改变最终交付日期。
  在开发过程中,客户可以增加故事,改变故事的权值,分解或者去掉故事。然后由XP团队重新考虑并修改计划。

设计:
  严格遵循KIS (Keep It Simple)原则,即使用简单而不是复杂的表述。不鼓励额外功能性(因开发者假定以后会用到)设计。
  鼓励使用CRC卡(类-责任-协作者)确定与当前软件增量相关的面向对象的类
  在某个故事设计中遇到困难时,立即建立这部分设计的可执行原型,实现并评估设计原型 (Spike解决方案:让不明确的评估成为明确的评估),其目的是在真正的实现开始时降低风险,对可能存在设计问题的故事确认其最初的估计。
  鼓励“重构”。【重构:是以不改变代码外部行为而改进其内部结构的方式来修改软件系统的过程。实质上,重构就是在编码完成之后改进代码设计 (设计优化,代码优化)。重构所需工作量随着应用软件规模的增长而急剧增长。】

编码:
  XP推荐在故事开发和初步设计完成之后,团队不是直接开始编码,而是开发一系列用于检测本次(软件增量)发布的包括所有故事的单元测试。一旦编码完成,就可以立即完成单元测试,从而向开发者提供即时的反馈。(先开发测试用例,然后再编码)
  结对编程。XP建议两个人面对同一台计算机共同为一个故事开发代码。这一方案提供了实时解决问题 (两个人总比一个人强)和实时质量保证的机制 (在代码写出后及时得到复审),同时也使得开发者能集中精力于手头的问题。
  实施中不同成员担任的角色略有不同,例如,一名成员考虑设计特定部分的编码细节;而另一名成员确保编码遵循的标准。
  当结对的两人完成其工作,他们所开发的代码将与其他人的工作集成起来。有些情况下,团队(专人)进行集成。还有一些情况下,结对者自己负责集成,这种“连续集成”策略有助于避免兼容性和接口问题。

测试:
  建立的单元测试应当使用一个可以自动实施的框架(因此易于执行并可重复),这种方式支持代码修改之后即时的回归测试策略。
  将个人单元测试组织到一个“通用测试集”,与传统方式不同,每天都可以进行系统的集成和确认测试,可以为XP团队提供连续的进展指示,也可在一旦发生问题的时候及早提出预警。 “每几个小时修改一些小问题,比仅在最后截止期之前修正大问题要节省时间。”
  XP验收测试,也称为客户测试 (由客户主导),由客户规定技术条件,并且着眼于客户可见的、可评审的系统级的特征和功能。验收测试根据本次软件发布中所实现的用户故事而确定。

5.4.2 工业极限编程(IXP)

工业极限编程
  工业极限编程(IXP)是XP的一种有机进化。IXP合并了六个新实践:1. 准备评估;2. 项目社区;3. 项目特许;4. 测试驱动管理;5. 回顾;6. 持续学习;

准备评估
  在IXP项目开始执行前,组织机构应进行准备评估(readiness assessment)。评估应确定是否:

  1. 存在支持IXP的适合的开发环境
  2. 开发团队由合适的利益相关者组成;
  3. 组织机构具有清晰的质量大纲并且支持连续的改进;
  4. 组织文化会支持一个敏捷团队;
  5. 组成较为广泛的项目社区 (大项目,人多)

项目社区
  经典XP建议选择适合的人员组成敏捷团队可以确保成功。就是说团队成员必须经过良好的训练,具有良好的适应性和技能,以及适宜的性格为自组织团队做出贡献。
  当在一个大型组织内将IXP应用于重要的项目,团队的概念就变成社区。一个社区可能拥有一个技术专家,处于项目成功核心地位的客户们,以及其他利益相关者(例如,法律人员、质量检验员、生产或销售人员),“他们通常位于IXP计划的周边,但在项目中他们扮演着重要的角色”。
  在IXP内,应明确定义社区成员和他们的角色,应建立社区成员之间交流和合作机制

项目特许
  通过对项目本身进行评估来确定:(1) 对于项目的合适的商业调整是否存在;(2) 是否可以进一步深化组织机构的全部目标。

测试驱动管理
  需要可测量的标准来评估项目的状态和迄今为止的进展情况。

回顾
  IXP团队在一个软件增量交付之后要实施特定的技术评审。这种评审称为回顾,在软件增量过程中与全部软件的发布过程中复查“问题、事件以及教训”。这样做的目的是为了改善IXP过程。

持续学习
  由于学习是持续过程改进中至关重要的组成部分,因此,鼓励XP团队的成员去学习新的方法和技术来提高软件产品质量。

5.4.3 XP的批评意见

1.需求易变
  因为客户是XP团队的成员,对需求的改变不是正式地提出。结果是,项目的范围会发生变化,早期的工作或许要进行修改来适应当前的要求。

2.矛盾的客户需求
  许多项目都有众多客户,每个客户都有自己的一套需求。在XP中,团队自身需要吸纳不同客户的要求,这项工作可能超出了自己的职权范围。

3.需求的非正规表示
  批评者指出需要更正规的模型或规格说明来保证遗漏、不一致以及错误在系统建立前就被发现。
  拥护者则认为,需求的变化特性在其发展时使这些模型和规格说明变得过时。

4.正规设计的缺乏
  XP削弱了对体系结构的设计的要求,在许多案例建议所有类型的设计都不必那么正规。
  批评者主张当开发复杂的系统时,必须强调设计以保证软件的体系结构能够展示其质量和可维护性。
  拥护者指出XP过程的增量特性限制了复杂性(简单性是其核心价值),因此降低了扩展设计的必要性 (设计简单点,不考虑扩展性,用增量的方式来改进设计)。

5.5 其他敏捷过程模型

Scrum
  Scrum得名于橄榄球比赛。
  Scrum原则与敏捷宣言是一致的,应用Scrum原则指导过程中的开发活动,过程由“需求、分析、设计、演化和交付”等框架性活动组成。
  每一个框架活动中,发生于一个过程模式中的工作任务称为一个冲刺(sprint)。冲刺中进行的工作(每一个框架活动中的冲刺的数目根据产品复杂度和规模大小而有所不同)适应于当前的问题,由Scrum团队规定并常常作实时修改。
  每一个过程模式定义一系列开发活动:

  • 待定项(backlog)
      能为用户提供商业价值的项目需求或特征的优先级列表。待定项中可以随时加入新项(即变更的引入)。产品经理根据需要评估待定项并修改优先级。
  • 冲刺(sprint) (待定项的一部分,眼前具体的任务) 。
      由一些工作单元组成 ,并且必须能在预定的时间段 (time-box)内(一般情况下为30天)完成。冲刺过程中不允许有变更(例如,积压工作项)。因此,冲刺给开发团队成员的工作提供了短期但稳定的环境。
  • Scrum例会
      Scrum团队每天召开的短会(一般情况为15分钟),会上所有成员要回答三个问题:1.上次例会后做了什么?2.遇到了什么困难?3.下次例会前计划做些什么?
      团队领导(也称为Scrum主持人)主持会议并评价每个团队成员的表现。Scrum会议帮助团队尽早发现潜在的问题。同时,每日例会进一步促进自我组织团队的建设。

动态系统开发
  动态系统开发方法(Dynamic System Development Method,DSDM)提供一种框架,使其“通过在可控项目环境中使用增量原型开发模式来满足对时间有约束系统的构建和维护”。
  如果交付整个应用系统需用100%时间,那么80%的应用系统可以用20%的时间交付。
特点:
  每一个迭代都遵循80%原则,即每个增量只完成能够保证顺利进入下一增量的工作,剩余的细节则可以在知道更多业务需求或者提出并同意变更之后完成。
DSDM生命周期活动:

  • 可行性研究
      建立要开发应用系统的业务需求和相关约束,并评估该应用系统采用DSDM过程是否可行。
  • 业务研究
      建立能为应用系统提供业务价值所需要的功能和信息需求;同时,确定基本的应用系统架构并识别软件的可维护性需求。
  • 功能模型迭代
      为客户开发一系列证明其功能的增量原型 (注意:所有DSDM原型都倾向于逐渐发展成可交付的应用系统 )。迭代的意图是在用户使用原型系统时诱导出反馈信息以获取其他的需求。
  • 设计和构建迭代
      重新构建原型以确保每一个原型都以工程化方式实现,并能为最终用户提供可操作的业务价值。
  • 实现
      将最终软件增量(一个可操作的原型)置于操作环境中。应当注意:(1)增量不见得100%完成;(2)增量置于操作环境以后可能需要改变。

敏捷建模
敏捷建模的原则:

  • 有目的的模型
      在构建模型之前,开发者心中应当有明确的目标(如与客户沟通信息有助于更好地理解软件的某些方面),一旦确定模型的目标,该用哪种类型的表达方式以及所需要的具体细节程度都是显而易见的。
  • 使用多个模型
      描述软件可以使用多种不同的模型和表示法,大多数项目只用到其中很小的部分就够了。AM建议从需要的角度看,每一种模型应当表达系统的不同侧面,并且应使用能够为那些预期的读者提供有价值的模型。
  • 轻装上阵
      随着软件工程工作的进展,只保留那些能提供长期价值的模型,抛弃其余的模型。
      所以每次决定保留一个模型,都要在使用信息的便利性与敏捷性方面做权衡(即团队内部、团队与利益相关者增强沟通)。
  • 内容重于表述形式
      一个有用的内容很少,但语法完美的模型不如一个有缺陷但能向读者提供有用内容的模型更有价值。
  • 理解模型及工具
      理解每一个模型及其构建工具的优缺点。
  • 适应本地需要
      建模方法应该适应敏捷团队的需要。

敏捷统一过程(AUP)
  采用了一个“全局串行”以及“局部迭代”的原理来构建基于计算机的系统。
  采用经典UP阶跃性活动—开始、加工、构建以及变迁。
  提供一系列覆盖(例如,软件工程活动的一个线性序列),能够使团队为软件项目构想出一个全面的过程流。
  在每一个活动里,一个团队迭代使用敏捷,并且将有意义的软件增量尽可能快地交付给最终用户。
每个AUP迭代执行以下活动:

  • 建模
      UML建立了对商业和问题域的表述。然而,为了保持敏捷,应保证这些模型“足够好” 。
  • 实现
      将模型翻译成源代码。
  • 测试
      设计和执行一系列的测试来发现错误以保证源代码满足需求。
  • 部署
      重点是对软件增量的交付以及获取最终用户的反馈信息。
  • 配置及项目管理
      配置管理着眼于变更管理、风险管理以及对开发团队的任一常效产品的控制。项目管理追踪和控制开发团队的活动情况和工作进展。
  • 环境管理
      协调过程基础设施,包括标准、工具以及适用于开发团队的支持技术。

第5章 思考题

1.用自己的话描述(用于软件项目的)敏捷性。
答:
  敏捷不仅仅是有效地响应变更,它鼓励能够使沟通更便利地团队结构和协作态度。它强调可运行软件地快速交付,它认为项目计划是可以灵活调整地。

2.为什么迭代过程更容易管理变更?只用一次迭代就能完成项目的敏捷过程是否存在?解释你的答案。
答:
  敏捷过程模型提供软件增量,然后是客户反馈和修订。因为增量很小,客户反馈很及时,所以在下一个软件增量中合并更改相对容易。
  存在,例如,敏捷软件开发(ASD)使用一个迭代过程,该过程包括适应性周期规划、相对严格的需求收集方法,以及一个迭代开发周期,该周期包括以客户为中心的小组和正式的技术评审,作为实时反馈机制。

3.为什么需求变更这么大?人们终究无法确定他们想要什么吗?
答:
  需求变化如此之大,以至于很难提前预测哪些软件需求将持续存在,哪些将发生变化。随着项目的进行,同样难以预测客户的优先级将如何变化。
  人们通常很难描述他们的软件需求,直到他们看到一个工作的原型意识到他们忘记了考虑一些重要的事情。

5.什么是XP的spike解决方案?
答:
  在某个故事设计中遇到困难时,立即建立这部分设计的可执行原型,实现并评估设计原型。其目的是在真正的实施开始时降低风险,并验证包含设计问题的故事的原始估计。

6.用自己的话描述XP的重构和结对编程的概念。
答:
  重构是不改变代码外部行为而改进其内部结构的方式来修改软件系统的过程。
  结对编程两个人面对同一台计算机共同为一个故事开发代码。

第6章 软件工程的人员方面

6.1 软件工程师的特质

一个卓有成效的软件工程师要具备:

  1. 责任感。这会让软件工程师去努力实现对同伴、其他利益相关者和管理者的承诺。为获得成功的结果,他会在需要的时候不遗余力地做他需要做的事情。
  2. 对一些人的需求有敏锐的意识,这些人包括同团队的成员、利益相关者、掌控整个项目并能找到解决方法的管理者。他会观察人们工作的环境,并根据环境和人本身来调整自己的行为。
  3. 坦诚。如果发现了有缺陷的设计,他会用诚实且有建设性的方式指出错误。
  4. 展现抗压能力。前面我们提到,软件工程工作经常处在混乱的边缘。压力(以及由此产生的混乱)来自很多方面——需求和优先级的变更、要求苛刻的利益相关者或同伴、不切实际或者令人难以忍受的管理者。但一个卓有成效的软件工程师可以在不影响业绩的情况下很好地处理这些压力。
  5. 有高度的公平感。他会乐于与同事分享荣誉,努力避免利益冲突并且绝不破坏他人劳动成果。
  6. 注重细节。这并不意味着追求完美,而是说他会利用产品和项目已有的概括性标准(如性能、成本、质量),在日常工作基础上仔细思考,进而做出技术性决策。
  7. 务实。他知道软件工程不是要恪守教条的宗教信仰,而是可根据当下情景需要进行调整的科学规则。

6.3 软件团队

凝聚力:
  一个有凝聚力的团队是一组团结紧密的人,他们的整体力量大于个体力量的总和。
  同一般的团队相比,有凝聚力的团队成员具有更高的生产率和更大的动力。他们拥有统一的目标和共同的文化,而且在很多情况下,“精英意识”使得他们独一无二。

团队毒性
  应该避免“团队毒性”,5个培育潜在含毒团队的环境:

  1. 狂乱的工作氛围。解决方法:项目经理应该确保团队可以获取完成工作所需的所有信息;而且,主要目标一旦确定下来,除非绝对必要,否则不应该修改。
  2. 重大挫折使得团队成员产生摩擦。解决方法:给予软件团队尽可能多的决策权,增强团队信心。
  3. 糟糕的软件过程 (碎片式的或协调很差):解决方法:允许团队选择过程模型。
  4. 成员角色模糊:导致责任不明,互相指责。解决方法:团队应该建立责任机制,并规定一系列当团队成员未能完成任务时的纠正方法。
  5. 反复地失败:导致丧失自信,士气低下。解决方法:建立基于团队的信息反馈方法和解决问题的技术。

6.4 团队结构

  团队结构取决于组织的管理风格、团队里的人员数目与技能水平,以及问题的总体难易程度。
规划软件工程团队结构应该考虑的7个项目因素:

  1. 待解决问题的难度
  2. 开发程序的规模,以代码行或者功能点来度量;
  3. 团队成员需要共同工作的时间 (团队生存期);
  4. 能够对问题做模块化划分的程度
  5. 待开发系统的质量要求和可靠性要求
  6. 交付日期的严格程度
  7. 项目所需要的友好交流的程度

软件工程团队的四种组织模式:

  1. 封闭式模式。按照传统的权利层次来组织团队。当开发与过去已经做过的产品相似的软件时,这种团队十分有效。但在这种封闭式范型下难以进行创新性的工作。
  2. 随机式模式。松散地组织团队,团队工作依赖于团队成员个人的主动性。当需要创新或技术上的突破时,按照这种随机式范型组织的团队很有优势。但当需要“有次序地执行”才能完成工作时,这种团队就会陷入困境。
  3. 开放式模式。试图以一种既具有封闭式范型的控制性,又包含随机式范型的创新性的方式来组织团队。良好的沟通和根据团队整体意见做出决策是开放式范型的特征。开放式范型的团队结构特别适合于解决复杂的问题,但可能不像其他类型团队那么有效率。
  4. 同步式模式。 依赖于问题的自然划分,组织团队成员各自解决问题的一部分,他们之间没有什么主动的交流。

主程序员团队
  从历史的角度看,最早的软件团队组织是封闭式模式结构,最初称为主程序员团队。团队的核心成员包括

  • 1个高级工程师 (“主程序员”),负责计划、协调和评审团队的所有技术活动;
  • 技术人员 (一般是2-5人),进行分析和开发活动;
  • 1个后备工程师,支持高级工程师的活动,并可以在项目进行过程中以最小的代价接替高级工程师的工作。

优点

  • 实现了项目人员分工专业化;
  • 降低了管理的复杂性,提高了工作效率。

缺点

  • 现实社会中,缺乏同时具备高超管理才能和技术才能的“全才”。

随机式组织结构
  随机式范型主张建立具有独立创新性的团队,其工作方式可恰当地称为创新的无政府状态。为了建成一支绩效良好的团队:

  • 团队成员必须相互信任。
  • 团队成员的技能分布必须适合于要解决的问题。
  • 如果要保持团队的疑聚力,必须将坚持将个人己见的人员排除于团队之外。

特点

  • 成员之间关系平等;
  • 根据每个人的能力和经验适当分配任务;
  • 通过全体人员协商决定项目工作。

优点

  • 同等项目参与权,可以激发大家的创造力,利于攻克难关;
  • 适用于小规模、能力强、有共同工作经历的团队。

缺点

  • 缺少权威人士,在意见分歧的情况下很难解决。

6.5 敏捷团队

什么是敏捷团队?

  • 小型的充满活力的项目团队
  • 如果项目成员足够优秀,那么他们几乎可以采用任何一种过程来完成任务;如果项目成员不够优秀,那么没有任何一种过程可以弥补这个不足。“人员胜过过程”;
  • 然而,如果缺乏用户和主管人员的支持,也可以毁掉一个项目,即“政策胜过人员”。缺乏支持可以阻止最好的人员完成任务;
  • 成员相互信任,成员各有所长,优势互补
  • 为了保证凝聚力,将自行其事者清除出团队
  • 团队是“自组织的”:不必保持单一的团队结构,给予敏捷团队很大的自主权 (制定计划、手段选择)。

小组沟通的有效性:

  • 小组规模:随着规模的扩大,要保证所有成员间的有效交流变得困难;
  • 小组结构:没有正规组织结构的组织 (没有领导),沟通比较有效;
  • 小组构成:同类型的人易冲突;
  • 小组的物理工作环境:工作场所是推动或阻滞沟通的主要因素。

6.7 Alpha Test VS Beta Test

Alpha Test VS Beta Test

  • 测试场所不同
    • Alpha测试是指把用户请到开发方的场所来测试;
    • Beta测试是指在一个或多个用户的场所进行的测试测。
  • 环境的不同
    • Alpha测试的环境受开发方控制;
    • Beta测试环境不受开发方控制,开发商无法知道用户如何折磨软件。
  • 测试时间不同
    • Alpha测试时间比较集中,Beta测试时间不集中;
    • 一般情况下,Alpha测试比Beta测试先进行。

6.8 协作工具

协作工具(例如Git, SVN)
  20个世纪的软件开发环境(SDE)已变成协作开发环境(Collaborative Development Environments,CDE)。有价值的CDE会提供为协同工作特别设计的服务:

  • 命名空间:使项目团队可以用加强安全性和保密性的方式存储工作产品和其他信息,仅允许有权限的人访问。
  • 进度表:可以协调会议和其他项目事件。
  • 模板:可以使团队成员在创造工作产品时保持一致的外形和结构。
  • 度量支持:可以量化每个成员的贡献。
  • 交流分析:跟踪整个团队的交流并分离出模式,用于需要解决的问题或状况。
  • 工件收集:可以通过回答以下问题的方式组织工作产品和其他项目制品:“是什么导致了某个特定的变更?可以跟谁商讨有关变更?团队成员的个人工作是如何影响他人的工作的?

6.9 全球化团队

全球化软件开发(GSD)团队面临距离的挑战:

  • 距离使交流复杂化
  • 距离使得协调更困难
  • 距离产生了由文化差异导致的障碍和复杂性
  • 障碍和复杂性会减弱交流
    在这里插入图片描述

第6章 思考题

1.根据你对优秀软件开发者的观察,说出三个共同的个人特质。
答:
  有高度的责任感、有强大的抗压能力、注重细节。

2.怎样做到“毫无保留地诚实”,同时又不被其他人视为有侮辱意图或者攻击性?
答:
  使用商定的标准和书面要求作为向团队成员反馈的基础,有助于对工作产品的不足之处进行评论时减少个人感情色彩。

3.如果要选择敏捷团队区别于传统软件团队的一个属性,你会选哪个?
答:
  敏捷团队是自组织的,在项目生命周期的不同阶段可能会改变其组织结构

4.距离为什么会使交流复杂化?距离为什么会强调对协调的需求?距离会导致哪些种类的障碍和复杂性?
答:
  距离会使与团队成员的联系变得更加困难(例如,一天中可能有12小时或更长的时差)。生活在不同国家的团队成员有不同的经历、不同的文化期望,可能会使用不同的语言。
  协调工作对于项目的成功至关重要。
  有效的沟通需要发送、接收和响应消息,任何一个失败点都可能妨碍团队成员和利益相关者之间有效的信息交流。

第二部分 建模

第7章 理解需求

软件需求
  对期望的软件行为的表达,分为功能需求、非功能需求:

  • 功能需求—描述系统预期提供的功能或服务:
    • 系统应提供的服务
    • 系统如何对输入做出反应
    • 系统在特定条件下的行为
    • 系统不应该做什么
    • 数据
  • 非功能需求:不直接与系统具体功能相关的需求:
    • 产品需求:产品行为的需求,包括性能需求、可靠性需求和可用性需求等。
    • 机构需求:客户和开发者所在机构中的政策和规定要求,如过程标准、实现要求、交付需求。
    • 外部需求:所有的系统外部因素要求,如互操作需求、道德需求。

7.1 需求工程

需求工程的定义:
  需求工程是指致力于不断理解需求的大量任务和技术。从软件过程的角度来看,需求工程是一个软件工程动作,开始于沟通并持续到建模活动。

需求工程在设计构建之间建立起联系的桥梁:

  • 由软件团队检查将要进行的软件工作的内容;
  • 必须提交设计和构建的特定要求;
  • 完成指导工作顺序的优先级定义;
  • 会影响随后设计的信息、功能和行为。

两种需求过程:

  • 瀑布式需求
      项目早期完全确定需求
  • 进化式需求
      结合迭代开发,持续地寻找、记录、组织和跟踪不断变更的需求

需求工程过程主要通过执行七个不同的活动来实现:
   起始、获取、细化、协商、规格说明、确认和管理
(1)起始
  多数项目都是当确定了商业要求或是发现了潜在的新市场、新服务时才开始。
  业务领域的利益相关者(如业务管理人员、市场人员、产品管理人员)定义业务用例,确定市场的宽度和深度,进行粗略的可行性分析,并确定项目范围的工作说明。
  在项目起始阶段中,要建立基本的理解,包括对问题、谁需要解决方案、解决方案的性质、与项目利益相关者和开发人员之间达成初步交流合作的效果。

(2)获取
  询问客户、用户和其他人:

  • 系统或产品的目标是什么
  • 想要实现什么
  • 系统和产品如何满足业务的要求
  • 最终系统或产品如何用于日常工作

  这些问题看似简单,实际上并非如此简单—相反是非常困难的。
获取需求为什么困难?

  • 范围问题系统的边界不清楚,或是客户或用户的说明带有不必要的技术细节,这些细节可能会导致混淆而不是澄清系统的整体目标。
  • 理解问题客户或用户并不能完全确定需要什么,他们对其计算环境的能力和限制所知甚少,对问题域没有完整的认识,与系统工程师在沟通上存在问题。
  • 易变问题实际需求随时间变化

(3)细化
  在起始和获取阶段获得的信息将在细化阶段进行扩展和提炼
  该任务集中于开发一个精确的需求模型,用以说明软件的功能、特征和信息的各个方面。

(4)协商
存在问题:

  • 只给定有限的业务资源,而客户和用户提出了过高的要求
  • 不同的客户或用户提出了相互冲突的需求,并坚持“我们的特殊要求是至关重要的”。

  需求工程师必须通过协商过程来调解这些冲突。应该让客户、用户和其他利益相关者对各自的需求排序,然后按优先级讨论冲突。
  使用迭代的方法给需求排序,评估每项需求对项目产生的成本和风险,表述内部冲突,删除、组合和(或)修改需求,以便参与各方均能达到一定的满意度。

(5)规格说明
  在基于计算机的系统(和软件)的环境下,术语规格说明对不同的人有不同的含义。一个规格说明可以是一份写好的文档、一套图形化的模型、一个形式化的数学模型、一组使用场景、一个原型或上述各项的任意组合。
   在开发规格说明时保持灵活性有时是必要的:对大型系统而言,文档最好采用自然语言描述和图形化模型来编写。 而对于技术环节明确的较小产品或系统,使用场景可能就足够了。
两种需求文档:

  • 需求定义客户要求的完整列表 (对外)
      通常由客户和需求分析师一起编写,是开发人员对系统功能的一个合同,主要给客户阅读;
  • 需求规格说明要构建系统的规格化说明 (对内)
      由需求分析师编写,并由其他软件开发人员使用。

(6)确认
  这一步将对需求工程的工作产品进行质量评估。
  正式的技术评审是最主要的需求确认机制。确认需求的评审小组包括软件工程师、客户、用户和其他利益相关者,他们检查系统规格说明,寻找:

  • 内容或解释上的差错
  • 可能需要进一步澄清的地方
  • 丢失的信息
  • 不一致 (开发大型系统时的主要问题)
  • 冲突或不现实的需求

(7)需求管理
  计算机的系统的需求会变更,而且变更的需求贯穿于系统的整个生存期。需求管理是用于帮助项目组在项目进展中标识、控制和跟踪需求以及需求变更的一组活动。

7.2 建立根基

7.2.1 确认利益相关者

利益相关者的定义
  直接或间接地从正在开发的系统中获益的人。包括:业务运行管理人员、产品管理人员、市场销售人员、内部和外部客户、最终用户、顾问、产品工程师、软件工程师、支持和维护工程师以及其他人员。
  每个利益相关者对系统都有不同的考虑,当系统成功开发后所获得的利益不相同,当系统开发失败时所面临的风险也是不同的。

7.2.2 识别多重观点

  因为存在很多不同的利益相关者,所以系统需求调研也将从很多不同的视角开展。例如:

  • 市场销售部门关心能激发潜在市场的,有助于产品更容易销售的功能和特点;
  • 业务经理关注应该在预算内实现功能,并且这些功能应该满足已规定的市场限制。
  • 最终用户希望系统的功能是他们所熟悉的并且易于学习和使用。
  • 软件工程师可能关注每个需求是否容易实现。
  • 支持工程师关注软件的可维护性。

  当从多个角度收集信息时,所形成的需求可能存在不一致性或是相互矛盾

7.2.3 协同合作

  需求工程师的工作是标识公共区域 (即所有利益相关者都同意的需求)和矛盾区域或不一致区域 (即某个利益相关者提出的需求和其他利益相关者的需求相矛盾)。
  在很多情况下,一个强有力的“项目领导者”(例如业务经理或高级技术员)可能要对删减哪些需求做出最终决策。

7.3 获取需求

7.3.1 协作收集需求

协作收集需求的基本原则:

  • 会议由软件工程师和其他的利益相关者共同举办和参与。
  • 制定筹备和参与会议的规则。
  • 建议拟定一个会议议程,这个议程既要足够正式,使其涵盖所有的重点,但也不能太正式,以鼓励思想的自由交流。
  • 由一“调解人”(可以是客户、开发人员或其他人)控制会议。
  • 采用“方案论证手段”(可以是工作表、活动挂图、不干胶贴纸或电子公告牌、聊天室或虚拟论坛)。
7.3.2 质量功能部署

质量功能部署 (Quality Function Deployment, QFD)
  是一种将客户要求转化成软件技术需求的质量管理技术

QFD目的
  是最大限度地让客户从软件工程过程中感到满意。为了达到这个目标,QFD强调理解“什么是对客户有价值的”,然后在整个工程活动中部署这些价值。QFD确认了三类需求:

  • 正常需求:这些需求反映了在和客户开会时确定的针对某产品或系统的目标。如果实现了这些需求,将满足客户。如:特定的系统功能以及已定义的性能级别。
  • 期望需求:这些需求隐含在产品或系统中,并且可能是非常基础的以至于客户没有显式地说明,但是缺少这些将导致客户非常不满。例如:人机交互的易用性、整体的运行正确性和可靠性以及软件安装的简易性。
  • 令人兴奋的需求:这些需求反映了客户期望之外的特点,但是如果实现这些特点的话将会使客户非常满意。例如多重触控技术的触摸屏,可视语音邮箱

7.4 开发用例

出卷系统案例

问题描述

  • 系统支持自动出卷和人工辅助出卷:
    • 自动出卷:根据教师出卷要求,抽取题目,自动得到一份试卷;
    • 人工辅助出卷:根据教师出卷要求,抽取符合要求的题目,供教师选择。
  • 出卷要求包括总分,总难度及其比例,总题型及其比例,总知识点及其比例。
  • 系统能进行题库管理:包括试题录入、修改、删除等;
  • 至少有1000道不同类型的试题;
  • 能容纳足够多的试题;
  • 试题含有内容、答案、题型、难度、知识点和加入时间等信息。
  • 系统能支持不同科目;
  • 系统有一个好的图形界面;
  • 试题不允许重复出现;
  • 试卷符合要求的96%以上即可结束,允许教师调整。
  • 能进行试卷分析。

功能分析

  • 用户:教师、学生、题库维护人员。
  • 用户的各自问题:
    • 教师:出一份合理的试卷,并能根据样式打印与输出;
    • 学生:通过生成一些模拟试题,进行在线学习和检查学习结果;
    • 题库维护人员:添加、更新、删除试题。
  • 精化后的问题:
    • 教师:自动出卷、手动出卷、试卷编辑、试卷输出;
    • 学生:随机抽卷、在线练习、在线评价;
    • 题库维护人员:试题管理。
  • 系统的功能需求:
    • 自动出卷:根据教师要求自动生成一份合理的试卷;
    • 手动出卷:教师手动从候选试题中挑选题目;
    • 试卷编辑:更新试题;
    • 试卷输出:根据某个样式输出试卷。
    • 随机抽卷:随机抽取试题,生成一份试卷;
    • 在线练习:学生可以在线做练习和查看答案;
    • 在线评价:根据测试结果,评价学生的表现;
    • 试题管理:管理人员维护题库中的试题;

出卷系统用例图
在这里插入图片描述

短信系统案例

问题描述

  • 基本目的:利用快捷的短信业务,发送即时消息以支持企事业单位进行信息通知、通告等各种服务,以及用短信进行客户服务。
  • 短信发送:客户选择若干个目标人员,编辑内容,立即或定时发送通知信息。
  • 短信人工应答:用户查看收到的短信内容,并可回复。
  • 短信自动应答:根据短信询问内容,并依据规则自动回复询问者。
  • 短信接收:接收外部短信。
  • 短信确认:确认接收方是否接收。
  • 客户资料维护:添加、删除和更新用户。
  • 接口要求:支持移动终端通过串口通信,支持与移动网关通信。

功能分析

  • 用户:收发人员、管理人员
  • 用户的各自问题:
    • 收发人员:负责发送短信给用户或接受用户短信;
    • 管理人员:添加、更新、删除用户。
  • 功能需求:
    • 短信发送:填写发送内容、选择发送用户、指明是否要回执、然后(通过无线终端或短信网关)发送短信;
    • 短信接收:从无线终端或短信网关读取短信内容,并查看;
    • 用户管理:添加用户、更新用户、删除用户。

短信系统用例图
在这里插入图片描述

SafeHome用例模板

用例:初始化监控
主要参与者:房主
目标:设置系统在房主离开住宅或留在房间内时监测传感器
前提条件:系统已经输入密码并识别各种传感器
触发器:房主决定“设置”系统,即打开警报功能
场景

  1. 观察控制面板
  2. 输入密码
  3. 选择“stay”或“away”
  4. 观察红色报警灯显示SafeHome已经被打开异常:
  5. 控制面板没有准备就绪:检查所有的传感器,确定哪些是开着的,并将其关闭
  6. 密码不正确:重新输入正确的密码
  7. 密码不识别:必须对监测和相应子系统重新设置密码
  8. 选择stay: 控制面板鸣叫两声并且Stay灯亮;激活边界传感器
  9. 选择away:控制面板鸣叫三声并且away灯亮;激活所有传感器

优先级:必须实现
何时可用:第一个增量
使用频率:每天多次
使用方式:通过控制面板接口
次要参与者:技术支持人员,传感器
次要参与者使用方式

  1. 技术支持人员:电话线
  2. 传感器:有线或无线接口

未解决的问题

  1. 是否还应该有不使用密码或使用缩略密码激活系统的方式?
  2. 控制面板是否还应显示附加的文字信息?
  3. 房主输入密码时,从按下第一个按键开始必须在多长时间内输入密码?
  4. 在真正激活系统之前有没有办法关闭系统?

7.5 构建分析模型

7.5.1 分析模型的元素

基于场景的元素:活动图
  可以从用户的视角描述系统。例如,基本的用例及其相应的用例图可以演化成更精细的基于模板的用例。基于场景的元素通常是正在开发模型的第一部分。同样,它们也作为创建其他建模元素时的输入。

基于类的元素:类图
  每个使用场景都暗示着当一个参与者和系统交互时所操作的一组对象。这些对象被分成类—具有相似属性和共同行为的事务集合。

行为元素:状态图
  状态图是一种表现系统行为的方法,该方法描绘:系统状态、导致系统改变状态的事件、某个特殊事件后采取什么动作

面向数据流的元素:数据流图
  信息在基于计算机的系统中流动时会被转换,系统接受多种形式的输入,使用函数将其转换生成多种形式的输出。
  输入可以是由变频器发送的控制信号,可以是操作人员输入的数字,也可以是网络上传送的信息包或从备份存储器取回的庞大数据文件。
  转换可能由单一的逻辑比较、复杂的数值算法或专家系统的规则推理方法构成。
  输出可能是点亮一个发光二极管或是生成一份200页的报告。

7.6 避免常见错误

作为软件团队实施需求工程时必须避免的三个相关错误:

  • 特性偏好:是指以功能覆盖率来表征整体系统质量的做法。一种软件开发者倾向快速实施简易功能,而不考虑它们的质量。事实上软件项目失败的最常见原因之一是缺少可实用的质量——而不是丢失功能。为了避免落入这个陷阱,你应与其他利益相关者讨论系统必需的关键功能,确保每项已交付的功能都具备了所有必要的质量特性。
  • 灵活性偏好:发生在软件工程师过分重视产品的自适应性和配置便利性时。过分灵活的系统会很难配置,且可操作性差,这是系统范围定义混乱的征兆。结果是“灵活”系统产生了不必要的复杂性,越难测试就会有越多的管理挑战。
  • 性能偏好:指软件开发者过分关注质量特性方面的系统性能开销,如可维护性、可靠性和安全性。系统性能特性应该部分取决于非功能软件需求的评估。性能应该与产品的商业需求一致,同时必须与其他系统特性相兼容。

第7章 思考题

1.为什么大量的软件开发人员没有足够重视需求工程?
答:
  首先软件开发人员认为客户已经把需求说清楚了,但是大多数情况初步的需求都是模糊的。其次工程的进度要求很紧迫,软件开发人员迫切希望投入到代码编写阶段。最后和客户沟通比较困难,使得大多数软件开发人员不重视需求工程。

2.讨论一下当需求必须从三四个不同的客户中提取时会发生什么问题。
答:
  每个人的需求会不一致甚至产生冲突。

3.想出3个以上在需求起始阶段可能要问利益相关者的“与环境无关的问题”。
答:
  ①谁是这项工作的最初请求者?②谁将使用该解决方案?③成功的解决方案将带来什么样的经济收益?

4.为如下活动之一开发一个完整的用例:a. 在ATM提款。b. 在餐厅使用信用卡付费。c. 使用一个在线经纪人账户购买股票。 d. 使用在线书店搜索书(某个指定主题)。
答:
在这里插入图片描述

5.在需求工程活动的协商情境中,“双赢”意味着什么?
答:
  利益相关者的“赢”:获得满足客户大多数需要的系统或产品;软件团队的“赢”:按照实际情况、在可实现的预算和时间内完成工作。

第8章 需求建模:基于场景的方法

8.1 需求分析

8.1.1 总体目标和原理

需求模型的三个主要目标:

  1. 描述客户需要什么,分析正确性;
  2. 为软件设计奠定基础;
  3. 定义在软件完成后可以被确认的一组需求。
8.1.2 分析的经验原则

在创建分析模型时应该遵循的经验原则:

  1. 模型应关注在问题或业务域内可见的需求,抽象的级别应该相对高一些。“不要陷入细节”,即不要试图解释系统将如何工作。
  2. 需求模型的每个元素都应能增加对软件需求的整体理解,并提供对信息域、功能和系统行为的深入理解。(存在即有用)
  3. 基础结构和其他非功能的模型应推延到设计阶段再考虑
  4. 最小化整个系统内的关联。类和功能之间的联系非常重要,但是,如果“互联”的层次非常高,应该想办法减少互联。
  5. 确认需求模型为所有利益相关者都带来价值。对模型来说,每个客户都有自己的使用目的。例如利益相关的业务人员将使用模型确认需求,设计人员将使用模型作为设计的基础;质量保证人员将使用模型帮助规划验收测试。
  6. 尽可能保持模型简洁。如果没有提供新的信息,不要添加附加图表;如果一个简单列表就够用,就不要使用复杂的表示方法。
8.1.3 域分析

目标查找或创建那些广泛应用的分析类或分析模式,使其能够复用
域分析师的角色发现和定义可复用的分析模式、分析类和相关的信息
在这里插入图片描述

8.1.4 需求建模的方法

四类需求建模方法:

  1. 基于场景的模型:表述用户如何与系统和使用软件时出现的特定活动序列进行交互。
  2. 基于类的模型:描述了系统操作的对象、对象间关系(某层级),以及定义的类间发生的协作。
  3. 行为模型:描述外部事件如何改变系统或驻留在系统里的状态。
  4. 面向流的模型:表示信息转换的系统,描述了数据对象在流过各种系统功能时是如何转换的。(输入 - 处理 - 输出)

8.2 基于场景建模

  在需求提出之初,往往是模糊的。设计者可以根据这些需求编写一个具体的例子——用例或场景。

8.2.1 创建初始用例

用例的定义
  用例只是帮助定义系统之外存在什么以及系统应完成什么。也就是,用例是从某个特定参与者的角度出发,采用简明的语言描述一个特定的使用场景。

描述性用例
  描述性用例的另一种表达形式是通过用户活动的顺序序列来表现交互,每个行动由声明性的语句表示。值得注意的是,这个连续步骤的陈述没有考虑其他可能的交互 (暂时不考虑细化问题)。这种类型的用例有时被称作主场景

8.2.2 细化初始用例

主场景中的每个步骤将通过如下提问得到评估:

  1. 在这一状态点,参与者能进行一些其他动作吗?
  2. 在这一状态点,参与者有没有可能遇到一些错误的条件?如果有可能,这些错误会是什么?
  3. 在这一状态点,参与者有没有可能遇到一些其他的行为(如由一些参与者控制之外的事件调用)?如果有,这些行为是什么?

  这些问题的答案导致创建一组次场景,次场景属于原始用例的一部分但是表现了可供选择的行为

8.3 补充用例的UML模型

8.3.1 开发活动图

示例
在这里插入图片描述

8.3.2 泳道图

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

补充

数据建模概念:
  定义在系统内处理的所有数据对象数据对象之间的关系以及其它与这些关系相关的信息

E-R图
在这里插入图片描述

第9章 需求建模:基于类的方法

9.4 类-职责-协作者建模

  类-职责-协作者CRC (Class-Responsibility-Collaborator)建模:提供了一个简单方法,用于识别和组织与系统或产品需求相关的类。
CRC模型是表示类的标准索引卡片的集合,分成三部分:

  • 顶部:写类名
  • 主体左侧:列出类的职责
    职责:和类相关的属性和操作,即“类所知道或能做的任何事”
  • 主体右侧:列出类的协作者
    协作者:完成某个职责需要的其它类,即信息请求或动作请求

示例:
在这里插入图片描述
类:
类的分类可通过如下三种分类方式进行扩展:

  • 实体类:也称模型或业务类,是从问题说明中直接提取出来的。例如,FloorPlan和Sensor;
  • 边界类:用于创建用户可见的和在使用软件时交互的接口(如交互屏幕或打印的报表)。例如,一个称做Camera Window的边界类负责显示SafeHome系统监视摄像机的输出;
  • 控制类:用于管理“工作单元”。控制类可以管理:(1) 实体类的创建或更新;(2) 边界类获取信息后的实例化。(3) 对象集合间的复杂通信。(4) 对象间或用户和应用系统间交换数据的确认。

职责:
分配职责的5个指导原则

  1. 智能系统应分布在所有类中以求最佳地满足问题的需求
      把“不灵巧”类(几乎没有职责的类)作为一些“灵巧”类(有很多职责的类)的从属。每个对象只了解和执行一些事情 (通常是适度集中),并提高系统的内聚性,这将提高软件的可维护性并减少变更的副作用影响。应该评估每个CRC模型索引卡上标记的职责,以确定某个类是否应该具有超长的职责列表,如果有这种情况就表明职责太集中,需要将一个类分成多个类或子系统。 此外,每个类的职责应表现在同一抽象层上;
  2. 每个职责的说明应尽可能具有普遍性
      在类的层级结构的上层保持职责 (属性和操作)的通用性,(因为它们更有一般性,将适用于所有的子类)。
  3. 信息和与之相关的行为应放在同一个类中
      这实现了面向对象原则中的封装,数据和操作数据的处理应包装在一个内聚单元中。
  4. 某个事物的信息应局限于一个类中而不要分布在多个类中
      通常应由一个单独的类负责保存和操作某特定类型的信息。通常这个职责不应由多个类分担。如果信息是分布的,软件将变得更加难以维护,测试也会面临更多挑战。
  5. 职责应由相关类共享
      很多情况下,各种相关对象必须在同一时间展示同样的行为;例如,一个视频游戏,必须显示如下类:Player, PlayerBody, PlayerArms, PlayerLegs, PlayerHead。每个类都有各自的属性(例如,position, orientation, color, speed),并且所有这些属性都需要在用户操作游戏时进行更新和显示。因此,每个对象必须共享职责update()和display()。

协作
类有两种方法实现其职责:

  1. 类可以使用其自身的操作控制各自的属性,从而实现特定的职责;(可自主完成)
  2. 类可以和其他类协作

类间的三种通用关系

  1. is-part-of (是……的一部分)【组合】{实心菱形}、has-a (有…)【聚合】{空心菱形}
    在这里插入图片描述
      组合是一种较为紧密的关系,从生命周期上看,部分和整体是共存亡的关系。聚合则是一种较为松散的关系,部分和整体的生命周期未必一致。

  2. has-knowledge-of (有关于……的知识)
      当一个类需要从另一个类中获取信息时;例如,ControlPanel必须从Sensor类中获取每个传感器的状态;

  3. depends-upon (依赖……)
      意味着两个类之间具有is-part-of和has-knowledge-of 不能实现的依赖关系:例如,PlayerHeader通常必须连接到PlayerBody;

9.5 关联和依赖

关联
  两个分析类以某种方式相互联系着,这些联系被称作关联(associations)。在某些情况下,关联可以更进一步地指出多样性。多样性限制的表示有以下几种情况:

  • 1…* 表示一个或多个
  • 0…* 表示0或多个
  • * 表示范围无上界
    在这里插入图片描述

依赖
  一个Camera对象向一个DisplayWindow对象提供视频图像。这两个对象间的关系不是简单的关联,而是存在着依赖关系。建模者必须提供特定的密码才能查看指定摄像机的位置。《access》意味着通过特定的密码控制使用摄像机的输出。
在这里插入图片描述

9.6 分析包

分析包的定义
  将分析模型的各种元素(如用例、分析类)以一种方式分类,分组打包后称其为分析包,并取一个有代表性的名。

每个包中分析类名字前加的符号有三种:

  • + 公共可见,可以从其他包访问
  • – 该元素对其他包是隐藏的
  • # 只能由指定包中的类访问

第9.5章 需求建模:流

面向流建模
  描述了数据对象在系统中的变换过程。采用数据流图(data flow diagram,DFD)、状态迁移图等。
  DFD采取了系统的输入-处理-输出观点,即流入软件的数据对象,经由处理元素变换,最后结果以数据对象的形式流出软件。

数据流图(记号)
在这里插入图片描述
示例:
在这里插入图片描述
导出数据流图的指导原则:
(1) 第0层DFD(也称环境层DFD或顶层DFD)将系统描述成一个泡泡;
(2) 仔细标记主要的输入和输出;
(3) 通过把选定的处理、数据对象和数据存储分离为下一层表示而开始精化过程,即逐步求精,一次精化一个处理;
(4) 使用有意义的名称,标记所有的箭头和泡泡;
(5) 从一层转至另一层时,注意保持信息流的连续性;
(6) 一次精化一个泡泡。

示例:【示例来源:如何画好数据流图?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(ps:有些教材把顶层图表示为0层,依次类推,这里的0层就表示为1层,1层表示为2层)

判定表
  一个表格,描述条件和条件导致的动作的集合。

示例:
在这里插入图片描述

数据字典
  管理各种关系模型中的信息,具体信息包括:

  • 一般信息:名字、别名、描述等;
  • 定义信息:数据类型、长度、结构;
  • 使用特点:值的范围、使用频率、使用方式;
  • 控制信息:来源、使用它的程序;
  • 分组信息:父结构、从属结构、物理位置等;

数据元素组成数据对象的方式:

  • 顺序:两个或多个分量以确定次序进行连接;
  • 选择:从两个或多个可能的元素中选取一个;
  • 重复:把指定的分量重复零次或多次。

符号:

  • = 等价于
  • + 和
  • [ ] 或 (选择一个,用 | 隔开分量)。例如:字母或数字 = [字母字符 | 数字字符]
  • { } 重复 ,(左右的数字分别为重复次数的上、下界)。例如:字母数字串 = 0{字母或数字}7 (可重复0-7次)
  • ( ) 可选 (即从括号从中任选一项,也可一项都不选)

示例:
在这里插入图片描述
在这里插入图片描述

第10章 需求建模:行为和模式

10.1 生成行为模型

行为模型
  描述了系统如何响应外部事件或激励

10.3 状态表达

类的状态有被动主动两种特征

  • 被动状态——某个对象所有属性的当前状态:
      前后状态对被动状态影响不大。比如,位置与方向信息等;
  • 主动状态——对象进行持续变换和处理时的当前状态:
      必然存在前后不同状态。比如,移动、休息、受伤、疗伤、被捕、失踪等;
      必然发生事件(有时被称为触发器)才能迫使对象做出从一个主动状态到另一个主动状态的转移。

状态图:
  为每个类呈现了主动状态和导致这些主动状态变化的事件
示例:
在这里插入图片描述
顺序图
   顺序图将交互关系表示为一个二维图,用时间函数表明事件如何引发从一个对象到另一个对象的转移。

  • 箭头:代表一个事件;
  • 时间纵向向下度量,消息从左到右排列;
  • 纵向矩形:表示处理某个活动所用的时间。

示例:
在这里插入图片描述

10.4 需求建模的模式

10.4.1 发现分析模式

需求模型由各种元素组成:
  基于场景(用例)、基于数据(数据模型)、基于类、基于流和行为。其中,每个元素都是从不同的视角检查问题,并且每一个都提供一种发现模式的机会,可能发生在整个应用领域,或者发生在类似但横跨不同的应用领域。
  在需求模型的描述中最基本的元素是用例。一套连贯用例可以成为服务于发现一个或多个分析模式的基础。

思考题

1.表示行为建模时有两种不同的“状态”类型,他们是什么?
答:
  状态图、顺序图

2.如何区分状态图和顺序图?
答:
  状态图描述一个对象状态的变迁,而顺序图描述几个对象之间交互的顺序。

3.配置模型的目的是什么?
答:
  将具有不同来源的配置转换成Configuration对象。

第11章 设计概念

11.1 软件工程中的设计

软件的设计
  软件的设计是将需求转变为软件陈述(表达)的过程。系统通过逐步求精,使得设计陈述逐渐接近源代码:

  • 第一步是初步设计(Preliminary design),关注于怎么将需求转换成数据和软件框架。
  • 第二步是详细设计(Detail design),关注于将框架逐步精细化为具体的数据结构和软件的算法表达。设计行为、数据、算法和程序设计都需要由现代程序所需的界面设计这一清晰的行为来结合起来。

需求模型提供了创建四种设计模型所需信息:

  1. 数据/类设计:将类模型转化为设计类以及目标软件的结构;
  2. 体系结构设计:定义了软件的主要构造元素间的联系;
  3. 接口设计:描述了软件和协作系统之间、软件和使用人员之间的通信;
  4. 构件级设计:将软件体系结构的构造元素变换为对软件构件的过程性描述。

11.2 设计过程

11.2.1 软件质量指导原则和属性

良好设计演化的三个特征:

  1. 满足用户需求
    必须实现需求模型中所有的显式需求;
    必须满足用户希望的所有隐式需求;
  2. 可读、可理解
    设计必须是可读、可理解的,使得将来易于编程、易于测试、易于维护;
  3. 全面性
    应从实现角度出发,给出与数据、功能、行为相关的软件全貌

质量指导原则
  为了评估某个设计表示的质量,软件团队中的成员必须建立良好设计的技术标准,这些将作为软件质量的标准:

  1. 设计应展示出这样一种结构
    (a) 使用可识别的体系结构风格或模式创建;
    (b) 由展示出良好设计特征的构件构成;
    (c) 能够以演化的方式实现,便于实现和测试。
  2. 模块化
    将软件逻辑地划分为元素或子系统;
  3. 设计应该包含体系结构、接口和构件的清晰表示
  4. 导出合适的数据结构
    数据结构适用于要实现的类,并从可识别的数据模式提取。
  5. 设计应导出显示独立功能特征的构件
  6. 设计应导出接口
    这些接口降低了构件之间以及与外部环境连接的复杂性。
  7. 设计方法应该是由需求信息驱动
  8. 采用有效的表示法
    使用能够有效传达意义的表示法来表达设计。

质量属性
  软件质量属性(FURPS)体现了所有软件设计的目标:

  • 功能性 (Functionality) :通过评估程序的特征集和能力、所提交功能的通用性以及整个系统的安全性来评估。
  • 易用性 (Usability):通过考虑人员因素、整体美感 、一致性和文档评估。
  • 可靠性 (Reliability):通过测量故障的频率和严重性、输出结果的精确性、平均故障时间(Mean-Time-To-Failure, MTTF) 、故障恢复能力和程序的可预见性来评估。
  • 性能 (Performance):通过考虑处理速度、响应时间、资源消耗、吞吐量和效率来度量。
  • 可支持性 (Supportability):包括可维护性(可扩展性、适应性和耐用性),可测试性、兼容性、可配置性、系统安装的简易性和问题定位的容易性。

11.3 设计概念

11.3.1 抽象

抽象是控制复杂性的基本策略,是人类处理问题的基本方法。

抽象过程从特殊到一般的过程,上层概念是下层概念的抽象,下层概念是上层概念的精化和细化。在最高的抽象级上,用概括性的术语描述解决方案。在较低的抽象级上,将提供更详细的解决方案说明。

两种不同的抽象:

  1. 数据抽象——描述数据对象的数据集合,定义数据类型和施加于该类型对象的操作
    例如:门的数据抽象包含一组描述门的属性 (例如,门的类型、转动方向、开门方法、重量和尺寸)。
  2. 过程抽象——具有明确和有限功能的指令序列
      过程抽象的命名暗示了功能,但是隐藏了具体的细节,这些功能实际上是由一系列更低级的功能或代码来实现的。
    例如:过程抽象“开”将利用数据抽象“门”的属性中所包含的信息。
11.3.2 体系结构

==软件体系结构定义 ==
  软件的整体结构和这种结构为系统提供概念完整性的方式

软件体系结构设计的一组属性:

  • 结构特性定义了系统的构件(如模块、对象、过滤器)、构件被封装的方式以及构件之间相互作用的方式。例如,对象封装了数据和过程,过程操纵数据并通过方法调用进行交互。
  • 外部功能特性。应当指出设计体系结构如何满足需求,这些需求包括:性能需求、能力需求、可靠性需求、安全性需求、可适应性需求以及其他系统特征需求。
  • 相关系统族。体系结构应当能抽取出在相似系统开发中常遇到的重复性模式。本质上,设计应当能够重用体系结构构件。
11.3.3 模式

设计模式经过验证的,用于解决在特定环境下、重复出现的、特定问题的解决方案

11.3.4 关注点分离

关注点一个特征或一个行为,被指定为软件需求模型的一部分
关注点分离表明任何复杂问题如果被分解为可以独立解决或优化的若干块,该复杂问题能够更容易地被处理。
“分而治之”的策略——把一个复杂问题分解为若干可管理的块来求解时将会更容易。

11.3.5 模块化

模块相对独立的程序体

  • 模块是数据说明、可执行语句等程序对象的集合。
  • 模块是单独命名的,并且可以通过名字来访问。
    例如:类、过程、函数、子程序、宏等 。

模块化就是把程序划分成独立命名且可直接访问的模块,各个模块完成一个子功能,这些模块集成起来构成一个整体,完成指定功能

如果我们无限制地划分软件,开发它所需的工作量会变得小到可以忽略?
:错误,模块数量增加时,只是使各个子模块的工作量之和有所减小,开发工作量还有很大一部分来自于模块间的接口和集成,除了技术上的接口和集成,还包括人与人之间的沟通,集成和沟通的开销到一定程度就会成为开发工作量的主要部分。

模块数增加时,模块间的关系也随之增加,接口和集成的工作量也随之增加;
结论:寻找最佳模块化程度平衡点
在这里插入图片描述

模块化的优点

  1. 使开发工作更易于规划;
  2. 可以定义和交付软件增量;
  3. 更容易实施变更;
  4. 能够更有效地开展测试和调试;
  5. 可以进行长期维护而没有严重的副作用。
11.3.6 信息屏蔽

信息屏蔽的概念
  每个模块都尽量对其他模块隐藏自己的内部实现细节,只交流实现软件功能所必需的那些信息,模块内部的数据和过程不允许其它不需要这些信息的模块使用。
  典型的信息隐蔽:面向对象的访问控制符。
  信息隐蔽是实现抽象/模块化机制的基本支撑

信息隐蔽的优点

  1. 对外隐蔽,减少副作用的可能性;
  2. 强调通过控制接口进行通信;
  3. 使用封装——高质量的设计的一个属性;
  4. 使得产生高质量软件。
11.3.7 功能独立

功能独立关注点分离、模块化、抽象概念和信息隐蔽的直接结果

功能独立的重要性——具有有效模块化 (也就是独立模块)的软件更容易开发

内聚度与耦合度
内聚(cohesion):一个模块内部各个元素彼此结合的紧密程度
耦合(coupling):模块之间相互关联的程度

内聚度的七个层次

  1. 巧合内聚(偶然内聚):将几个模块中的相同程序代码段独立出来建立的模块 (无明显独立性)。
  2. 逻辑内聚:完成一组逻辑相关任务的模块,由控制型参数来确定执行哪一种功能 (选择其中一个功能,内聚性不强)。
  3. 时间内聚:模块中的多个任务必须在一段时间内先后执行 (有时间约束,无明确的过程约束)。
  4. 过程内聚:模块内的多个任务必须按指定的过程执行。
  5. 通信内聚:模块内所有处理元素都集中在某个数据结构的一块区域中(例如,对课程进行选、退课和查询)。
  6. 顺序内聚:指一个模块完成多个功能,这些功能又必须顺序执行 (更加单一的过程内聚)。
  7. 功能内聚 :指一个模块中各个部分都是为完成一项具体功能而协同工作,紧密联系,不可分割的 (单个功能)。

在这里插入图片描述

耦合度的七个层次

  1. 内容耦合:一个模块可以直接访问另一个模块的内部数据或内部功能。
  2. 公共耦合:多个模块共同访问某些公共数据元素。
  3. 外部耦合:多个模块间需要遵循同样的外部约束,例如通信协议、数据格式等。(遵循全局的约束)
  4. 控制耦合:模块间的交互参数包含控制信息,可影响另一个模块的执行逻辑。
  5. 标记耦合:模块间传递特定的数据结构。
  6. 数据耦合:模块间仅传递简单数据。
  7. 非直接耦合:两个模块可以相对独立工作。

在这里插入图片描述

11.3.8 求精

求精对各种抽象的细化
逐步求精为了集中精力解决主要问题而尽量推迟对细节的考虑,是一种自顶向下的设计策略
抽象和求精是互补的概念:
  抽象能够明确说明内部过程和数据,但对“外部使用者”隐藏低层细节,求精有助于在设计过程中揭示低层细节。

11.3.10 重构

重构——是一种重新组织的技术,可以简化构件的设计(或代码)而无需改变其功能或行为。
定义不改变代码[设计]的外部行为而是改变其内部结构

11.3.11 面向对象的设计概念

面向对象设计模式解决的是类与相互通信的对象之间的组织关系,包括它们的角色、职责、协作方式几个方面。

11.3.12 设计类

五种设计类,每一种都表示体系结构的一个不同层次:

  1. 用户接口类:定义人机交互所必须的所有抽象;
  2. 业务域类:通常是早期定义的分析类的精化。这些类识别实现某些业务域元素所必需的属性和服务(方法);
  3. 过程类:实现完整的管理业务域类所必需的低层业务抽象;
  4. 持久类:在软件执行之外持续存在的数据存储(例如,数据库);
  5. 系统类:实现软件管理和控制功能,使得系统能够运行,并在其计算环境内与外界通信。

组织良好的设计类的四个特征:

  1. 完整性与充分性
      设计类应完整封装所有合理预见的类中的属性和方法。例如,为视频编辑软件定义的Scene类,只有当它包含与创建视频场景相关的所有合理属性和方法时,才是完整的。充分性确保设计类只包含那些“对实现这个类的目的足够”的方法,不多也不少。
  2. 原始性
      应该关注于实现类的某一个服务。一旦服务已经被某个方法实现,类就不应该再提供完成同一事情的另外一种方法。例如,视频编辑软件的VideoClip类,可能用属性startpoint 和 end-point 指定剪辑的起点和终点。方法setStartPoint()和setEndPoint()为剪辑提供了设置起点和终点的唯一手段。
  3. 高内聚性
      一个内聚的设计类具有小的、集中的职责集合。例如,视频编辑软件的VideoClip类可能包含一组用于编辑视频剪辑的方法。只要每个方法只关注于和视频剪辑相关的属性,内聚性就得以维持。
  4. 低耦合性
      在设计模型内,设计类之间相互协作是必然的。但是,协作应该保持在一个可以接受的最小范围内。
11.3.13 依赖倒置

依赖倒置
  高层模块(类)不应当(直接)依赖于低层模块,两者都应当依赖于抽象。抽象不应当依赖于细节,细节应当依赖于抽象

11.3.14 测试设计

接缝
  即详细设计中的一些位置,在这些位置可以“插入一些测试代码,这些代码可用以探测运行中软件的状态”,以及“将待测试的代码从它的产生环境中分离出来,以便在受控的测试环境中执行这些代码。

11.4 设计模型

11.4.2 体系结构设计元素

体系结构模型从以下3个来源获得:
  (1) 将要构建软件的应用域信息(应用场景);
  (2) 特定的需求模型元素,如数据流图或分析类;
  (3) 体系结构模式。

11.4.3 接口设计元素

软件接口设计元素描述了信息如何流入和流出系统以及被定义为体系结构一部分的构件之间是如何通信的。

接口设计的3个元素:

  1. 用户界面 (User Interface, UI);
  2. 和其他系统、设备、网络或其他的信息生产者或使用者的外部接口
  3. 各种设计构件之间的内部接口
11.4.4 构件级设计元素

软件的构件级设计完整地描述了每个软件构件的内部细节:

  • 构件级设计为所有局部数据对象定义数据结构
  • 构件级设计为所有在构件内发生的处理定义算法细节
  • 定义允许访问所有构件操作(行为)的接口

UML构件图
  也称组件图。描述了软件的各种构件和它们之间
的依赖关系
。通常包括三个元素:构件、接口和依赖
在这里插入图片描述

11.4.5 部署级设计元素

部署级设计元素指明软件功能和子系统将如何在物理计算环境内分布

第11章 思考题

1.软件设计和编码有什么不同?
答:
  软件设计包括概要设计和详细设计,编码是将详细设计中的过程描述转换成用程序设计语言来描述。

2.如果软件设计不是程序,那它是什么?
答:
  软件的设计是将需求转变为软件陈述(表达)的过程。

3.如何评估软件设计的质量?
答:

  1. 设计应展示出这样一种结构
    (a) 使用可识别的体系结构风格或模式创建;
    (b) 由展示出良好设计特征的构件构成;
    (c) 能够以演化的方式实现,便于实现和测试。
  2. 模块化
    将软件逻辑地划分为元素或子系统;
  3. 设计应该包含体系结构、接口和构件的清晰表示
  4. 导出合适的数据结构
    数据结构适用于要实现的类,并从可识别的数据模式提取。
  5. 设计应导出显示独立功能特征的构件
  6. 设计应导出接口
    这些接口降低了构件之间以及与外部环境连接的复杂性。
  7. 设计方法应该是由需求信息驱动
  8. 采用有效的表示法
    使用能够有效传达意义的表示法来表达设计。

4.用自己的话来描述软件体系结构。
答:
  软件的整体结构和这种结构为系统提供概念完整性的方式

5.什么是关注点分离?分而治之的方法有不合适的时候吗?这种情况对模块化的观点有多大的影响?
答:
  关注点分离(Separation of concerns,SOC)是对只与“特定概念、目标”(关注点)相关联的软件组成部分进行“标识、封装和操纵”的能力。
  有,当复杂问题无法分解或者分解完子问题不可编码实现时,分而治之的方法就不合适了。
  会导致无法进行模块化处理。

6.什么是信息屏蔽?
答:
  每个模块都尽量对其他模块隐藏自己的内部实现细节。

7.重构意味着迭代地修改整个设计吗?如果不是,它意味着什么?
答:
  不是,重构意味着不改变设计的外部行为而是改变其内部结构。

8.什么是依赖倒置?
答:
  高层模块(类)不应当(直接)依赖于低层模块,两者都应当依赖于抽象。抽象不应当依赖于细节,细节应当依赖于抽象。

9.简要描述设计模型的四个元素。
答:
  ①数据设计元素创建了在高抽象级上表示的数据模型和信息模型。②体系结构设计元素被描述为一组相互联系的子系统,且常常从需求模型中的分析包导出。③接口设计元素描述了信息如何流入和流出系统,以及被定义为体系结构一部分的构件之间是如何通信的。④构件级设计元素完整地描述了每个软件构件的内部细节。

第12章 体系结构设计

12.1 软件体系结构

12.1.1 什么是体系结构

体系结构的概念
  也称架构,它是系统的一个或多个结构。它包括:构件,构件的外部可见属性以及它们之间的相互关系。

软件体系结构的作用:
(1) 对设计在满足规定需求方面的有效性进行分析;
(2) 在设计变更相对容易的阶段,考虑体系结构可能的选择方案;
(3) 降低与软件构造相关联的风险;

“体系结构”和“设计”的区别
  设计是体系结构的一个实例,对于同一个体系结构,可能会产生多种基于该体系结构的设计。

12.1.2 体系结构为什么重要

体系结构为什么重要

  • 有助于利益相关者的交流 (对体系结构的关注点不同);
  • 突出了早期设计决策,这些决策对随后的软件工程工作有深远影响,同时对系统的成功有重要作用;
  • 构建了一个相对小的,易于理解的模型,该模型描述了系统如何构成以及其构件如何协同工作。

12.3 体系结构风格

12.3.1 体系结构风格的简单分类

以数据为中心的体系结构
  数据存储驻留在体系结构的中心,其他构件访问该数据存储,并进行各种数据操作(更新、增加、删除或修改)
  黑板(变种):当用户感兴趣的数据发生变化时,它将通知客户软件。
在这里插入图片描述
优点

  • 开放:数据对所有使用者开放,客户软件可以直接决定存取方式;
  • 可集成性:现有构件可以被修改,新的客户构件可以加入到体系结构中,而无需考虑其他客户。

问题

  • 客户软件难以协作;
  • 中心数据的格式必须为所有客户软件所接受。

数据流体系结构
  当输入数据经过一系列的计算构件和操作构件的变换形成输出数据时,可应用该体系结构。
在这里插入图片描述
优点

  • 易理解;
  • 容易并行运行。

问题

  • 适用于批处理,不易交互;
  • 流的协作需要考虑。

调用和返回体系结构
  该体系结构风格能够设计出一个相对易于修改和扩展的程序结构。存在以下子风格:

  • 主程序/子程序体系结构:将功能分解为一个控制层次结构,其中的“主”程序调用一组程序构件,这些程序构件又去调用别的程序构件 (此时,对于被调者来说,这些主调者就是主程序)。
  • 远程过程调用体系结构:构件分布在网络的多个计算机上。
    在这里插入图片描述

面向对象体系结构
  系统的构件封装了数据和应用到该数据上的操作。构件间通过消息传递进行通信与合作

层次体系结构
  定义了不同的层次,各个层次完成各自操作;每一层为上层提供服务,又接受下层的服务
优点:明确的抽象层次、易于增减或修改层次;
问题:系统并不是总能分层。

13.3.2 体系结构模式

模式体系结构模式在特定坏境和一系列限制与约束下处理特定的应用问题。

体系结构框架是:一个特定应用领域问题的体系模式一个待实例化的完整系统

12.4 体系结构考虑要素

体系结构考虑要素

  • 经济性——许多软件体系结构深受不必要的复杂性所害,它们充斥着不必要的产品特色或无用的需求(如无目的的可重用性)。最好的软件应该是整洁的并依赖抽象化以减少无用的细节。
  • 易见性——设计模型建立后,对于那些随后将验证这些模型的软件工程师而言,体系结构的决策及其依据应该是显而易见的。如果重要的设计和专业领域概念与随后的设计和开发人员没有进行有效沟通,所产生的设计模型往往是晦涩难懂的。
  • 隔离性——适当的隔离会产生模块化的设计,但过分的隔离又会导致碎片化和易见性的丧失。
  • 对称性——体系结构的对称性意味着它的属性是均衡一致的,对称的设计更易于理解、领悟和沟通。比如,一个客户账户对象,其生命周期可被软件体系结构直接模式化为同时提供Open()和Close()方法。
  • 应急性——紧急的、自组织的行为和控制常常是创建可扩展的、经济高效的软件体系结构的关键。比如:许多实时性的软件应用是由事件驱动的,定义系统行为的事件序列和它们的持续时间确定了应急响应的质量,很难预先规划好事件所有可能的序列,相反,系统体系结构设计师应构建一个灵活系统,能够适应这类突发事件的出现。

12.5 体系结构决策

决策模型
  记录了所需要的体系结构决策、在过往的项目中实际做出的决策以及支持这些决策的理由。

12.6 体系结构设计

12.6.1 系统环境的表示

系统环境的表示
  软件体系结构设计师利用体系结构环境图对软件与外部实体的交互方式进行建模。

与目标系统交互的系统,即外部实体可表示为:

  • 上级系统:视目标系统为某些高层处理方案的一部分
  • 下级系统:被目标系统使用,向完成目标系统提供必要的数据和处理
  • 同级系统:在对等的基础上相互作用 (即信息或者由同级系统和目标系统产生,或者被同级系统和目标系统使用)
  • 参与者:通过产生和消耗必要的处理信息,实现与目标系统交互的实体。(人、设备)

在这里插入图片描述

12.6.2 定义原型

原型
  原型是表示系统行为元素的一种抽象。

12.6.3 将体系结构细化为构件

  在将软件体系结构精化为构件时,系统的结构就开始显现。
构件的来源如下:

  • 应用领域:需求分析模型中的类;
  • 基础设施域:如内存管理、通信构件、数据库构件等;
  • 界面领域:环境图中描述的接口隐含着一个或者多个特定的构件。

  每一个顶层构件都必须经过反复的迭代精化。

12.6.5 WebApp的体系结构设计

  WebApp是典型的使用多层次体系结构来构造的客户端–服务器应用软件,包括用户界面或表现层、一个基于一组业务规则来指导与客户端浏览器进行信息交互的控制器,以及可以包含WebApp的业务规则的内容层或模型层。

12.6.6 移动App的体系结构设计

  移动App是典型的使用多层体系结构来构造的系统,包括用户界面层、业务层以及数据层。
影响移动App体系结构设计的方面:
 (1)将要建立的Web客户类型(瘦或富客户端);
 (2)所支持的设备种类(如智能手机、平板电脑);
 (3)连接程度需求(偶尔的还是持久的);
 (4)带宽需求;
 (5)移动平台的限制;
 (6)重用和可维护性的程度也是重要的;
 (7)设备资源的限制(如电池寿命、内存大小、处理器速度)。

12.7 评估候选的体系结构设计

12.7.2 体系结构评审

体系结构评审
  体系结构评审是一种特定的技术性评审,它提供了一种评估方法,该方法可以评估软件体系结构满足系统质量需求的能力以及识别任何潜在风险的能力。体系结构评审可以尽早检测到设计问题,具有降低项目成本的潜能。
  与需求评审会涉及所有利益相关者的代表不同,体系结构评审往往只涉及软件工程团队成员,并辅以独立的专家。业界最常用的体系结构评审技术有:基于经验的推理、原型评估、情境评审以及检查单的使用。

12.8 经验学习

经验学习
  Wright [Wri11]建议了几种决策分析和解决方案(Decision Analysis and Resolution,DAR)的方法,有助于消除分歧和促成协作。三个代表性DAR方法如下:

  1. 原因链法。一种根源分析的技术,团队定义好一种体系结构的目标或效果,然后阐述导致目标实现的相关动作。
  2. 石川鱼骨法。一种图示技术,列出为达成既定的体系结构目标所需的各种可能的操作或原因。
  3. 思维导图或蜘蛛图。这种图示方法用来表示围绕着一个中心关键词、约束或需求的词汇、概念、任务或软件工程产品。

12.9 基于模式的体系结构评审

基于模式的体系结构评审
  基于模式的体系结构评审(Patten-Based Architecture Review, PBAR) 是一种用来平衡体系结构模式与软件质量属性之间关系的评估方法
  PBAR是一种轻量的评估方法,非常适用于小规模敏捷团队,只需要相对较少的额外项目时间和精力。只需要很短的准备及评审时间,PBAR便能够适应不断变更的需求和较短的建设周期,同时,也有助于团队理解系统体系结构。

PBAR包含以下的迭代步骤

  1. 遍历相关的用例,以确定并讨论系统最重要的质量属性。
  2. 结合需求讨论系统体系结构图。
  3. 协助评审人员识别使用的体系结构模式,并将系统结构与模式结构相匹配。
  4. 使用现有文档和过往用例,检查体系结构和质量属性,以确定每一种模式对系统质量属性的影响。
  5. 识别并讨论由设计中使用的体系结构模式所引起的质量问题。
  6. 针对会议上出现的问题作一个简短的汇总,并对可运行的系统骨架进行相应的修正。

第13章 构件级设计

13.1 什么是构件

构件定义
  计算机软件中的一个模块化的构造块。
OMG UML的构件定义
  系统中模块化的、可部署的和可替换的部件,该部件封装实现并暴露一组接口。

13.2 设计基于类的构件

13.2.1 基本设计原则
  1. 开闭原则 (The Open-Closed Principle, OCP):模块应该对外延具有开放性,对修改具有封闭性;
  2. Liskov替换原则(LSP):子类可以替换它们的基类;
  3. 依赖倒置原则(DIP):依赖于抽象,而非具体实现 ;
  4. 接口分离原则(ISP):多个用户专用接口比一个通用接口要好。
13.2.3 内聚性

内聚性
  描述为构件的专一性
  内聚性意味着构件或者类只封装那些相互关联密切,以及与构件或类自身有密切关系的属性和操作。

内聚性分类

  1. 功能内聚
      主要通过操作来体现,当一个模块中的各个部分只完成某一组特定操作并返回结果时,就称此模块是功能内聚的。(最好的内聚)
  2. 顺序内聚
      模块中各个处理元素密切相关,必须顺序执行,前一功能元素的输出就是下一功能元素的输入
  3. 过程内聚模块内的多个任务必须按指定的过程执行
  4. 通信内聚:模块内所有处理元素都集中在某个数据结构的一块区域中。(模块中所有成分引用共同的数据
  5. 时间内聚
      模块各个功能的执行与时间有关,通常要求所有功能必须在同一时间段内执行
  6. 逻辑内聚
      模块把几种相关的功能组合在一起,每次被调用时,由传送给模块的判定参数来确定该模块应执行哪一种功能
  7. 实用内聚
      逻辑上不能纳入其他内聚类型的相关实用程序放在一起,形成实用内聚 (巧合内聚)。(将多处出现的相同的一组语句用函数或者类进行封装)
13.2.4 耦合性

  构件之间彼此联系紧密程度的一种定性度量。随着构件相互依赖的增加,构件的耦合程度也会增加。

耦合性的分类

  1. 内容耦合 (耦合度最高,最不推荐)
    包括下列情形:
     (1) 一个模块直接访问另一个模块的内部数据;
     (2) 一个模块不通过正常入口(调用或顺序执行)转到另一模块内部;
     (3) 一个模块有多个入口。
  2. 共用耦合
      若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为共用(公共)耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
      缺点:进行变更时,会导致不可控制的错误蔓延和不可预见的副作用
  3. 外部耦合:多个模块间需要遵循同样的外部约束,例如通信协议、数据格式等。(遵循全局的约束)
  4. 控制耦合
      如果一个模块通过传送开关、标志、名字等控制信息,控制选择另一模块的功能,就是控制耦合。
      缺点:模块B中的一个不相关变更,可能会导致模块A所传递的控制标记的意义也必须发生变更。
  5. 标记耦合(特征耦合)
      一个数据结构被作为参数传递。并且被调用模块只使用了部分而非全部数据。
      问题:传送了不必要的数据:
  6. 数据耦合
      如果一个模块访问另一个模块时,彼此之间是通过简单数据参数 (不是控制参数、公共数据结构或外部变量)来交换信息的,则称这种耦合为数据耦合。(推荐使用的方式)
  7. 非直接耦合
      两个模块可以相对独立工作。

模块关联的评价指标
扇出一个模块直接控制的模块数目。扇出过大意味着模块过分复杂,需要控制和协调过多的下级模块。理想的平均扇出为3-4(上限为5-9)。
扇入有多少个上级模块直接调用它。扇入越大意味着共享该模块的数目越多。
  设计得好的软件结构通常顶层扇出高,中层扇出少,底层高扇入

13.3 实施构件级设计

实施构件级设计步骤
步骤1:标识出所有与问题域对应的设计类:
步骤2:确定所有与基础设施对应的设计类:
步骤3:细化所有不能作为复用构件的设计类:
步骤3a:说明消息细节
步骤3b:确定接口
步骤3c:细化属性
步骤3d:详细描述操作中处理流
步骤4:说明持久数据源(数据库和文件)并确定管理数据源所需要的类:
步骤5:开发并且细化类或构件的行为表示 (可用状态图):
步骤6:细化部署图以提供额外的实现细节
步骤7:考虑每一个构件级设计表示,并且时刻考虑其他可选方案:

13.4 WebApp的构件级设计

WebApp构件是
  (1)为最终用户处理内容,或提供计算或数据处理;
  (2)提供最终用户所需的功能
  因此WebApp构件级设计通常包括内容设计元素功能设计元素

13.6 基于构件的开发

基于构件的软件工程(Component-Based Software Engineering,CBSE)是一种强调使用可复用的软件构件来设计与构造计算机系统的过程

  • 把重点从编码转移到组装软件系统;
  • 考虑的焦点是“集成”,而不再是“实现”。

第14章 用户界面设计

14.1 黄金原则

关于界面设计的三条黄金原则

  1. 把控制权交给用户
  2. 减少用户的记忆负担
  3. 保持界面一致

14.4 界面设计步骤

14.4.3 设计问题

界面设计时,总会遇到以下6个问题:

  1. 系统响应时间(两个重要属性:时间长度和可变性
  2. 用户帮助设施
  3. 出错信息处理
  4. 命令标记
  5. 应用系统的可访问性
  6. 国际化

第三部分 质量管理 & 第四部分 管理软件项目

软件工程知识点总结——第三、四部分

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值