本文描述了基于用例进行评估的一个框架。为了使描述更加具体,本文为框架的参数选择了一些值,尽管这些值有待于论证,但它们并不总是错误的。像往常一样,随着数据的搜集,这种估计应该根据实际情况和重新估计的参数值进行测试。这种框架对于不同种类的系统考虑了用例层次、规模和复杂度等思想,并且不再采取细粒度的功能分解。为减轻计算的负担,对于诸如 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 - 类