【IT168 技术文章】
如果您的基于 RUP 的项目比较成功,您怎样知道您的团队所使用的 RUP 是这个项目成功的原因呢?这里 Gary Pollice 提出了一个可以科学地度量几个迭代开发技术的方法。
在过去两年内我曾不止一次地说过“软件工程”的说法是不恰当的,我们实际上操作的是软件开发。 1 Philippe Kruchtenn 和其它人说区分软件和其它工程学科主要有两点:其一是每个软件开发项目都是唯一的,其二是没有应用于所有软件的基本定律。这难道意味着我们应该放弃所有寻找基本定律的希望,以及开发一个更像工程学的方法来开发软件吗?
完全不是。软件仍然是一个年轻的学科,在我们前面仍然有大量基础和应用研究用于发现它的基本定律。我们同样需要明白软件开发的什么部分以及在什么情况下需要遵守更严格的方法。科学的方法需要我们观测现象(与软件相关的),明确表达假设,用那些假设来预言未来的行为,并验证我们的假设是否是正确的。
如果您在您的软件开发实践中应用一个过程,您已经应用了这个科学的方法,至少间接地使用了。让我解释一下我表达的意思。
首先,您要观察您的组织的或者开发团队的效力。当您看到他们是高效的,但是您认为他们还可以更加高效,您开始思考变化这个过程也许有所帮助。您观察与软件相关的现象并开始明确表达出一个假设。
接下来,您要决定运用什么过程。您在这个阶段中真正在做什么,这是以先前项目的观察和经验为基础来决定您的过程选择的。
您选择了您的过程,因为您想要提高您项目的成功机率。因此您必须有效地阐明关于这个过程功效的假设。
理想情况下,您为您的项目或者团队来配置过程。当您为您的项目选择和配置这个过程时同样要间接地预知您的项目/过程的未来。
现在您必须收集数据并用它来证实您的假设。如果这个假设与观察到的现象不相匹配,您必须修订您的假设。有也必须能够执行预言并且反复验证,以此来说明这个假设已经并证实了,等等。可重复的结果在这个科学的方法中是十分重要的。
我想详细考虑一下最后这个步骤——收集数据来验证这个过程的益处。
让我们设想您确定,以适合于您的组织的任何一种方式,一个项目是成功的。显然,您假定您所选择的过程是这个项目成功的部分原因。您向您的组织发出了关于您成功的消息,并激励其他人为他们的项目使用您的过程配置,如果他们有类似的项目。您有数据——从成功的项目中收集的——来支持您的主张:这个过程(选择它是明智的)是形成这个成功的原因。可靠的推理,不是吗?
第二天,您收到执行委员会发来的通知,让您亲自去证实您的主张。您收集您的数据,并给他们一个关于您所收集数据的极好的幻灯片——每一千行代码中的缺陷率,团队的生产力等等——非常清楚地显示了这个项目是绝对成功的。您重复您的主张说,在这个成功中起作用的因素是您选择了正确过程。
关于这一点,这个主要执行审查人员盯着您问了您一个您不知所措的问题。“您的团队都用这个过程吗?”您脑海里出现的唯一的回答是“当然,他们告诉我他们都用的,”以及“他们必须使用这个过程因为这个项目是成功的。”您意识到任何一个都不能充分回答这个问题。即使您做了大部分收集项目数据和度量项目的几个属性的工作,但是您没有收集任何关于这个过程使用情况的数据。
的确,这个团队的成员告诉您他们使用了这个过程,他们真诚地相信他们的确这样做了。但是那并不意味着他们真的这样做了,尤其是在这个项目的初始阶段,您所选择的这个过程对于这个组织来说是一个新的过程。他们也许在构建系统方面更加小心,只是因为他们知道您将在他们的执行中收集数据。这只是山楂效应(Hawthorne Effect)的一个例子。 2 因此留下的疑问是:您怎样知道去度量什么?
度量 Rational 统一过程(Rational Unified Process)
当您执行您的实验时,您必须收集关于您所使用的这个过程的数据和实验结果。如果您大力宣扬您的主张,您必须提供足够的信息证明这个实验能够被其他研究人员或者研究团队来重复试验。对这个实验来说,有相同的结果就是正确的。问题又出现了,因为我们经常不知道去捕捉什么数据,在捕捉数据以后,怎样来分析它。带着确定您的团队事实上多大程度上使用了这个过程的目的,这篇文章的剩下部分提出了几个度量您的过程的方法。如果您可以搜集这些数据,那么您可以确定那些技术在您的环境中是最有效的。
Rational 统一过程?,或者 RUP?,包含了软件开发各个方面的指导。为了成功地使用它,您必须创建一个适合您的项目的过程配置。绝大多数RUP配置是建立在一系列非常好的实践和其它已经在不同类型的软件上表明是有效的技术上的。 3
我们的方法十分简单。我们将选择一个练习来观察几个度量这团队事实上采取这个实践的情况的方法。我们将使用 Goal Question Method (GQM)技术 4 。 我们的目的显而易见。我们想知道,如果这个团队实际上使用了这个过程,接下来我们的决定将取决于我们将要问的一些问题,这些问题的答案将有助于我们决定能否实现目标。最后,我们将决定使用何种度量方法来回答这些问题。
难道我们不能简单地问这些团队成员他们是否使用了这个过程吗?您可以,我们也能够这样问,而且也应该这样问,但是这些回答将会是更加主观的而并不客观。事实上,人们时常会告诉您您想知道的他们在想什么或者他们相信什么是真的,无论那是真还是假。例如,如果您问别人他们怎样转到自行车的左边去,他们会告诉您仅仅将车把转到左边自行车就自然而然地转到左边了。但是如果他们想一下这个问题,他们将会告诉您他们也可以将自己的身子倾斜到左边。如果他们十分谨慎地叙述他们自己将自行车转到左边,事实上,他们做的第一件事是将自行车车把转到右边。 这个小小的移动没有使他们转到自行车的左边,而然后把自行车车把转到左边来完成这个转向。也就是说,他们需要的是经验主义的数据——基于对这个团队成员行为的观察或者我们通过其它方法获取的数据——这些数据将使我们能够确定他们是否使用了这个过程以及使用的程度。
我们将看看RUP三个基本的区域:需求管理,迭代开发和测试。有太多的区域或者区域合并需要我们去尝试并实施。在这篇文章中我们目的是,为了更好地理解我们的过程,我们怎样选择一个技巧或者方法,并在其中应用一定的度量方法。
需求管理
绝大多数RUP配置是以用例为中心的。这意味着对于功能性的需求(关于系统必须实际上做什么的需求),我们应当使用用例来描述系统的行为。什么是我们将要问的问题来确认这个团队是否真正应用了用例并从功能性的观点来描述系统。 5 出现在我头脑中的其中一个问题是:"在代码中实现的所有特性 6 都在这些用例中描述到了吗?"这似乎是非常的直截了当。如果我们能够识别出实现的这些特性,我们可以将它们与用例中描述的特征进行比较。最大的困难是确定事实上被实现的这些特性。如果我们可以这样做,我们就可以计算下面用例的度量效果:
假定 F i 是所有被实现特性的数量, F s 是既被实现并且又被特定指定的特性的数量。如果您用100乘以U ,您将得到一个在您的用例中被实现了并实际上也被特定的特性的百分数
具有代表性的是,在您的用例中您所特定的特性将会比您实际上实现的要多。为了及时交付一个可使用的产品,您在管理这个项目范围时将会删除一些特性。因此 F s必须仅仅包含那些在您特定的并实际实现的特性。现在度量数据U的值在0和1之间。如果您完全使用用例作为说明功能性需求的方法,您得到的值将会是1。当您实现了您的用例中没有特定的一些特性,这个 U值将会减小。
度量数据的唯一问题是,我们如何才能获得 F s 和 F i? 7 首先,将用例分散到离散的特性中去, F s,并不是很难得到的。 我们能够检查用例,并且通常我们同意他们特定的特性。我们可以用场景作为我们度量的一个单元,或者将描述系统行为的每一个步骤作为一个特性。但是更困难的部分是计算 F i。 如果您仅仅测试特定的特性,您可以确定他们是否全部都被实现了,但是您不能确定您的开发人员是否实现了那些并没特定指明的特性。
让我们提出一些估计 F i值的方法。一个极好但耗时的确定实现的编码是否就这个用例中特定指明的方法是,对检入到项目中的所有编码实行检查。这个检查与您寻找特别的东西有点不同。在这个情况下,您应该尽力的识别已经被代码实现的特定特性,然后将这些特性映射到用例图。
第二个确定没有被特定指明但是已经被实现了的特性的方法是,让您的测试人员在软件上执行探测测试。 探测测试是 Cem Kaner和James 发明的技术。 8 。使用这个技术,测试人员不必以一系列测试用例开始,也不用其它预定义的测试脚本。测试人员仅仅需要启动探测软件,看它能做什么。测试人员试着确定产品允许他做什么。您可以向测试人员提供用例,让他们以用例为向导来探测这个产品。当测试人员探测到用例中所没有的情况,他就把它记录下来作为实现了但是没有被特定指明的特性。
我首选的找出 F i值的方法是一个混和方法:
首先,在严格基于用例的基础上运行您的验收试验。这些在下一步前必须都通过。
其次,使用代码覆盖工具运行您的验收试验。被执行的代码表示了这是实现所有F s所需要的代码。
最后,检查您测试中的那些没有实现的代码。这些代码要么是实现了例外条件,要么是实现了但没特性指明的特性。理想的情况是,这的代码数量很少,所以也很容易识别出那些未特定指明的特性。
以上的度量数据,U,告诉我们开发人员实现的是否就是特定指明的。但是一个值(特定的)小于1,就意味着这个开发人员没有很好地完成采取用例驱动开发的工作吗?也许是在项目执行时用例发生的变化,但是团队成员没有尽力去更新这个用例。也许他们依靠一种更加不正式的方法来表达一个新的场景和用例。这将表明实际的过程使用了已经编写好的、受控的用例来作为一个起始点——这并不一定是一种坏的情形,但是与计划好的过程有所不同。
当您在您的测试中检查到并没执行的代码时,如果需求发生了变化,但没有正式地被更新,那么最好的办法是让一个人来负责确确认需求。事实上,一个快速检察它是否是一个问题的方法是,查看您的用例工件的版本控制日志。如果他们在最初的版本之后没有任何变化,您可以清楚地确定这个团队没有保持需求更新,至少在用例中以一种持久的形式使他们保持更新。
迭代开发
任何基于RUP的裁剪的过程,除了大多数小的项目之外,都包含了迭代开发的向导,在迭代过程中软件是按照迭代的增量式地构建的。通常,最开始的两次迭代都关注于精化关键需求和开发一个可执行的架构。 9 在这些迭代之后,如果还没有最终完成项目,每个迭代都应当产生一个可运行的系统。
要看我们的团队实际上是否执行了迭代开发,我们应该问什么问题呢?
迭代的特征之一是严格控制时间。 那就是在迭代的开始您可以决定它的终止日期。当这个日期到达时,迭代就结束了。您考虑的仅仅是全部的特性或者您使用什么作为迭代的可交付工件来度量过程。如果一种特性差不多已经完成,但是正好还需要更多一点的工作,但它并不是迭代可交付工件的一部分——也就是说,您不用决定延长迭代的终止日期来适应这个特性。因此您可以这样问一个问题: "迭代都是有严格时间控制的吗?" 就是说,在迭代的开始它的终止日期就已经确定好了吗?这是迭代的实际的终止日期吗?
我们可以用下面的方程式为这个项目的迭代持续度定义一个度量:
假定I m是终止日期已经被修正了的迭代的次数(在迭代开始以后), I t是迭代的总次数。 如果这个团队严格遵守了迭代的开发过程,我将得到的值是0。在这个可能值范围的另一个端点,这个团队在每次迭代开始后,修改了 所有迭代的终止日期。在这种情况下,我将得到的I值是1。 不考虑您是怎样维持您的项目计划的,这个度量是十分容易计算的。您所要跟踪的是您的计划中日期的变化。
严格时间控制的迭代是有必要的,但是要证明这个团队执行了迭代开发,理由还是不够充分。我们还需要知道什么呢?另一个我们可能要问的问题是: "在每次迭代结束的时候都会产生一个可运行的软件吗?" 您通过计算产生的可运行的软件来确定您的答案。如果您在每次迭代结束时都将软件配置存档,通常是通过在您的版本控制系统中对配置进行标记以及在必要的时候重新构建,这样您可以在很短的时间内验证这个软件的运行情况。
一旦您有了每次迭代的这个信息,您可以计算一个运行软件的比值,W,如下所示:
假定Iw 是产生可运行软件的迭代数值, I t 是总的迭代数,跟前面的一样。当可执行的构架是被第一次产生或者当第一个可执行的软件开始出现时,您可以选择调整 I t 为总的迭代数。这样可以使W的值在0和1之间变化,包括0和1。W 的值越大表明采用迭代开发的程度越高。
测试实践
测试是您可以在执行活动的正常过程中应用这些度量的区域。您可以容易地跟踪缺陷发现率和修复率,测试覆盖统计,等等。您应该能够开发一些度量来帮助您决定在您的整个过程中,您的实际测试过程是否是已被定义的。
RUP有大量的活动和工件可供团队来选择。如果您实行了迭代的增量开发,您的测试应该反应出开发的状况。这就是说,您应该希望看到第一次迭代产生的测试用例和测试工件,然后随着系统的增量而增加。
让我们假设您的团队的测试过程计划表明,开发人员所提供的单元测试是针对他们开发的每一个特性的;测试人员将根据需求开发一系列集成和验收测试,它将测试每次迭代中的运行软件。再一次,您需要找出这样的问题,它的回答可以帮助您确定您的团队实际上是否是根据这个过程进行测试工作的。对我们的例子来说,我们仅仅需要考虑一个问题: "开发人员会单个测试他们的编码吗?" 如果您安装了自动化测试工具,那么所有的单元测试可以从一个简单的命令开始运行,您就可以很容易地回答这个问题。更值得一提的是,您可以设置您的配置管理系统在任何检入动作发生时执行测试。
您怎么知道所有的功能都通过了单元测试呢?这个判定是相当困难的。您可以要求每一行编码都执行单元测试,但是在有些情况下是达不到预期的目标的——也就是说,花更多的精力来开发测试,与这个编码所带来的损失比较起来并不值得。我们知道,我们没有足够的时间来做所有的事情,因此我们必须根据这个行为的回报来进行优先级选择。无论什么原因,您确定单元测试的覆盖率达到100%是不恰当的。在这儿脑子里形成的度量是单元测试的编码覆盖率。在每次迭代或者几次迭代结束时我们可以获得数据。我们所寻找的是数据的趋势。我们想知道单元测试在整个项目中是否自始至终都在执行。
让我们假定我们有12个迭代数据值。图一中的曲线图表明三个项目的数据。
图1:三个项目中12次迭代的测试覆盖率
从这个数据中,我们可以推断项目2(图1中急剧下滑的曲线)很明显没有遵循单元测试的过程向导。项目1和项目3似乎很好地完成了这项工作。如果我们认为这很重要,而且有日常数据并有一个更好的图表,我们可以对它进行更深地研究。图2中的曲线图表明了两个项目中的每天单元测试的数据,如果根据图1中的X和Y轴看,他们看起来是十分一致的,但是根据有更多坐标点的图2来看他们却是十分不同的。我们仅仅看了四次迭代,假定我们有每周的迭代(一周按5天计算)。在这种情况下,项目2在执行编码时并没有花时间来开发测试,但是在迭代结束时花了时间来编写测试。如果这两个项目在成功之处有所不同——比如,如果项目2比项目1有更差的质量——这提供了一个这样的暗示:您在追求更高质量时要进行测试。
图2:在这种情况下,项目2的团队在执行编码时并没有花时间来开发测试,但是在迭代结束时花了时间来编写测试。
总结
在这篇文章中,我已经为一些基本练习提出了一些的度量方法。但是我认为这篇文章可以帮助您来确定哪些个度量方法更合适您的项目,您因此能够开发出一个更合理、更容易计算的度量方法。如果您仅仅计划为一两个项目获取度量,那就不必要用这种方法来费心。它不能为您做出有效的推论提供足够的信息。然而,如果您开始为您所有项目获取一些关键度量,您可以逐渐使之增长成为一个有价值信息的数据库,根据它您可以应用统计分析。您不需要大量的数据就可以开始分析并详细阐述关于哪些是有效的哪些不是。您可以,然而需要用一种客观一致的方法来搜集数据。
管理您的过程并明白它对您的组织是否有效与用科学的方法来进行实践是相似的。您的目的是能够选择并形成一套正确的能有效支持您的项目的技术。您应该为关键的实践识别出一组度量数据,收集必要的数据来确定这个项目团队是否执行了这个实践。当您获得了经验,增长了度量的数据,您就能够根据经验的观察来调整您的过程。您很快就能够信心百倍地陈述您的项目团队中哪些执行了过程,哪些没有执行过程。