开发模型是软件工程中指导开发的一种开发思想和开发体系。
不同的开发模型分成不同的阶段,具有不同的指导思想,做着不同的事情。
开发模型多种多样,经过几十年的发展,产生了很多开发模型,各种开发模型各有特色。
1970年温斯顿·罗伊斯(Winston Royce)提出了著名的“瀑布模型”,直到80年代早期,它一直是唯一被广泛采用的软件开发模型。在全盛时期,大约90%的项目采用瀑布模型,包括美国的国防部都是指定使用瀑布模型进行开发。但是慢慢的瀑布模型就淡出了人们的实现,基本上属于被淘汰的行列,因为瀑布模型具有重大的缺陷。这种缺陷足以导致项目的失败,因为有研究机构进行过统计分析,发现使用瀑布模型做开发十有八九会失败,这种失败体现在 要么延期,要么成本超支,要么根本就做不下去了。
那么为什么会有这样的现象诞生呢?请带着疑问往下看。
图注
瀑布模型的开发过程中,每一个步骤的末尾都会有软件的评审工作;评审上一个步骤是否合格,上一个步骤相应的产出物是否符合相关要求,这些标准都被评审的,而且瀑布模型更强调文档化标准化。
瀑布模型是一个结构化方法中的模型,一般应用于结构化的开发。而且非常具有代表性,它把结构化特点表现的淋漓尽致。
讲到这里,似乎还没有看出有什么缺陷,做事情先有计划再分步骤进行,每个步骤完成后做评审,这似乎是一种很好的方式,而且改进后的瀑布模型还加了回溯的通道。
这样子看起来似乎还不错,为什么会导致那么严重的问题呢?
根本性原因是 需求阶段难以把控。软件的需求往往是不明确的,往往是在项目的初期阶段。你要在软件需求的项目初期能明确几乎是不可能,这就导致了在需求不明确时就开始做,而我们开始做的时候认为这种需求就是用户所需要的东西,完成开发阶段之后交给客户去验收,很大概率会推翻你的所有工作,为什么呢?客户会告诉你这里不行,哪里不行,哪里需要改,这个思路跟我们想的不一样等等这些问题,所以需要回到需求分析重新开始。这样子会导致浪费大量的时间,最终导致软件项目的失败,就是因为这个原因使得瀑布模型很难完成项目的开发。
瀑布模型适用于什么样的场合呢?
需求明确或者是二次开发的情况下。当然我们也可以把瀑布模型用在这种场合下,用其它模型先把需求做明确,再按照瀑布模型完成开发阶段和维护阶段,这也是可以的。
总结
瀑布模型是一个结构化方法中的模型,一般应用于结构化的开发。
瀑布模型只适用于需求明确的项目,对于需求不明确的项目千万不要使用瀑布模型做开发。
瀑布模型是比较早的一种模型。在它出现之后,引起人们对模型的疯狂追逐,所以产生了很多其它的一些模型。当然,在产生其它模型的同时人们也注意到瀑布模型巨大的缺陷,所以试图避免瀑布模型的缺陷在其它模型中重新出现,避免重蹈覆辙。
原型模型和瀑布模型是一对互补的模型。瀑布模型失败是因为对需求变化无法进行灵活的应对,它无法把握需求从而导致后面开发产生一系列问题,所以原型模型从诞生开始就定位于需求不明确的情况下使用。
原型模型是怎么做的呢?
假设开发一个系统初期进行需求分析方面的工作时,无论你跟用户做如何详细地沟通,用户都很难把他的需求表达准确和全面。原因就是用户自己也不知道需要一个什么样的系统,而且用户和开发团队之间有一个隔阂——双方的知识领域不一样,这样就导致了沟通需求方面存在很多问题。那么原型模型就强调在项目开发的初期会构造一个简易系统。
这个简易系统是什么呢?
它可以是一套界面,展示我们这个系统开发之后,是一个什么样子的情况,在哪里显示什么按钮,点击按钮会产生什么样的现象。也可以做一个初步的系统出来,让用户来看一看用一用。
原型模型强调构建一个简易系统的好处:就是可以让用户知道开发出来的东西是什么样子从而知道一些细节需求。但是原型模型往往只用于开发过程中的需求分析阶段。
如果说咱们把最初的原型通过很多步的演化调整,最终变成了给用户使用的软件产品,我们称这种模型为演化模型。
由原型模型的思想和瀑布模型的思想结合得到 增量模型。
增量模型是一种怎样的思路呢?我们知道用户有多种多样的需求,其中核心是哪一块呢?
我们做系统的时候先把核心的部分做出来,这个周期可能有原来做项目的20%的时间,做好核心的几个模块,就把做好的核心模块拿去给用户使用,用的过程中发现问题就修正问题,下一个月又开发另外两个模块,就这样子一部分一部分进行,就这样软件越变越大,到最终完成所有的内容,这就是增量模型。
好处:核心模块比较早的和用户进行了接触,在每一轮交给用户去看相关效果的时候,都相当于对核心模块进行再一次的审视,所以这种项目做下来风险会小很多,这是不会出现最后用户提出来核心功能不行需要修改的情况,要修改的内容在整个流程中就已经改完了。
总结
这就是原型模型和瀑布模型与其它模型的一些区别和联系。
原型强调构造一个简易的系统,而且它是针对需求不明确的情况。
螺旋模型基本形状犹如螺线形状,从中间一圈一圈地循环出来,所以称之为螺旋模型。
螺旋模型也是从最初的原型发展而来的。在这种模型中,融合了多种模型的特征,比如说有原型,演化、瀑布模型等一系列模型。
特征①:从上方图中可以看出,螺旋模型的步骤中具有最初的原型和分阶段的瀑布模型的过程。由多个模型组成,所以多个模型的特点它都具备。
特点②:引入了风险分析。因为它是成螺线圈的形状一圈一圈循环出来的这个过程中有风险分析,这个风险分析是之前一系列模型中都没有的特征,所以风险分析就成了螺旋模型中最显著的特征之一。
V模型以形状而得名,整个流程形成一个V字型。
从这样的阶段划分可以看出跟瀑布模型非常地接近。
快速开发模型属于由瀑布模型(SDLC)和构建组装模型(CBSD)形成的一种模型。
如果说用VB等可视化的工具做开发,那就已经运用到RAD模型了。为什么这么讲呢?
我们可以看到如果像瀑布模型做相应的一些开发,按照流程来走会有很多部件形成了组件化,这就已经符合快速开发的特点了。因为这个名词是很多年前就已经提出来了,以前做开发时你要使用C语言做个界面出来,那么你需要花费很多时间来绘制这个界面,然后才能形成漂亮的图像化界面。但可视化工具的诞生就改变了这一切,通过拖动的方式就能够达到目的。空间、按钮、连接数据库、显示报表信息等等这些已经有了非常标准的构件,还有很多人为第三方提供了相应的第三方的构件库。所以RAD就结合瀑布模型和构建组装模型的特点形成了自己的风格。
用RAD开发的过程依次为 业务建模、数据建模、过程建模、应用生成、测试与交付。
这种模型最大的特点就是能够快速的构建应用系统,所以这些技术出现之后就能够得到广泛的应用,很多信息系统都是用到来做相应的开发。
这种模型的基本思路是什么呢?
把软件开发当中的各个模块考虑成为标准的构件,做成标准构件之后,通过一定的方式进行组装就得到了我们最终需要的软件。
那么这种思路为什么能够得到广泛的认可呢?
其中一个最重要的原因就是极大的提高了软件开发的复用性,一旦提高了复用性就可以使得软件的总时长极大的减小,可以使软件的成本降低,同时还可以使软件的可靠性增加,缩短时间减少成本。
为什么能够提高可靠性呢?
因为在CBSD这种开发模型当中会建立一个构件库,这个构件库中的构件如果说在新的系统中用得上,就可以直接提取出来应用它。构件库中有着以前很多的构件,这些构件以前运用到其它系统中的构件,这些构件的可靠性已经经过了很长时间的验证,如果说有问题,在以前的系统中就已经发现并修正了,所以在应用到新的系统中,出错的效率就远远小于新开发的构件,正是因为有着这样的新特色,CBSD也就是有着非常强的竞争力。很多的软件开发模型都应用到了这种思想,如RAD。
从所有开发方法来看,敏捷开发方法属于比较年轻的一类开发方法。
发展历程
最初咱们是没有模型没有方法的,这样子发现产出的软件产品质量很难控制,所以发展出了软件工程,随之发展出了一系列开发方法开发模型,在开发模型和方法一步一步增加的时候,规范程度越来越高的时候,人们就发现在开发过程中真正按一些重量型模型去做开发往往是得不到很好的效果的,因为重量级的开发模型非常地关注流程和文档,通过这些方式来规范你的开发,那么这样一来,我们会发现开发人员的负担会越来越重,而你产生的这些文档也不见得你真正用得上,所以花了那么多的时间做出来的东西不见得是那么的好,所以有人提出来要为开发人员减负,如何减负呢?把不必要的流程砍掉,把不必要的文档减去,这样就形成了敏捷开发的思想。
当敏捷模型的基本原则都达到要求时,就进入了下一个轮回,为什么呢?
这就相当于原来是减,然后减难以控制就变繁,即加了很多的流程规范,流程规范过多就导致走出了正常的尺度,那么咱们就需要回归到轻量级简单级的开发模式。基本就是这种思路,但是这种状态和项目开始比较简单的状态有着本质上的差异,同时敏捷方法也有着很大的局限性,为什么这么讲呢?因为敏捷方法的思路只使用中小型项目,绝大部分是小型项目,中型项目就有点为难。一般是小型项目,做小型项目一般是比较合适的,因为你砍掉一些文档是没有问题的,核心文档抓住就行了,但如果是大型项目就有点力不从心了。因为IBM做过这种尝试,用极限编程(XP方法)来做一个项目,而且还是作为极限编程的样本工程,结果项目做了不到两年失败了,原因就是规模太大,不适合敏捷开发方法。所以敏捷方法往往是适用于小项目,它强调的是小步快跑的模式去做项目。
如果说让大家写一篇敏捷开发的文章,你可以取几个点来讲,比如:讲一讲敏捷编程的思路,讲一讲每周工作40小时不加班的好处,运作过程中遇到些什么问题等等。从这些思路进行分析进行探讨。
信息系统开发方法主要分成四种方法。
以前用结构化方法做开发非常之普遍。
结构化方法的特征
把上面的几条特征看完之后,大家是不是有种感觉,每一条似乎都是优点,你看自顶向下逐步求精分解。那这种过程往往适合于把复杂的事物把它简单化,这是有好处的,像工程化,文档的标准化,那自然也有好处是不是?然后强调整体全局,这些似乎都是它的优点。
为什么结构化方法全身似乎都是优点,但是慢慢的被面向对象方法所取代了?
因为目前来讲不争的事实就是现在结构化方法用的是越来越少,面向对象方法用的是越来越多了。那么我们就应该反思 问题出现在哪里呢?
结构化方法最大问题就在于一旦开发完成,它的流程是固化的,是不灵活的。为什么这么讲呢?比方说咱们开发一个软件,就好比开发一套财务系统,好花了几个月时间把它开发出来了,整个财务审批的流程是当事人提交申请,部门经理签批,然后总经理签批,最后到财务那里去领款。因为公司人数还不多,所以财务权把控在总经理手上。但是随着公司不断的发展壮大到几百人的时候,总经理发现这个事情不能够由我来做,否则的话我一天到晚都忙着财务签批去了。这个时候任命了一个财务总监专门来为这个事情把关。而总经理就月度来看这个报表。所以这么一个改变在现实生活中是非常简单的。再比如我们召开一个会议说今天是星期五,下周一开始咱们走新流程,大家都清楚了,这个流程改起来了非常的容易,这是在现实生活中的。而在系统里面,假设你开会公布了这个事情之后,接下来你跟这一个开发团队讲说,大家也参与了会议,也知道咱们这个会议的主题。那么大家知道流程变化了,这是一步,另外一步非常重要的就是咱们系统要支持,所以大伙这个周末加一加班,把它改过来。那这个时候如果说你是这个开发团队的一个主管,你可能就会头痛了。一个系统你说看上去容易,但实际上它涉及到的面可能比较多。尤其是这一套系统,如果说跟其他部位有一些衔接,那你还不好随意动。因为你这样子改变了是需求变了,需求变了,设计要变设计变了,编码要,编码变了还得做测试。所以我们会发现,现实生活中分分钟就能够解决的问题,在系统中变得非常的麻烦。流程不容易变化,这就是结构化方法最大的弊端。所以就出现了面向对象方法。
原型化方法主要是应用在开发的一个阶段,即需求阶段。
现在主流的开发方法都是用的面向对象开方法。
既然结构化最大的败笔是系统和现实有着比较大的差距,那我就把这一块做得更好一些。
在开发系统之前,先抽象在现实生活中,这个系统会涉及到哪些人、哪些物,我们会把这些东西都抽象为对象。然后不同对象之间的区别可以用属性来区分一个对象和另外一个对象。现实生活中的动作可以用了对象本身已有的方法来写它能干什么。这样一来就 建立了一个全面合理统一的模型 之后,整个开发就容易了,相当于整个开发就是在组流程。所以这种系统往往会有更好的 复用性 。因为对象在这一个系统里面,我把它创建出来了,在另外的系统里面我们也可以了复用部分的对象。与此同时,面向对象的方法 分析、设计实现这三个阶段界限已经不明确,因为做需求分析的时候会把设计的一些活也干了,这样子的话两者之间就没界限。
面向服务方法属于一种比较新的方法。它的整个体系还不是非常的成熟,所以在考察过程中我们只需要了解图中的基本特性就可以了。其中 SOA 就是我们后面要讲到的面向服务的架构。
需求的分类根据不同的方式有不同的分法。
首先需求它可以分为业务需求、用户需求和系统需求。
所谓业务需求,其实是从业务的角度有一个比较总态的一个描述。比方说我的企业要开发一套财务管理系统,那这个时候如果说我们有内部团队会是一个什么样场景呢?大家可以想象一下,如果说我是这一家公司的总经理,那我会把我开发部门的经理叫过来。我告诉他,按现在公司业务发展的需求,我们需要开发一套适合于自身的财务系统。然后把财务的审批、费用的报销等等这些东西给系统管理起来。大致讲一下宏观方面,我们对这个系统的一个初步的想法,大的方面的想法。这个时候业务部门的这个经理,开发部门的经理他可能会提出疑问来。那具体来讲咱们哪些职位会用到财务系统,每一个职位,它具体有什么样的要求了?我作为公司的总经理,我是不会去跟他讲这些东西的,我只会告诉他这套系统反正是内部人员用,大致是会涉及到哪些角色,在讲宏观的业务的需求的时候会提到。
那这个时候你作为开发部门的经理,你就会要去思考一个问题,这套系统为了满足业务的要求,我们应该要涉及到哪些角色,要做哪些事情。有这个初步想法之后了,你应该去找各个角色去进行沟通,由各个角色给你反馈。你比如说会计,比如说出纳,你去跟他聊的时候,你从它的那里去获取到,从这一个角色本身的角度来看,需要一些什么样的功能,需要走什么样的流程,就是这样的一个思路。聊完了之后,把这些各个用户从他们自身角度描述的比较微观的这些需求把它们收集起来,这是用户需求。
用户需求收集到之后,要把它转成系统需求。系统需求就是把用户需求转换成计算机能够指导开发的需求。比如说哪些地方它往往是以窗口的形式表达,哪些地方是以选择的方式是来进行,等等这些东西要考虑进去。具体来讲,系统层次的需求会包括功能需求、性能需求和设计约束。
从 QFD 质量展开模型的这一个角度来看的话,需求可以分为基本需求、期望需求和兴奋需求。
基本需求就是用户明确提出来需要完成的一些需求。这部分需求对于我们开发团队而言是必须要去完成。
希望需求是用户没有明确提出来,但是用户觉得这个话根本不用我讲,你就应该要把这个事情做好,他认为理所应当,这个系统要达成这样的一个效果,这一部分需求也是你必须要去做的。有的时候我们为什么会讲需求工作难做,客户没讲,但你要领会到他的意思,把他做出来,否则他也不满意。
兴奋需求就是用户没有提出来要做这个事情,他也没有觉得这个事情是必须要做的,而开发人员给做了。就好比我们开发一套财务系统好财务的有一些指标,可能我们要用一些报表的方式 整体地总态地体现出来会比较好。客户只要求到这一个程度,结果你的开发人员一看说,直接使用报表,看起来似乎有些枯燥。对很多指标我给你既有报表也有这一个曲线图,还有饼图之类的,给你把这个整个的一些情况趋势都给展现出来。这种做法对于客户而言,他是开心兴奋的。因为除了做好他要做的希望得到的效果以外,还有额外的东西也给他做好了,超预期了,他是很开心的。但是这种做法我们是不提倡,甚至是要严格控制的。为什么?
如果说你作为开发方的角度来看,这就是一个风险极大的事情。因为你去做这些额外的事情会涉及到成本的增加,本来可能一个月就能够完成的任务,因为你的程序员私自加了这么一些需求给他实现了,所以导致这个项目做到了一个月零几天。那么这几天的成本是不是由项目组来支付啦。所以很有可能一个利润很高的项目就被这么一些小的东西给折腾,一些无关紧要不需要去实现的需求给他消耗掉成本了,导致了项目没什么太多利润,这种情况当然要杜绝了。
所以从 QFD 的角度了,是要我们分清楚哪些事情我们该做这些事了,我们必须得去做哪些事情不该做,那就杜绝他不要去做他,这是这一个分类的问题。
所谓结构化设计,其实就是结构化方法里面的软件设计问题。
软件设计的三个原则
这种设计基本的原则是自顶向下逐步求精,意思就是从上而下来进行,然后一步一步拆分就精化了,细化了问题。
在设计的过程中还要注意信息隐蔽的原则。所谓信息隐蔽,其实就是一个函数里面的内容是不宜展现在外界的。为什么会有这种要求呢?我们可以把这一个函数看成是一个部门,因为函数能够完成一个功能,一个部门协同也完成了相应的功能。如果说部门和部门之间要进行协作,协作过程中一个部门可以直接指挥到另外一个部门里面,具体的人力资源往往会乱套。那这个时候我们采取的办法是什么呢?就是两个部门它都有部门相应的接口。然后我要操作另外一个部门的时候,我实际上是去操作这个部门的接口,然后这个部门接口会把相应的信息传递到它的内部,然后进行内部的相关的一些调度协同工作,最后完成任务。这就是一种信息隐蔽原则,内部的信息不向外界展现,展现的只是接口。
第三个原则就是模块独立的原则。比方说我一个系统有多个模块,这些模块联系比较紧密会好一些,还是连的比较松散会好一些呢?或者说更具体一点,中间存在一个 A 模块它跟周边的很多模块有关联会比较好,还是跟很少的模块有关联比较好呢?显然是联系松散一些会比较好。模块独立性差带来了什么问题呢?修改比较麻烦,修改比较麻烦。比如说我要修改模块 A 那你要考虑它对周边模块的影响,修改了模块 A 会不会导致周边模块也发生一些变化呢?修改了 A 之后也是需要考虑了周边的变化。修改完成,我们要进行回归测试,回归测试又得把周边这些模块全测一遍,所以问题就变得复杂了。所以我们希望模块的独立性比较高。
模块独立性比较高,用什么指标来衡量呢?
就是类聚和耦合两个指标。所谓类聚,就是一个模块内部的各个部件,它连接的紧密程度往往累积越高越好。这说明这个模块内部联系紧密,是应该要化成一个模块来处理的。而耦合是模块与模块之间的一个衡量的概念。耦合程度越高就说明了这个模块跟其他模块联系比较紧密,耦合程度低,说明一个模块和其他模块联系是比较松散。所以耦合这个指标要求是低耦合,意思就是一个模块尽可能低的,少的与其他模块进行关联。这是这样的一个情况。同时要控制模块的复杂度。
软件设计的一些细致的条款
模块的内聚性表现在模块内部各个子成分功能的集中程度,分成6个级别,如下图所示:
类聚程度最高的是功能类聚,最差的是巧合类聚(偶然内聚)。
耦合程度最高的是内容耦合,耦合程度最低是非直接耦合。
在这一个图当中展示了一系列的这种变换图
我们看到变换图当中其他图形基本了解一下就可以了。对于这一个图(B)是需要掌握的,这个模块它分成 传入型、传出型以及变换型。
传入型是直接把这个数据传入进去,箭头是单向的;传出型是直接把这个数据传出来,箭头也是单向的;变换型箭头是双向箭头的。
PS:软件测试是考试当中每次都会考到的一个知识点。软件测试的内容主要是出现在上午题中,偶尔作为小的问题出现在案例分歧当中,同时也有一定的几率的出现在论文当中。当然一般我们对测试有着一些基本的认识,同时按方法去练好论文的技巧。
尽早、不断地进行测试
这一点和我们之前所讲到的V模型是非常吻合的。V模型认为咱们做测试工作如果说把测试工作都压在最后面去做,这会有极大的风险。因为当你发现问题的时候,你要去修改会要做非常大的一些调整。所以要尽可能早的去做测试,这样子发现问题可以以代价很低的时候就予以修正。
程序员要避免测试自己设计的程序
因为从人性的角度来看,这段程序是程序员编写的,然后你花了很多时间精力去编写它,希望把它做得尽善尽美。从内心里面来讲,你希望它满是窗怡,而非到处是 BUG。所以说了你在测试的时候,潜意识里会按你自己设计的思路去设计一些了能够通过测试的用例,而不会想着想尽办法找出他的错误了,这是一方面。
另一方面就是因为你带有你设计的思路去做相应的测试,这种测试是不全面的,因为你想到的你就设计进来了,你没有想到的那一部分很可能就有瑕疵,有问题的部分。即你做设计的时候没想到你做测试的时候仍然没有想到,所以不应该由程序员去测自己的写的程序,这样子做就不容易找出问题。
既要选择有效、合理的数据,也要选择无效、不合理的数据
有效合理的意思就是在合法的取值范围之类。你比如说要输入一个年龄,设计输入数据为 1 岁、5岁、10岁、90岁等等,这些都是属于合法的数据,它能够录入到系统并且正常处理。但是你不能够仅仅只选这些数据,除了这些数据你还要选不合理的数据,比如说输入数据为 300岁 看看会是什么情况?因为现在还没有人活到这么高的年龄,和这个年龄相差甚远,最多也就活到 100 多岁,一般输到300,说明了输入的数据很有可能出错了。好像这种不合理的数据要输入还有什么数据呢?你比如说 101 岁,后面这个 1 了输成了小写字母的 L 看上去和 101 非常像。那这种数据也要输进去测一测为什么?因为很有可能用户在使用的过程中一不留神 copy 了一个年龄,一看以为是101,结果了后面是 L 那用户用的时候就会发现报错了,他不知道是什么原因。所以在测试的时候,这些五花八门的情况都要测进去看。面对这种不合理非法数据的时候,系统是怎么反映的?应用程序会不会立马崩溃,报异常错误之类。所以测试数据要显得全面,既有有合理的,也要有不合理的。
修改之后应进行回归测试
什么叫回归测试了?在修改成功 一些 bug 之后,不要直接就发布并使用该系统,这是不行的。因为你修改一个 bug 之后,很有可能引入其他的 bug,这个时候你需要做回归测试,就是把之前已经测过的这个模块重新再测一测,看会不会发生新的问题。
尚未发现的错误数与该程序已发现的错误数成正比
这句话的意思就是有一个程序 A 我们经过测试发现了它有 30 个 bug。有一个程序 B 经过测试发现了它有 100 个 bug。A 和 B 所有 BUG 全部修正之后,应该重点测哪个模块呢?应该重点测 模块B 因为尚未发现的错误数量与该程序已发现错误数成正比。为什么会有这种情况呢?因为模块之间它的难度会有很大差异。对于原来写得好的程序,可能测出来整体的 bug 数就会比较少,同时它隐藏的 bug 了也比较少。而对于找到了大量 bug 的,往往是不成熟的团队开发的,可能隐藏了更多的问题。所以要利用到这一点来做一些分析。你像这两个模块把所有的 bug 都修正之后,重点测的还是 B 模块。这就成正比的原因。
另外一个方面就是修正一个 bug 会引入新的 bug,那 100 个 bug 修正引入新 bug 的数量,也会比 30 个引入新 bug 的这个情况会要严重一些。
这是测试的一些基本原则。当然测试的原则肯定不仅仅只有这么五条测试的基本原则,它是一种思想。
既然是一种思想,它可以有很多很多的讲法,只要符合测试的基本观念思想就是 OK 的。所以这五条基本的原则可以引申出很多条。所以在了解这些概念的时候,我们更重要的是注意它如何去推导出来,是什么理念,这样子才能够举一反三。
动态测试 指利用到了计算机进行测试
动态测试分黑盒、白盒以及灰盒。黑盒测试有多种方法都属于黑盒测试,白盒也是这样子的。灰盒测试就是将黑盒和白盒两者结合,这其实很符合中国人的中庸之道。就黑的白的都有好的地方,那我们就把它综合起来应用。这些后面会详细的展开来讲动态测试。
静态测试 指纯手工进行测试,期间没有利用到计算机
测试用例设计涉及到两大方法体系,一个是黑盒测试法,第二个是白盒测试法。
黑盒测试法 指在测试的时候,你能够把这一个软件模块看成一个黑盒子。你看不见里面是什么东西并且不能够打开盒子,但是知道这个盒子输入是什么、输出是什么。即不知道软件模块的内部结构。
白盒测试法 指的在测试的时候,你能够把这一个软件模块看成一个白盒子。你能够打开盒子,看到里面是怎么样的一个情况,看里面的结构是怎么样的。即知道软件模块的内部结构。
以程序模块为例来说明黑盒和白盒测试。
如果说是黑盒测试,我们只知道这个模块的功能是什么,它要输入什么样的参数,它将输出什么样的结果,测试的时候以什么方式来衡量模块是对还是错。比如:它是一个加法模块,输入 1 和 1,得到的结果观察是不是 2 。如果得到的结果是2,我们认为这一组测试用例得到了正确的结果。再用其他的测试用例来进行测试,查看得到的输出是否为正确的结果。
如果说是白盒测试,我们可以看到程序的内部结构,通过程序内部结构来设计测试用例。比如说我们看到一个分支,那我测试用例设计的时候可能就考虑设计用例不能够设计都走一条路线,应该设计两个真分支和假分支,两个分支分别设计一个测试用例。
所以说相对来讲,从理论上来讲,白盒测试往往会比黑盒测试了能够做得更加全面一些,因为你可以看到它结构,当你看到它结构,把所有结构当中的路径全部都用测试用例覆盖一遍的时候,你的测试是完整的完善的。而黑盒测试了是没有这种先天条件的。但是通过科学合理的方法设计,我们也能够把这种覆盖度达到一定的程度。
黑盒测试的测试方法
等价类划分
首先考虑这一个程序模块它的功能是什么,然后它处理这些数据里面哪些数据可以归为一类,分类之后从每个类中设计测试样例。举个栗子,把成绩分等级进行划分,高于 90 分或者等于 90 分的分数我们认为它是优;大于 70 分的是良;高于 60 分的是及格;低于 60 分的是不及格。划分之后 我们设计测试用例,在 优的范围内选择 95 分来测,在 良的范围内选择 88 分来测,在 及格的范围内选择 63 分来测,在 不及格的范围内选择 8 分来测。测试完之后,我们会发现,虽然我们没有看程序的内部结构但是你测的时候打开盒子一看,会发现你选的测试用例 95、88、63、8都是走的不同的路径,故这种方法也是非常科学,应用十分的广泛。
这是等价类划分。它会考虑把所有的数据类进行归总,看哪些是具有代表性的并且属于一类。在同一类里面我们选一个出来测就 OK 了。由于做了等价类划分,所以可以使得咱们整个的覆盖面会要更加全面一些。
边界值分析
边界值分析是指测试的时候测的是边界值。我们讲 90 分以上的是优等,这是包含 90 分的。像我们等价类划分举的这一系列例子,是不能够
发现边界值是否满足条件。你测 95 也好,88也好,63也好,都不能够发现边界值问题,那要怎么办呢?那要测 90 你就会发现问题了,90本来应该分成 优的,结果被分成了良,所以出问题了,这就测出来了。90是属于边界值,它是属于边缘性的值,正好在两种不同的这个等价类之间的边界上。所以边界是一个极其容易发生问题的地方。所以边界值分析强调我们要去注重边界值的测试。
相信大家对等价类和边界值有一定了解。而我们平常应用的过程中,绝大部分时候会把两种结合起来,即划分等价类测试也侧边界值。举个例子,年龄的取值范围是 0 到150,那我们要做边界值分析的测试应该测哪些点呢?要求测试年龄的值是整数值。像这种区间问题,往往边界值只有四个,-1、0、150、151。这四个点分别是 正好在两个端点上面的,略小于端点的、略大于端点的。
错误推导
错误推导,没什么章法可言,他强调的是一种经验。其实我们平常也经常遇到这种情况。比如说你以前做开发,现在了做项目经理或者说做技术总监,你会发现底下的人写出的代码,他们也经过了自己的一些检查测试,但是有些问题难以发现。而到了你手上,你一看随便一测就发现问题了。原因是什么呢?原因就是你有丰富的经验,你知道哪些地方容易产生问题,所以你一测就测出了问题。错误推测法就是这种意思,我们会去推测哪些地方有可能产生问题,就去测这些地方,而不是非常严整的思路去走。这种方式实际上应用也非常多。像微软的庞大的测试团队里面就有一类了,非常另类的人为什么讲他们另类呢?他们有非科班出身,也没有接受过专业的训练,甚至于有些人家庭妇女,没有专业技术找他们来做测试。但是很奇怪的一点,就是往往这类人能够发现一些用其他方法所找不到的问题,就是灵光一闪,觉得哪里有可能有问题,一测果然有问题。这就是错误推测法,往往强调的是一种经验灵感之类的。
因果图
因果图就是由果分析原因的这种方式。即有了一个结果或者一个问题,我们反推分析出它的原因。
白盒测试的测试方法
白盒测试有基本路径测试、循环覆盖测试和逻辑覆盖测试三种测试方法。其中我们主要要了解的是一系列的逻辑覆盖。
A > 0
分成A > 0
和A <= 0
两个真假条件。那 A > 0
这个条件的真假分支都要被覆盖。条件覆盖比判定覆盖又要高一层。软件测试阶段主要分 单元测试、集成测试、确认测试和系统测试。
四种测试之间的先后关系
单元测试和集成测试这两种是可以确定先后关系的,都是先做单元测试再做集成测试。但是确认测试和系统测试这两者先后顺序在不同的资料上面是有不同的讲法。因为对于普通的一般的软件项目而言,是只做到确认测试打止了。但如果说你做的是一个集成项目,会涉及到软硬件还有网络,那往往会有系统测试,就把各个设备连起来一起来测。那这个时候往往又会把系统测试放在集成测试之后,最后再去确认测试。因为确认测试涵盖了验收测试,往往是最后的一个环节。
单元测试
它的关注点是模块级的东西,就是做了一个函数 或者 做了一个过程之类的。那么这一个函数是否达到了我之前的目的,完成了它本身应该完成的职能,这是单元测试要做的事情。所以它会测局部的功能,会测这一个局部的数据结构以及这个模块的相关接口。完成这个测试仅仅只能说明单元测试已经把整个系统中内部模块级的一些东西测试完成了,也就是说现在系统中每个单独的模块是没有问题的。
集成测试
比单元测试再高一个层级是集成测试。所谓集成测试,就是把各个模块联合起来,一起来做测试工作。这个时候测的是什么呢?测的是模块之间的衔接接口,看它们之间进行相互配合的工作会不会有问题。因为单个模块之前测了已经没问题了。做集成测试的时候,毫无疑问需要把模块进行组装,因为你只有把它组装在一起,你才能够测模块之间的衔接。
组装有两种不同的组装形式。
这两种形式都是可以的。但相对来讲增量式的组装工作量会大些,但是增量式组装更稳妥,他发现的问题会全面一些,因为你一次性组装把所有的组装在一起,有些问题可能就难以已暴露出来了。
那么单个模块那如何去测试呢?就没有组装起来之前它是独立的,它按道理来讲要在一个系统里面才能够发挥它的功能。我们可以编写一些驱动模块和桩模块 来配合我单个模块来进行测试,伪装成上级调用模块给你传参数,伪装成这个下级模块给你了,返回相应的参数,这是可以的。该过程看上图右上角。
确认测试
确认测试确认的是需求,看你需求是不是这个就按需求去做的这个软件。具体来讲有内部确认测试、Alpha测试、Beta测试等等。像 Alpha 测试和 Beta 测试是针对产品的,一般项目式的开发是接触不到这一块,现在做了一个产品。 如果说在实验环境开发环境去测试它,这种称为Alpha测试。如果说是由用户在它本地的计算机使用它,这种称为 Beta 测试。 就比如说了我们平常去用 QQ 下载一个它的测试版来用,这就是在做 Beta 测试。我们可以看到了, QQ 有些测试版本的上面会写着 Beta 之类的测试。验收测试了用户来参与进来看看这个东西是否符合他的要求,他愿不愿意来接受这个产品。
系统测试
系统系统测试了包括多个方面,但是它更加偏重于 压力、性能、可靠性 方面的测试,而不是考虑功能性的测试。这么一系列的测试当中,我们主要需要了解 负载测试、强度测试、容量测试,因为这几个非常的接近,都是属于性能这一块的。
冒烟测试
冒烟测试这个名词很有意思,它是怎么来的呢?比如说维修这种燃气管道什么油路的一些管道之类的时候,维修好之后我要测它是否有问题是否维修好,所以就放烟雾进去,看哪个位置冒烟出来。这是一种讲法。另外一种讲法是 维修电路一通电看电路板冒不冒烟短路说明有问题。说到这里,实际上是你在进行了相关的一些操作维护之后,然后来看到有没有问题产生,初步第一次来看会不会有明显的缺陷存在。因为我们之前讲你做了修改之后要做回归测试,回归测试会比较全面,而冒烟测试了就是了最初步的一次检测,仅此而已。(回归测试不属于测试类型,它的做法就是重新测试一遍。)
一个程序结构可以通过抽象为一系列的 点 和 边表现出来的一个图,这个图是一个有向图。
计 算 有 向 图 G 的 环 路 ( 圈 ) 复 杂 度 公 式 为 计算有向图G的环路(圈)复杂度公式为 计算有向图G的环路(圈)复杂度公式为 V ( G ) = m − n + 2 \color{red}{V(G)=m-n+2} V(G)=m−n+2
说 明 : 其 中 V ( G ) 是 有 向 图 G 中 的 环 路 个 数 , m 是 G 中 的 有 向 弧 数 , n 是 G 中 的 节 点 数 。 说明: 其中 V(G) 是有向图 G 中的环路个数, m 是 G 中的有向弧数, n 是 G 中的节点数。 说明:其中V(G)是有向图G中的环路个数,m是G中的有向弧数,n是G中的节点数。
其中值得我们注意的有哪些细节呢?
值得我们注意的细节就是在把一个图转成渐线图的时候,抽象节点的问题 如编号1节点为代表的是一个语句,它要抽象为一个节点,这毫无争议。二是一个判断位置要抽象为一个节点,这也没有什么争议。往往容易产生问题和分歧的是什么呢?是 像这种分叉的位置,原来的程序当中是没有相应语句的,我们要不要把它抽象为一个节点,这导致我们需要注意的问题。 那如何去思考和分析这个问题呢? 很简单的一个原则,你把所有的分叉的地方抽象为节点是可以的,不抽象为节点其实也是可以的。 无论是否把它抽象为节点,它的环路复杂度实际上不会发生改变。以本题为例,我们不把5和6两个分叉抽象为节点,可以怎么写呢?直接把 2 连到 7 这个节点,3也连接到 7 这个节点,4也连接到 7 这一个节点。这最终的结果也是对的。为什么呢?因为这种方案当中我们增加了三条边,但是没有增加任何节点,所以边的数量是三节点数量是0,就是这个局部。我的意思是从 2 到7,3到 7 和 4 到7。而按原来的这种方式会有五条边,然后又产生了两个中间节点。所以其实无论我们把这些分叉的位置是否抽象为一个节点,它们的差值边和点之间的差值是相等的,原来 3和0 相差3,5和2 也相差3。所以你无论是否把它抽象为节点,最终求出来的环路复杂度是一样的。
系统运行与维护当中的软件维护的问题
软件维护是生命周期当中非常重要的一个工作。因为我们从生命周期的阶段来看,维护是其中一个阶段。因为生命周期有立项阶段,有开发阶段,有运行维护阶段,还有了消亡阶段。维护阶段是几个阶段当中周期最长的,所以重要性也非常高。我们忽视了维护阶段的问题,往往会导致你在维护阶段付出更多不必要的成本,维护阶段主要是要确保系统能够正常的运行。在这个过程中,如果说系统不能够正常运行,通过维护能够让他正常运行,这是软件维护的基本思想。
可维护性
可维护性中的“维护”指的是 系统在什么方面有一些缺陷,我们要对系统进行相关的调整,会涉及到编码这个层次的一些事情。所以跟我们日常生活中所讲到的维护有一定的差异。可维护性包括易分析性、易改变性、稳定性以及易测试性。有的地方称为可分析性、可改变性之类的。
易分析性
所谓易分析性就是指 分析源代码能够比较容易地理解和看懂。如果说在编程的过程中这个变量不规范、结构不规范等等有这样的一些问题,那往往易分析性就会比较差,所以编码规范它会影响到代码的可维护性的问题。
易改变性
易改变性就是指 修改一段代码它的容易程度。那为什么会涉及到改变起来难还是容易呢?这就涉及到设计里面的一个问题,就是耦合性的问题。如果说模块与模块之间是松耦合低耦合的,那改变起来了非常的容易。如果说模块之间耦合度很高,那你要改变一个模块的内容就不容易。为什么?因为你改了一个地方可能影响很多的模块,这就不能够随便去改代码。所以易改变性是可维护性的一个方面。这里又反向的要求我们在做软件设计的时候要是松耦合的结构以便于维护。
稳定性
稳定性就是系统随着运行时间的推移,系统是否能够正常的提供基本服务。
易测试性
易测试性就是做了相关的一些调整(如修改BUG)之后要做回归测试,那是测起来方不方便的问题。
维护类型
维护类型有改正性维护、适应性维护、完善性维护和预防性维护。
改正性维护
改正性维护也称为正确性维护。这种维护是非常明确,即它的情况很好界定。它是指的什么情况呢?软件开发出来,它里面总会有瑕疵。虽然我们会做很多的测试,但不可能把所有测试做完之后就把所有 bug 给找出来,这是不现实的。总会有一些 bug 会到用户用的时候才能发现,当用户发现 bug 然后我们就要去修正 bug,这样子所做的工作称为了改正性维护。
适应性维护
适应性维护就是维护系统适应新的环境。比方说我们开发一个软件,原来是运行在 Windows 2000 上面。现在我们要把这一个服务器的操作系统的版本由 Windows 2000 升级到 2008。那这个时候软件有可能由于改变了操作系统环境,所以运行有些不太正常。虽然我们讲操作系统都是兼容以前的操作系统,但是也不可避免的有些小的问题。那这个时候我们针对这些小问题做维护的工作,称为了适应性维护。这是适应操作系统环境,还会有其他的环境,这些环境的隐藏性、隐蔽性会更高。比方说适应数据环境,就是数据环境发生变化要求了应用程序跟着变。这也被归为适应性维护。软件硬件这一块需要去适应的情况,它都属于适应环境的一个适应性维护的一个范畴。
完善性维护
完善性维护主要指的是 在系统的运行过程中发现了很多东西已经发生了改变,我们要去扩充功能和改善现有的性能,要扩充功能加一些新的东西进来,要把性能改的比以前更好,这就是完善性的维护。
预防性维护
预防性维护就是 现在不维护其实不会有问题,但是现在不维护将来可能导致问题,就是做预防性的工作。比方说我们闲时把一些需要进行维护的模块做一些重构,然后做一些文档方面的健全的工作,以后维护起来了就方便了。那这就是属于预防性的维护。
举一个例子来说明一下,就是预防性维护有的时候可能转变成其他方面的维护。
比方说我们以前在 99 年,98年的时候, IT 领域提得非常多的一个词就是千年虫问题,千年虫的问题是怎么导致的呢?当时来讲,为了节省计算机里面的存储空间,在记录年月日的时候,年份只用了两位,比如说1997年记录的是 97,98 年记录的是 98 号,99年还没问题,到 2000 年变成 00 了。而系统种中默认的 00 是 1900 年。因为我们知道像计算机发明出来也才几十年的时间,1946年才发明出来。所以他没有考虑了跨百年的这种情况。好到了那个节骨眼上面,人们就发现一旦 2000 年记录成 00 会有很大的问题,因为年份会相差 100 年之多,对于金融领域呢更是毁灭性的灾难。所以很多机构意识到这个问题,提前就做了升级,提前去做这个升级了就是预防性维护。如果说你后知后觉,等到 2000 年几月份的时候,一查账才发现有错误,因为千年虫问题所导致的,这个时候你再进行维护,那不叫预防性维护,叫改正性维护,因为已经出错了。
这就是这些维护类型。所以什么情况属于什么维护类型要了解清楚。因为像维护这个主题了,不仅仅只是在选择题里面出现,案例分析和论文也是有可能考察这方面知识的。
CMMI是CMM模型的最新版本。所谓 CMM 就是能力成熟度模型,具体来讲成熟度是指软件开发的成熟度,即软件能力成熟度模型。它主要用来衡量软件开发的承包商他的改善软件质量的能力。像其中的成熟度它指的其实是你做事的方法的问题。就好比了我们有一句老话叫做“嘴上无毛,办事不牢”,他是看你这个人成不成熟。如果说你人本身成熟,我认为你做很多事情可能都会比较靠谱。CMM就是基于这样的一种思想发展而来的。但当时来讲 CMM 局限性太大,所以进行了扩充。 CMMI 是属于了能力成熟度模型的一个集成,它分了多个方面,多个侧面,但是有些东西仍然是由 CMM 传承下来的。比如说它阶段的划分和 CMM 就有很接近很相似的地方。
CMMI 它的体系分成 阶段式和连续式。那么这两种模式当中的阶段式和 CMMI 的阶段基本上比较匹配,分五个等级。
下面分别阐述五个等级的基本理念
混乱级
第一级是属于混乱级。混乱级在上图中没有写出来,因为混乱级是不需要评定的,它认为所有机构在没有通过 CMMI 的相应级别的时候 都属于混乱级。
已管理级
第二级是属于已管理级。达到二级水平需要做项目的需求管理、项目计划配置管理、项目的监督与控制,要有合同管理、度量和分析等等这些方面的内容。即这些方面的内容达到了 CMMI 里面相关标准,说明你就已经到了管理级,但这还是属于最为粗浅的层次。这一个层次做到之后,只能说明了你在做相关的一些项目(做过同类项目,比如做过一个房地产项目)的时候,你能够借鉴和传承这种经验,这种重复仅仅只是在项目级,这可以有什么隐患呢?就比如说我在这个公司里面做了一个房地产方面的项目。我在这个项目当中我积累了很多自身的经验。在做同类的项目的时候,我知道如何去应对这种项目,然后哪些地方有可能产生一些什么问题,我可以有效的避免一些问题的发生。有一些经验我可以做到下一个项目去。但是注意仅仅是我来做这个事情,我来领导这个项目会有相应的经验。换一个项目经理来带类似的项目,它是没有这块的经验的。因为经验只在项目这个层面上,它没有上升到企业层面上。所以在上面一个级别三级就考虑的不是项目级的问题,而是组织级的问题。
已定义级
第三级是属于已定义级,属于组织级别的问题。为什么讲第三级是组织级的问题呢?我做这个房地产项目公司会有一些标准的模板规范,一些东西可以给我指导,这些东西称之为组织过程资产,即组织在经验这一块的积累。在做的过程中用到了这些模板、方法工具,等我做完之后,我有了自身的体会,觉得公司里面有些模板其实不够完善,有些模板其实不太好用,那么我就把它们改一改。我会把这些经验把它更新到组织过程资产里面。所以别的项目务经理底做同类项目的时候可以传承到这种经验。然后知识是分显性的和隐性的。那么已定义级考虑想把隐性知识转成显性知识。当然已定义级还有一些特征。如:文档化、标准化,这是它的关键词。
定量管理级
第四级是属于定量管理级。 关键词 量化 就是在这一个级别里面,它会非常强调管理的量化。因为如果说管理不够量化,往往很难把它管好,这是第四级。
优先级
第五等级也最高等级是属于优先级。第四级做好了量化管理,那么五级里面做什么呢?做持续的优化。
1.在考试的时候往往是以选择题的形式出现,它会给你一些描述,问你这个是属于 CMMI 的几级或者说给你一些描述讲 CMMI 几级是有什么样的特征?问你对还是不对,这些需要要区分得开。
2.CMMI 除了阶段式还有连续式。其实个人认为连续式对于很多企业提升自身的能力来讲是一种更好的选择。为什么呢?阶段式规定了很多内容,但是各个企业都有自身的情况,不见得你到这一个等级所有东西都要用上才好,有些东西可能不符合企业现状的一些要求。所以连续式它是列出了很多的过程域,让企业自己来选择,觉得哪些方面需要加强,你就去选这些方面来进行实施就可以了,这是这样的一个情况。所以对于提升过程能力来讲,其实连续式也是有它的优势。但是作为一个标准,你要去应用它,去推广它。阶段式也有它的优势。为什么呢?如果说你没有评级,那么如何去评判呢,比如说招投标过程中你要达到一个什么样的程度才算符合我们的要求了,所以有一个分级标准这是很好的一个东西。所以 CMMI 是这么一种情况。当然 CMMI 从国外流到国内来的时候,已经发生了一些变化,因为国内的整个的大环境会有点急功近利,会比较追求结果,而不注重自身能力的提高。所以导致国内其中很多企业已经通过了 CMMI 比较高的级别,比如说 4 级还是 5 级,但实际上企业能力没跟上来。原因是什么呢?就是为考证而去过这个级的,为了拿这一个证书去拉单。然后去实施了 CMMI 标准和拿到证书之后,他就没有按 CMMI 的一些规则去走,认为 CMMI 是会消耗过多的企业成本。但实际上这是一个误区。 因为CMMI 提出来了,希望以最低的成本来完成项目。为什么大家都觉得会提高成本呢?原因很简单,因为大家对 CMMI 用得不够好,认识不够深入。你要想庞大的一个体系,你就以全新的视角去直接用它。你是新手怎么可能用得好呢,只有你反复去用它,总结规律才能够把它真正用好。用好之后其实是会节省成本的。
3.所以说为什么给大家还讲这些题外话呢?是因为万一你在论文当中会涉及到这些主题的时候,你不但要有理论的支持,而且你可以结合国内行业的现状来做一些自己的评判,这样子就会更加有深度一些。别人会觉得你确实有实践经验,你会有自己的观点,你会知道了哪些东西?现在我们是在按标准做哪些东西了,没有按标准做,而产生的原因又是什么?因为如果说你把一篇文章写得过于完美,考官就会觉得这是不是虚构出来,因为大环境并不支持这么完美的过程,这是这一点。所以我们在学习很多知识的时候,你要从知识的前因后果思考它甚至于用自己的语言去总结它。那这样子的话,你面临案例分析,面临论文这样的一些主题的时候,你也能够轻松应对。
在软件设计师的考试当中,项目管理考的分值比较低,一般只出现在上午题当中,每一次考察基本上也就是那么一两分两三分左右。所以我们不会去整体的介绍项目管理的知识体系,因为这是一个很庞大的体系,项目管理有九大知识领域,按新的标准已经发展到了十大知识领域。我们真正考的其实主要是时间管理的一些概念和计算,以及了风险管理里面的一些相关概念。下面我们就来看到时间管理里面经常考到的题型。
时间管理里面经常考到的是 Gantt图和 PERT图。
Gantt 图
所谓Gantt图是用图的这种形式来展现进度的一个安排情况。它的最为直观的特点是整个图简洁明了,可以从图非常直观的看到整个计划是怎么样的,哪项工作计划在哪一段时间开展,然后实际情况和进度的情况如何,都能够在Gantt图上面非常直观的表达,这是它最大的优势。然而最大的缺点也就在于它过于简单明了,不能够清晰地去表达任务之间的逻辑关系,就是任务之间的先后关系以及两者之间的依赖关系。在Gantt图里面不能够非常直观的给它表达出来,这是它最大的一个缺点。
PERT 图
对于 PERT 图的理解,主要是要了解一些计算的问题。像下方图片中展现的一个 PERT 图,在这个图当中,每一个节点有事件号、最早开始时间和事件持续时间以及最晚开始时间,这些值把它写在上面了。那么这个值就决定了相关的一些参数的值。你比如说整个图当中关键路径是哪一条?我们要知道如何去计算。在图当中每一个节点它的相应的时差,这些东西也应该会计算。所谓关键路径,简单一点来讲就是在整个图当中从开始节点到结束节点最长的那一条路径,它对应的是整个项目的最短的工期。因为在一个项目当中有很多任务可以并行的开展。如果说最耗时的一条路径上的所有任务都完成了,那么按理说其他的活动正常开展也应该都完成了。所以最长的这条路径就对应了整个项目的最短工期。
解
(1)根据分析可知,Gantt图不能清晰地描述各任务之间的依赖关系。故选D。
(2)在这种考题当中,我们要会计算相关的一些量。比如说在这个题当中,要求我们计算事件 6 它的最晚开始时间。那么标准的步骤应该是如何进行呢?应该是先用正推的方式把所有事件的最早开始时间把它求出来,再通过逆推的方式把所有事件的最晚的开始时间给它逆向推导。咱们来看一看这个流程应该是怎么走的。从图中可以看出选择C。
风险是指“损失或伤害的可能性”。这些风险往往要对你的项目产生一些影响才可以算数。如果说它对你的项目并没有影响,是对别人的项目产生的影响,那对于你而言也不算是风险。风险有这么一个特点,就是做风险管理的时候,会关心未来变化以及选择,这是基本概念层次上的东西。
风险可以分成多种类型,有不同的维度来对风险进行划分。其中最为著名的一种分类方法将风险分成 项目风险、技术风险和商业风险。
项目风险
项目风险是指 项目这一个层级的风险。比如说项目组相关的工作没有做好,导致了原来本来是要花 10 万块钱就能够完成的项目结果,但是由于各种原因没有控制好,花到了 15 万亦或是一开始预算没有做准确,实际是要花到 15 万的项目,结果项目计划只计划了 10 万就可以完成,最终导致项目没有完成。
技术风险
技术风险是指 由技术因素所导致的。比如说我们对这个技术不熟悉而采用了这种技术导致了无法控制,或者说这个技术本身是新技术,存在着一些不确定性,或者说技术过于陈旧,导致后期的一些维护更新升级产生的一些问题,这都属于了技术维度的风险。
商业风险
商业风险是指 已经超出了项目组的范畴,是不是项目组内部的一些管理问题所导致的,也不是技术因素导致的,而是这两者之外的一些东西。比如说市场贡献,就是我们项目管理做得不错,技术层面上也把握得很好。但是最终我们发现市场不需要这样的产品,这也有相应的风险。
这些风险主要就是看这个层次维度的问题,往往最好区分的是技术风险。然后再看哪些是控制在项目组之内的,由项目经理可以有一定的主导权来控制的,那往往就是项目风险再超出这个维度的就是商业重险。
在风险这一块,我们经常提到一个词叫做风险曝光度。为什么要有风险曝光度呢?是为了有一个有效的量化方式来衡量一个风险。
比方说我告诉你在项目当中有一个风险,这个风险一旦发生,它导致的损失将是百万的损失,这个损失额度已经很高了,那我们要不要去重点管控它呢?不见得必须需要管控,为什么呢?因为有可能它发生的概率并不是很高,比如说百分之零点五。而如果说另外一个项目当中有一个风险,它可能造成 10 万块的损失。同时它发生了概率的高达80%,和刚才百万元损失的这风险相比,它是缩减到了 1/10 了。但是由于这种风险它发生概率极高,反而我们要更加注意它。所以就提出风险曝光度,我们会用风险发生之后造成的损失乘以它发生的概率得到风险曝光度。
用风险曝光度来衡量一个风险,我们是应该重点管控还是可以不怎么管它。 因为你像这一个十万这个风险,虽然相对于百万的风险,它发生之后了损失要小一些。但是由于发生概率高,所以风险曝光度乘出来之后将是 8 万。而百万的这个风险由于它的概率很低,0.5%,所以乘出来只有5000。所以横向一对比,我们就会发现这个是我们要重点管控的风险。所以其实风险曝光度这个值是通过这种方式来使用它的。
软件变更控制是变更管理的重要内容,要有效进行变更控制,需要借助配置数据库和基线的概念。配置数据库一般包括开发库、受控库和产品库。