本文描述了基于用例进行评估的一个框架。为了使描述更加具体,本文为框架的参数选择了一些值,尽管这些值有待于论证,但它们并不总是错误的。像往常一样,随着数据的搜集,这种估计应该根据实际情况和重新估计的参数值进行测试。这种框架对于不同种类的系统考虑了用例层次、规模和复杂度等思想,并且不再采取细粒度的功能分解。为减轻计算的负担,对于诸如
Estimate Professional 这样的工具,可以构建一个前端,从而提供一种基于用例的规模输入的不同的方法。
直观上看起来似乎根据用例模型的特征,可以对开发工作所需的规模和工作量进行估计。毕竟,用例模型捕获了功能性需求,那么难道不应该有基于等价于功能点的用例吗?这里存在许多困难:
- 有许多不同的用例规格样式和形式,很难定义一个度量标准,例如,某人可能希望能够度量用例的长度;
- 用例应该代表外部参与者对于系统的观点,因此,500,000 sloc 系统的用例就与 5,000
sloc 子系统的用例在完全不同的层次上(Cockburn 97 讨论了层次和目标的概念);
- 用例可能在复杂性方面不同,编写时是显式的,实现时又是隐式的。
- 用例应该从参与者的角度来描述行为,但是这可能相当复杂,特别是当系统具有状态时(绝大多数情况是这样的)。所以描述这种行为需要系统的模型(在实现它们之前)。当试图捕获行为本质时,这将导致过多的功能分解层次和细节。
所以,为了能够进行评估,是否有必要实现一些种类的用例呢?或许是对于直接根据用例进行估计的期望过高,并且在功能点和用例点的概念之间直接划等号对我们产生了误导。功能点数量的计算无论如何都需要一个系统模型。从用例描述中派生的功能点需要达到与用例表达一致的层次,并且只有达到该层次时,我们才能够对功能点的数量有信心。Fetcke
97 描述了一种从用例到功能点的映射,但是,用例的层次必须适当,这样映射才能有效。其他的方法使用基于类或基于对象的度量标准作为来源,PRICE
Object Points 就是一个这样的例子(Minkiewicz 96)。
在描述和形式化用例方面的工作相当完备――Hurlbut 97 对此有很好的概括。而从用例中派生估计的度量标准却寥寥无几。Graham
95 和 Graham 98 中包含了对于用例相当严格的批评(但是我并不完全理解为什么他认为他的想法和用例是大相径庭的),并且建议将"任务场景"作为克服用例问题的方法――包括它们的变化的长度和复杂度。Graham
的"原子任务场景"是"任务点"度量收集的基础。原子任务场景存在的问题是它处于低层:根据
Graham的说法,它最理想的情况是作为一个单一的句子,并且如果仅仅使用本领域的术语那么不能更进一步进行分解。Graham
的"根任务"包含一个或者更多的原子任务场景,并且每一个根任务"在初始化计划的类中,与一个系统操作正好对应"
(Graham 98)。这些根任务在我看来似乎非常像低层用例,并且这些原子任务场景如同是这样的用例中的步骤。然而,这种层次方面的问题仍然没有解决。
Karner(Karner 93)、Major(Major 98)、Armour,以及Catherwood(Armour
96)和 Thomson(Thomson 94)完成了其他方面的工作。Karner 的论文中指出了计算用例点的一种方法,但是该方法仍然假设这些用例是以一种通过类可以实现的方式来表达的(例如,在一种更合适的细节层次上而不是子系统上)。
那么,我们应该不使用用例来估计而依赖于所实现的分析和设计吗?这个问题妨碍了做出估计的能力,并且无法满足已经采取该技术的项目管理者的要求――需要尽早估计并且不得不使用其他方法。对于项目管理者来说,为了做项目规划,最好能够尽早获得评估,然后反复对其进行精化,而不是拖延评估并且毫无头绪地进行工作。
本文中描述了一个框架,在该框架中可以使用任何层次的用例来形成工作量估计。为了展示这些观点,本文描述了一些简单的规范结构,这些结构具有相关的一定实践基础上的维度和规模。本文中大多是大胆的(或者应该说缺乏根据的)推测,因为我没有其他的方法来解决这个领域中缺少的工作和数据的问题。本文引用了"互连系统构成的系统"思想。
接下来,我将暂时撇开主题来介绍一些将我引入本文主题的一些背景想法。
功能分解的思想对于软件开发领域中的许多人来说像一个"诅咒"。我对功能分解的体验更是其中的极端(在一个很大的数据流图中有
3000 个原始转换,五层或者六层深,在除了基础设施层外没有使用任何构架的思想的情况下完成),让我感到异常悲观。在该用例中存在的问题不仅仅与功能分解思想有关,还和下面这种想法有关,即直到分解到功能的原始层次才描述一个进程。在该层次上规格说明的长度应该少于一页。
所得到的结果难以理解――所需要的更高层次的行为如何从这些原始转换中显现出来,这一点很难搞清楚。另外,功能结构如何映射到物理结构上来满足性能和其他质量方面的要求并不是特别明显。这就产生了一种自相矛盾情况,我们一直进行分解直到达到了能够"解决问题"(原始层次)的那一层,但是,这些原始层是否能够实际上协同工作以满足更高层的目标却并不清楚或者可以被证明。没有办法以这种方式来考虑非功能性需求。从总体上讲,构架和基础设施(通讯,操作系统等等)都应该随着分解而不断演进,并且每一次分解都应该对其它分解产生影响。
那么 Bauhaus 规则"形式服从功能"又如何呢? 有许多好的设计源自功能主义方法,但也不乏一些不良设计。例如,随处可见的平屋顶结构的使用。如果您只关心屋顶的功能,并且将其完全设计为居民所需的一个房盖,那么至少在一些特定的领域中是不能够令人满意的
。这种屋顶很难防水,并且容易积雪。
现在这些问题可以解决了,但是在一个更大的范围内而不是在您已经选择的不同设计中。尽管看上去有些过时,但是形式还是应该服从所有的功能和非功能性需求,以及后续的美学要求。架构师面对的问题经常是非功能性需求经常表达模糊,并且过多的依赖于架构师的"事情就应该是这样"的经验。因此如果功能分解仅仅用来驱动构架(即分解产生了几个向下的层次并且功能的原始层次与"模块"一一匹配)和定义其接口,那么将一无是处。
像这样的考虑使我确信,在完成构架工作之前,将用例向下分解到标准化的水平(这可以通过类的协作来实现),这没有任何意义。对于一定规模的系统而言,这些分解确实必要,(参见
Jacobson 97)但是分解的标准和实施过程至关重要――特别是当功能分解不是足够好的时候。
系统工程师完成功能分析、功能分解和功能分配工作(当综合一项设计时),但是功能并不是系统构架的唯一驱动因素,一个专门的工程师团队就能够在评估不同的设计方面做出贡献。IEEE
Std 1220,系统工程过程的应用和管理标准(Standard for Application and
Management of the Systems Engineering Process)在 6.3
节中描述了功能分解的使用,功能分析(Functional Analysis)在 6.3.1 节,功能分解(Functional
Decomposition),和系统产品解决方案等综合在 6.5 节中。6.5.1 节包含了一些特别有趣的内容,分组(Group)功能和分配(Allocate)功能,6.5.2
节是物理解决方案的选择(Physical Solution Alternatives)。在 6.3.1
节中指出,分解是用来清晰地理解系统必须完成哪些功能,并且一般情况下一层分解就足够了。
注意,功能分解的目的并不是为系统定型(由综合工作来来完成定型),而是理解和沟通系统必须完成什么――功能模型是能够完成这些的好的方式。在综合中,子功能首先被分配给解决方案的结构,然后评估这个解决方案――必须考虑所有的需求。这种方法和多层功能分解之间的不同之处在于:在每一层都试图描绘所要求的行为,并且在决定是否该行为在下一层需要被精化,以及分配到更低层的组件中之前,找到一种解决方案来实现它
。
从中可以得出一个结论就是,在任何层次上使用数百个用例来描述行为是没有必要的。可能很少量的外部用例(和相关场景)就能够恰当地覆盖所要描述的对象(系统、子系统、类)的行为。我应该讲一下我所说的外部用例是指什么。举一个由子系统组成的系统例子,这些子系统又由类组成。描述系统及其参与者的用例,我称之为外部用例。子系统或许有它们自己的用例――它们对于系统来说是内部用例,但是对于子系统来说是外部用例。最终用来构建一个庞大系统(大于
100 万行代码)的外部用例和内部用例的总数,可能数以百计,因为这样规模的系统将包含其它系统,或者至少包含子系统。
用例的数量
在 IBM Rational 中,我们认为用例的数量应该很小(10-50 个),并且认识到大量(超过100
个)的用例表明可能需要进行功能分解,在功能分解中用例对于参与者毫无价值。然而,在实际项目中我们仍然能够发现大量的用例,并不总是"糟糕的",至少在层次上是全面的。例如,在
Rational 内部的电子邮件中,作者引用了一个 Ericsson 例子:
- Ericsson,对大部分的新一代电话交换机的建模,估计要多于 600 个人年(最多,3 到400
个开发人员),200 个用例(使用不止一层用例,请参考"互连系统构成的系统")对于一个超过
600 人年(这有多大呢?150万行 C++ 代码吗?)的系统,恐怕用例分析会限于子系统上面的某一层上(也就是说,如果一个人定义了一个
7000 到 10000 行代码的子系统),否则用例的数量还会增加。
因此,我仍然强调这种观点即少量的外部用例是适合的。为了匹配我曾经建议的结构和规格,我断言 10 个外部用例,每个用例带有
30 个相关场景 ,这对于描述行为是合适的 。如果实际中用例的数量超过了 10 个,并且确实是外部用例,那么它们所描述的系统要比相应的规范系统具有更大规模。在下文中我将提供一些支持理由来说明这些数字是合理的。
结构分层
建议的结构分层如下:
4 - 多个系统组成的系统
3 - 系统
2 - 子系统组
1 - 子系统
0 - 类
类和子系统在 UML 中定义为;在 UML 中更大的聚合是子系统(包含子系统),为了更简单的进行描述,我进行了不同的命名。对于那些知道
2167 和 498 军方标准(称子系统为 CSC,称类为 CSU)中的术语的人来说,子系统组(subsystemGroup)的规模用
CSCI -来表示。我记得,经过 2167 天的关于 Ada 的结构应该映射到哪一层次的争论后,尘埃落定,Ada
包通常映射为 CSU。我并不建议系统必须严格的遵循这种层次结构,还将存在层次之间的混合,这种层次结构使我能够更好地了解规模对于每个用例工作量的影响。
在每一层上都会有用例(尽管对于单个的类可能不是这样),但并不是单纯的大量细节堆砌 ,而是用例针对那个层上的每个组件(例如子系统、子系统组,等等)。在上文中我曾断言对于每一层的每一个组件都有
10 个用例――如果用例的描述平均是 10 页,那么将会给出一个潜在的、大约 100 页长度的说明文档(还要加上类似的或者少一些的关于非系统性需求的相应说明),这是
Stevens 98 提倡的数字,并且和Royce98推荐的数字很接近。但是为什么是 10 个用例呢?为了得出这个数字,基于对每一个子系统的类的数量、类的规模、操作规模等等我认为的合理的规模,我进行了自下向上的推理。这些和其他假设共同搜集在下表中供大家引用。
我没有大量的经验数据-贯穿文中的是琐碎的、分散的数据,Lorentz 94 和 Henderson-Sellers
96 有一些数据,我也有一些在澳大利亚的项目中得出的数据,主要是在军用航空航空领域。任何情况下,在这个阶段,将框架或多或少的定位到合适的位置是非常重要的。
这里我应该指出的是,我曾经使用代码行来度量组件的大小,但许多人不喜欢这种度量。这些是 C++(或者相同层次的语言)代码行,所以,要回到功能点非常容易。
在容器中的类的数目和能表达的行为的丰富性之间肯定有许多关系。我选择了 8 个类/子系统 ,8 个子系统/子系统组,8
个子系统组/子系统,等等。那么为什么是 8 个呢?
1. 它在 7 或-2 之间;
2. 由于每个类有 850 slocs(每 70 slocs 有 12 个操作)的 C++代码,它得出了一个子系统的规模是
7000 slocs-一个可以由小的团队(3-7人)在 4-9 个月就能够交付的功能/代码的程序块,其中系统的迭代长度就该调整到
30 万-100 万slocs (RUP 99) 的范围内 。
那么,多少用例能够表达八个类的行为(外部的)?,哪些是属于子系统的并且已经被定位在子系统中了?决定丰富性的原因不仅仅是用例的数量,还有每个用例的场景数量。现在,并没有多少方法来指导场景/用例扩展――在Booch
98中,Grady Booch 指出"存在一个从用例到场景的"膨胀系统",一个复杂度适当的系统中可能有几十个用于捕获系统行为的用例,每个用例可能具有几十个场景….",Bruce
Powel Douglass 在 Douglass 99 中指出,"….为了详细描述用例需要很多场景,通常需要1打到几打"。我选择了
30 个场景/用例――这处于"几打"的较低的一边,但是 Rechtin(在 Rechtin
91中)指出,工程师能够处理 5 到 10 个互相作用的变量(对于这个变量,我解释为互相协作的 5 到
10 个类)并且 10 到 50 种交互(我解释为场景)。以这种方式解释,多个用例即为该变量空间的多个实例。
因此,10 个用例,每个用例 30 个场景,也就是说一共 300 个场景(后面将导致大约 300 个测试用例)对于覆盖
8 个类的有意义的行为来说已经足够了。是否有其他的迹象表明这是个合理的数字呢?如果应用 Pareto 的
80-20 规则,那么20%的类将表达80%的功能,同样,80% 的功能将被每个类中20%的操作来表达。让我们保守的说,我们需要20%的类(等)来达到75%的功能并且通过这点来构建一个
Pareto 分布图。(图 1)
图 1: 一个 Pareto 式样的分布图
如果我们想要描述 80% 的系统行为,并且将 Pareto 规则应用到类、操作和场景数量方面,那么对于每一者都需要描述其行为的
93%(0.933= 0.8)--也就是对于每一个都需要 50%,例如,4 个类和 5 个操作(= (12
- 2 构建器/析构器)/2)。节点树的不同分叉的数量可能达到数千个(其中节点树用来代表4个类及每个类5个操作的执行模式)。我为每个节点创建了
1 到 3 个链接,假设在顶层有 10 个操作(接口操作)的层次结构,并且形成了一个三层的树。这将会有
1000 条路径或者场景。所以,500 个场景将会得到 93% 的覆盖。使用 300 个场景(用相同的假定)我们可以得到
73% 的覆盖。根据一个选定的算法,可以对这个树进行修剪,从而删除冗余的行为说明,甚至更少的数量就完全可以符合要求。
达到该目的的另一个方法就是研究一下对于 7000 slocs 的 C++代码需要多少测试用例(从场景派生而来)。这些测试用例不受单元测试层次的制约,并且在
Jones 91 和 Boeing 777 项目中有许多证据表明这个数字是安全的,至少它符合实践。这些来源表明在
250 到 280 之间是合适的。在一个完全不同的层次上,加拿大自动空中交通系统(Canadian Automated
Air Traffic System ,CAATS)项目使用了 200 项系统测试(我私下里获悉的)。
用例的规模
用例应该具有多大规模呢?是否应该足够大以及表达足够的细节才能表达所需要的行为--这取决于与系统有关的用例复杂性、内部用例和外部用例。--这里我们就应该描述多少系统的内部动作来深入探讨一下这个问题。很明显,从外部行为描述来构建系统,要求将输出与输入关联起来。例如,如果行为对历史记录敏感并且很复杂,那么在没有系统内部的一些概念模型及行为的动作时,就很难描述它。注意,没有必要描述一个系统是如何从内部构建的--任何满足非功能性需求和匹配模型行为的设计就能够满足要求。
UML 1.3 中提供的定义是:"用例【类】:一个系统可以执行的动作(包括变体)序列的说明,其中这些动作与系统参与者进行交互"。对复杂的行为的内部动作,可能合理的采用这个定义也可以在实现阶段再进行定义――这对于最终用户来说是个更远的步骤。业务规则也应该纳入到用例中以便约束参与者的行为(例如,在一个ATM系统中,银行需要有一条规则:在一次交易中,提取的金额不能超过
500 美元,无论账号中的余额为多少)。
根据这种解释,事件的用例流描述的页数可以为 2-20 。从计算的角度上看,具有简单行为的系统显然不需要冗长的描述。或许我们可以认为简单的商务系统通常用
2 到 10 页来描述,平均为 5 页。对于更复杂的系统来说,业务系统和科学系统在 6 到 15 页之间,平均为
9 页。复杂的命令和控制系统在 8 到 20 页之间,平均为 12 页(这些比率反映了相同规模系统的工作量与类型之间的非线性关系),尽管我没有数据来支持这种观点。更富有表达力和描述性的形式(例如状态机或者活动图)可能需要更少的篇幅--我们仍旧倾向于加强文本,所以此处不讨论其他形式,毕竟相关资料很少或者根本没有。
与上述规模有系统差异的开发应该运用乘法规则来计算在这些假设基础上得出的每个用例的小时数(我建议增加一个
COCOMO -样式的成本驱动,该驱动是系统类型的(简单的业务类型、更复杂的类型、命令及控制类型等等)的观察到的平均规模或建议的平均规模。
用例规模的另一个方面是场景的数量。例如,一个 5 页长的用例可能是一个具有很多路径的复杂结构。再一次重申,需要将场景的数量以及这个比例估计为
30(这是我对于每个用例的场景数的初步估计),将其作为成本的驱动因素。
得到的结果是,我们假设基于大约长度为 100 页说明的用例,对于任何给定层次的外部说明及补充说明来说,都是足够的。范围是
20 到 200 页之间(这些界限是模糊的)。注意,一个系统(子系统组)在最低的层次上的总数是 3-15
页/ ksloc(简单的业务系统)到 12-30 页/ ksloc(复杂的命令和控制系统)。这或许能够解释
Royce 98 表中的 14-9 和实际项目之间明显的矛盾之处,前者的工件所占用的篇幅非常少,而实际项目却占用了大量的页。本文的观点认为规格说明的层次不应受页数的限制。--Royce
是正确的,对于大型的、复杂的系统而言,重要内容的说明(如版本声明)可以达到范围的上限――200 页
子系统层次
一个子系统层次看上去像什么呢?这里有一些我用过的简单的"标准"形式。注意,这些只是用来实现一个系统的概念形式。实际系统的范围超出了这些形式的集合,并且每个子系统外部用例的总和就是系统全部的外部用例;因此,一个实际的系统可能有超过
10 个外部用例,但是正如我们后面将要看到的那样,上限并不是无限的。注意,这里并不是建议所有的开发都在它们的描述中使用
4 层用例。小的系统(<5 万 slocs)可能只用 1 层或者 2 层。
第一层
在第一层,具有通过零个或以上的子系统中的类实现的用例
图 1: 一个 Pareto 式样的分布图
在这一层估计系统(系统具有可通过类来实现的用例)规模的范围(使用7+或者-2的概念):
- 2 到 9 个类(没有形成到子系统中)――1700 slocs 到 8000 slocs ,或者
- 由 5 个类组成的子系统,共计 4000 slocs
- 由 7 个类组成的子系统为 9 个,共计 53,550 slocs
范围为 2 到 76 个用例。这是个模糊的界限,至少对于上限来说是这样的――在该限定下,以这种方式构建一个系统(在这个规模上),永远也不使用更高层的形式来表达所要求的行为,那么用例的数量应该降到零。如果用例的数字大于零,那么就是画蛇添足。
第二层
在第二个层次上,我们有一个由 8 个子系统组成的子系统组。我认为这等同于防御性术语中的计算机系统配置项(computer
system configuration item ,CSC I)。在这一层,用例是通过子系统的协作来实现的:
在这一层估计系统规模的范围(使用 7+或者-2 的概念):
- 从由 5 个子系统(每个子系统有 5 个类)组成的子系统组,共计 22,000 slocs,到
- 9 个由 7 个子系统(每个子系统有7个类)组成的子系统组,共计 370,000 slocs。
这就是说,外部用例的范围是 4 到 66。再次重申,这些只是模糊的界限。
第三层
在第三层,我们具有一个系统(由子系统组构成)。在这一层,用例是通过子系统组的协作来实现的:
在这一层估计系统规模的范围(使用 7+或者-2 的概念):
- 从 1 个系统,由 5 个子系统组组成,每个子系统组又由 5 个子系统(每个子系统有5个类)组成,共计
11 万 slocs,到
- 9 个系统,每一个系统都由 7 个子系统组组成,每个子系统组又由 7 个子系统(每个子系统有 7
个类)组成,共计 260 万 slocs 的类组成。外部用例的范围是 3 到 58。再次重申,这些界限是模糊的。
第四层
在第四层中,我们有一个由系统组成的系统。在这一层,用例是通过系统的协作来实现的:
在这一层估计系统规模的范围(使用 7+或者-2 的概念):
- 从 1 个由 5 个系统组成的系统,每个系统是由 5 个子系统组组成,每个子系统组是由 5 个子系统(每个子系统有
5 个类)组成,共计 54 万 slocs,到
- 9 个由系统组成的系统,每个大系统由7个系统组成,每个系统由 7 个子系统组组成,每个子系统组由
7 个子系统(每个子系统有7个类)组成,共计 1800 万 slocs 的类组成。外部用例的范围是
2 到 51。再重申一次,这些界限是模糊的。
假设更大的聚合也是可能的,但是我实在不想再考虑了!
每个用例的工作量
通过对每一层的额定的规模的工作量估计,我们可以对每个用例的工作量有一些深入了解。使用 Estimate
Professional? 工具 (基于 COCOMO 2 和 Putnam's SLIM 模型),将语言设置为
C++(其他成本驱动因素设置为额定值),然后计算每一个示例系统类型在每个额定规模点的工作量(假设 10
个外部用例),得到表 1。表中描述的 L1 和 L2 范围考虑到了单个用例的复杂度――使用 COCOMO
的代码复杂性矩阵通过类比进行估计。在 L2 层,我相信复杂性在被纳入系统类型的特征时复杂程度发生变化,因此一个更高层次的复杂命令和控制系统用例,将包含在一个较低的层次上复杂性的混合。在一个按照
log-log 比例的图上绘制这些数据,得到图 2。
图 2: 用例工作量规模图
从中我们可以看到,150-350 小时/用例(10 2.17-10 2.54)这个原来的 Objectory
数字在 L1 层上很适合,例如,这些用例可以通过类的协作来实现――因此存在一些理由来支持这个数字。然而,它不足以在分析中用来描述所有项目--我的一位同事曾在电子邮件与我交流时说:它太"片面"
了。
当前的实际系统不能与这些槽(slot)一一匹配。所以,为了帮助了解应该如何描述一个系统,我们将使用从该方法种得出的模糊的界限并将它们绘制出来:
Figure 3: 每个层次的规模范围
从图 3 中,我们可以看到一个超过 2.2 万 slocs 的系统最可能是在第一层描述,用例的数量在
2 到 30 之间。在这个规模上,更高的用例数量表明用例的粒度太细了。
规模在 2.2 万 和 5.4 万 slocs 之间的系统,应该使用一层用例和两层用例的混合,用例的数量在
4(都在第二层)和 76 都在第一层)之间,正如上图所表明的那样,一般不会出现极限值。
规模在 5.4 万和 11 万 slocs 之间的系统,一个结构好的系统完全在第二层进行描述是可能的,用例的数量在
10 到 20 之间;混合起来可能是 L1/L2/L3(1 到 160 个用例,一般不会出现极限值)。
规模在 11 万 和 37 万 slocs 之间的系统,可能在第二层和第三层之间,用例的数量在 3(全部在第三层)到
66(全在部第二层)之间。
规模在 37 万 和 54 万 slocs之间的系统,如果完全在第三层进行描述,那么用例的数量在 9
到 12之间;混合情况可能是 L2/L3/L4(1 到 100 个用例,一般不会出现极限值)。
规模在 54 万 和 260 万 slocs 之间的系统,可能在第三层和第四层之间,用例的数量在 2(全部在第四层)到
60(全部在第三层)之间。
规模超过 260 万 slocs 的系统,在第四层的用例数量应该在 8 左右。
多少用例才是足够的?
从一些经验法则中可以得到一些有趣的观察结果。有一个问题经常被问及--多少用例是过量的呢?这个问题实际上意味着在捕获需求的过程中多少是过量。答案似乎是多于
70 个,甚至对于最大的系统来说,70 这个数字也表明对于设计来说粒度太细了。在 5 到 40 之间是非常合适的,但是这只是数量,而并没有考虑到层次,不能用来估计规模和工作量。这是初始的数量,对于特殊的层次是合适的。如果一个大型超级系统被分解为系统,系统又被分解为子系统,以此类推,那么需要数以百计的用例。如果直到类的层次达到后才开发用例,那么最终的数量可能是上百个甚至是上千个(对于一个
140 人-年的项目,或者对于每个用例有15个功能点这样的项目来说是 600 个用例)。然而,作为一个纯粹的独立于设计的用例分解来说,这并不会发生。这些用例起源于
Jacobson 97 中描述的过程,Jacobson 97 中系统层次上的用例被划分为分配给子系统的行为,其中可以为子系统编写更低层次的用例(将其他子系统作为参与者)。
工作量估计的过程
如何进行估计呢?这里有许多先决条件:如果不能理解问题的领域、不了解系统的规模和系统构架,以及在哪一阶段进行估计,那么就不能够进行基于用例的估计。
第一次粗略的估计可以根据专家的观点或者更正式的采用 Wideband Delphi 技术(该技术是Rand
组织在 1948 年发明的,请参考Boehm 81 的描述)。这将使得评估者可以将系统在图 3 所示的规模范围中对号入卒。这种部署将提供用例数量的范围,并且表明表达式的层次(L1,
L1/L2 等等)。然后评估者必须基于对现有构架知识和领域中的理解来决定这些用例是否适合某一层(是否毫不相关),或者是不同层次的混合(以事件流的方式来表达)。
从这些考虑中可以看到,数据是否不够健康是显而易见的--例如:如果 Delphi 估计是 60 万行代码(或者等价的功能点),并且几乎没有什么构架方面的工作,那么对于系统结构方面知道得并不多--图
3 表明用例的数量应该在 2(所有的第四层)和 14(所有的第三层)。如果实际上用例数量是 100,那么用例可能已经提前进行了分解,或者
Delphi 的估计严重出轨。
继续分析这个例子:如果实际的用例的数量是 20,并且评估者决定它们都在 L3;更进一步讲,用例的长度平均7页,并且系统是一种复杂的业务系统,每个用例的小时数(从图
2 中得到)是20,000。为了降低复杂度,要乘以 7/9(基于用例的长度)。所以根据这种方法计算的工作量是
20×20000×(7/9) = ~310,000 人-小时,或者 2050 人月。根据 Estimate
Professional,对于业务系统而言,60 万行的 C++代码需要 1928 人月。因此,在这个设计的例子中,充分体现了这一点。
如果实际的用例的数量是 5,并且评估者决定将 1 个用例分配到 L4,其他 4 个分配到第三层。更进一步
L4 用例是 12 页,L3 用例平均是 10 页,然后计算工作量将是 1×250,000×12/9+4×21000×(10/9)
= ~2800 人月。这就表明 Delphi 的估计需要重新进行修订,尽管假设系统的主要部分看起来仍然在很高的层次上,但总之在边界上有很大的错误。
如果原来的 Delphi 估计是 10 万行 C++代码,图 3 表明用例应该在 L2 并且应该有 18
个。如果实际上有 20 个,如同前面的例子一样,如果 Delphi 估计很糟糕的话,那么是因为不考虑实际用例层次而应用该方法将得出一个不正确的结果。
因此,估计者必须检查用例是否在建议的抽象的层次上(L2)并且可以通过子系统的协作来实现,以及用例并不完全在
L3 上--尽管 Wideband Delphi 方法并不是经常那么糟糕(例如,预计 10 万,而实际上是接近
60 万)。问题是这种评估方法在使用时使人缺乏自信,没有额定的或者概念上的构架,而这些构架正是和用例的层次相匹配的。对于一个在该领域非常有经验的评估者来说,模型可以是一个能够判断形成哪一层的想象中模型,而对于一个经验比较少的评估者或者团队来说,做一些构架建模来观察一下在一个特殊的层次上用例实现得如何,不失为一种明智之举。
对于复合表达的用例(也就是说,层次 N 和层次 N+1的混合)应该计算为 n=8(l隔开两层的部分)
,得出用例在较低一层的数量。因此,一个用例假设 50%在 L1 并且 50% 在 L2,那么应该计算为
80.5 = 3 个 L1 用例,一个用例假设在 L2 和 L3 之间的 30%,那么应该计算为80.3
L2 用例= 2 个 L2 用例。一个用例在 L2 和 L3 之间的 90%,那么应该计算为 80.9
= 7 个 L2 用例。
表的规模调整
实际上考虑总的工作量规模时,需要对个别用例的小时数做进一步调整――工作量的数字只适合于在该规模系统的上下文中的每一个层次上。因此,在表
1 中的 L1 层,当构建一个 7000 slocs 的系统时,将采用每一个用例 55 小时。实际的数字将取决于总的系统规模――所以如果要构建的系统的规模是
40,000 slocs 并且使用 57 个 1 层的用例来描述它,那么对于一个简单的业务系统来说工作量就不是55×57
小时,而是(40/7)0.11 × 55 = 66 小时/用例。这是基于规模和工作量的 COCOMO 2
关系。根据 COCOMO 模型,工作量=A × (size)1.11,其中
- size 的单位为 ksloc
- A 为成本驱动因子
- 项目比例因子为额定值(将 1.11 用作指数)
注意这些计算可以作为因子用到诸如 Estimate Professional这样的工具中,从而减轻计算负担;此处完整列出了它们。
因此每 ksloc 的工作量或者每单元工作量等于 A× (Size)1.11/Size,从中推出 A×
(Size)0.11,因此,每单元的工作量在 size 为 S1 到 S2 的比率为(S1/S2)0.11。
对 Delphi 估计还要说明一点,系统的规模可以从各个层上用例的数量来粗略地计算出来:如果在第一层有
N1 个用例,在第二层有 N2 个,第三层有 N3 个,第四层上有 N4 个,那么总的规模就是[(N1/10)×7
+ (N2/10)×56 + (N3/10)×448 + (N4/10)×3584] ksloc。因此,我们可以计算工作量乘上表
1 中的每个用例的工作量,然后将总的规模除以表1中第一列中列出的每一层的规模(单位是 ksloc)。
因此, 在第一层, (0.1×N1 + 0.8×N2 + 6.4×N3 + 51.2×N4)0.11。
第二层 (0.0125×N1 + 0.1×N2 + 0.8×N3 + 6.4×N4)0.11。
第三层, (0.00156×N1 + 0.0125×N2 + 0.1×N3 + 0.8×N4)0.11。
第四层, (0.00002×N1 + 0.00156×N2 + 0.0125× N3 + 0.1×N4)0.11。
显然,以第四层为例,与第三层或第四层的用例数量相比,第一层用例的数量的影响微乎其微。
本文描述了基于用例进行评估的一个框架。为了使描述更加具体,本文为框架的参数选择了一些值,尽管这些值有待于论证,但它们并不总是错误的。像往常一样,随着数据的搜集,这种估计应该根据实际情况和重新估计的参数值进行测试。这种框架对于不同种类的系统考虑了用例层次、规模和复杂度等思想,并且不再采取细粒度的功能分解。为减轻计算的负担,对于诸如
Estimate Professional 这样的工具,可以构建一个前端,从而提供一种基于用例的规模输入的不同的方法。
对本白皮书的评论以及反馈意见,请通过电子邮件
jsmith@rational.com 与 John Smith 取得联系。
您可以参阅本文在 developerWorks 全球站点上的
英文原文。
1. Armour96: Experiences Measuring Object Oriented
System Size with Use Cases, F. Armour, B. Catherwood,
et al., Proc. ESCOM, Wilmslow, UK, 1996
2. Boehm81: Software Engineering Economics, Barry W.
Boehm, Prentice-Hall, 1981
3. Booch98: The Unified Modeling Language User Guide,
Grady Booch, James Rumbaugh, Ivar Jacobson, Addison-Wesley,
1998
4. Cockburn97: Structuring Use Cases with Goals, Alistair
Cockburn, Journal of Object-Oriented Programming, Sept-Oct
1997 and Nov-Dec 1997
5. Douglass99: Doing Hard Time, Bruce Powel Douglass,
Addison Wesley, 1999
6. Fetcke97: Mapping the OO-Jacobson Approach into
Function Point Analysis, T. Fetcke, A. Abran, et al.,
Proc. TOOLS USA 97, Santa Barbara, California, 1997.
7. Graham95: Migrating to Object Technology, Ian Graham,
Addison-Wesley, 1995
8. Graham98: Requirements Engineering and Rapid Development,
Ian Graham, Addison-Wesley, 1998
9. Henderson-Sellers96: Object-Oriented Metrics, Brian
Henderson-Sellers, Prentice Hall, 1996
10. Hurlbut97: A Survey of Approaches For Describing
and Formalizing Use Cases, Russell R. Hurlbut, Technical
Report: XPT-TR-97-03,
http://www.iit.edu/~rhurlbut/xpt-tr-97-03.pdf
11. Jacobson97: Software Reuse - Architecture, Process
and Organization for Business Success, Ivar Jacobson,
Martin Griss, Patrik Jonsson, Addison-Wesley/ACM Press,
1997
12. Jones91: Applied Software Measurement, Capers Jones,
McGraw-Hill, 1991
13. Karner93: Use Case Points - Resource Estimation
for Objectory Projects, Gustav Karner, Objective Systems
SF AB (copyright owned by Rational Software), 1993
14. Lorentz94: Object-Oriented Software Metrics, Mark
Lorentz, Jeff Kidd, Prentice Hall, 1994
15. Major98: A Qualitative Analysis of Two Requirements
Capturing Techniques for Estimating the Size of Object-Oriented
Software Projects, Melissa Major and John D. McGregor,
Dept. of Computer Science Technical Report 98-002, Clemson
University, 1998
16. Minkiewicz96: Estimating Size for Object-Oriented
Software, Arlene F. Minkiewicz,
http://www.pricesystems.com/foresight/arlepops.htm,
1996
17. Pehrson96: Software Development for the Boeing
777, Ron J. Pehrson, CrossTalk, January 1996
18. Putnam92: Measures for Excellence, Lawrence H.
Putnam, Ware Myers, Yourdon Press, 1992
19. Rechtin91: Systems Architecting, Creating &
Building Complex Systems, E. Rechtin, Prentice-Hall,
1991
20. Royce98: Software Project Management, Walker Royce,
Addison Wesley, 1998
21. RUP99: Rational Unified Process, Rational Software,
1999
22. Stevens98: Systems Engineering - Coping with Complexity,
R. Stevens, P. Brook, et al., Prentice Hall, 1998
23. Thomson94: Project Estimation Using an Adaptation
of Function Points and Use Cases for OO Projects, N.
Thomson, R. Johnson, et al., Proc. Workshop on Pragmatic
and Theoretical Directions in Object-Oriented Software
Metrics, OOPSLA '94, 1994
|