OO 设计过程:验证分析

发表于:2007-05-25来源:作者:点击数: 标签:分析设计过程验证
OO 设计过程:验证分析 原型与模型的差异以及二者的重要性 Allen Holub 首席技术官,NetReliance 2000 年 12 月 来自IBM DW站点 既然我们已经定义并细化了问题陈述,现在要为我们的教育软件构建一个模型。 本文是 OO 设计过程系列中的第四篇文章。前三篇是:

OO 设计过程:验证分析
原型与模型的差异以及二者的重要性

Allen Holub
首席技术官,NetReliance
2000 年 12 月
来自IBM DW站点


既然我们已经定义并细化了问题陈述,现在要为我们的教育软件构建一个模型。

本文是 OO 设计过程系列中的第四篇文章。前三篇是: 

入门 
开始设计软件 
细化问题定义 

这个月,我将通过创建一个模型来从问题陈述阶段转向解决方案阶段,并将该模型部署到用户社区(我 7 岁大的儿子)。

修改 
在纸上定义好问题之后,下一步是确保问题定义是正确的。可以使用几种方法来这样做(模型、UI 原型以及其它方法),我将在本月和下个月分别讲解。请记住,正如您阅读这些文章所感觉的那样,杂志上的文章一般都是连续的,但实际上,这些活动中的很多活动都并行发生。例如,我在创建 UI 的同时还在细化模型;我将使用通过用例分析发现的信息来改进 UI,并且,在进行 UI 方面工作的同时,还会找出用例分析中的缺陷。同样,当开始进行模型方面的工作时,我还会不可避免地发现初始问题陈述中的缺陷,并回过头来修正它们。设计过程不是一种有序的、循序渐进的过程,您不能在进行到下一步之前完成上一步的所有工作。而且,还要经常重新修改那些您认为已经完成了的工作,并用在目前正在进行的工作中发现的信息来更新它。

经常性的反复修改正是设计过程的一部分,并且必须这样做。对于设计文档来说,变成“过时的”实在是很容易,因为它不是象这样来更新的。对于在一年之后才能看到代码的程序维护人员来说,设计文档是必需的。虽然我认为,只要仔细编写代码(仔细选择变量和方法名,具有良好结构等等),代码本身也可以提供足够的文档信息,但是我不同意 Kent Beck 和那些“极端编程”人员的看法:不应该费力去使设计文档与实际代码保持同步,因为繁忙的程序员没时间这样做。

既然设计过程如此不稳定,我喜欢尽可能多地将它记录下来。Stravinsky 在创作 Rite of Spring 时将整篇乐谱放在公寓的墙上,以便可以从总体上观看作品。对于软件设计,这也是个好主意。

例如,我不喜欢使用 OO CASE 工具,因为它将设计文档隐藏在计算机内部,我看不到它们,我更喜欢用大量的白板,并在上面留下足够大的空间,以便随时使用。50 码长的白色简易纸卷也是不错的选择。只有在设计过程变得相对稳定时,我才会考虑将设计移至 CASE 工具中进行,并且,我不会使用任何不允许轻易打印出整个设计的 CASE 工具,因为,那样我就无法将设计样图粘回到墙上了。

模拟解决方案 
“修改”过程中的第一步是确保问题是值得解决的。我通常用模型来回答这个问题。

“原型”和“模型”之间有一个重要区别。以航空业为例,波音 777“原型”是一架功能齐全的飞机。除了在设计过程完成之后会有新机型取代它之外,它就是波音公司出售的飞机。实际上,原型是一个被部分构建的程序,而不是在测试之后即被丢弃的废品。与波音 777 一样,您使用原型程序作为设计思路的试验台。如果设计思路有效,则在原型中保留该思路。也就是说,原型是最终程序的部分构建版本(通常是最终程序的一部分)。必须仔细设计和组织原型;这是您设计的成品程序。这种类型的开发-逐步细化原型,直到生产出成品为止-通常称为“递增式细化”。

但在目前,我不需要原型。我需要的是模型。我想看看,为孩子设计的银行的总体思路是否有意义;我还不想构建实际的应用。模型是用管道粘胶、口香糖、纸夹和油漆等制成的试验品,用于测试那些目前还不想实现的概念。波音公司可能也模拟了 777 坐舱,以了解是否可以从驾驶员座椅触及所有的开关。他们可能用胶合板和其它现有飞机的座椅进行试验。相反,原型坐舱的大小与实际坐舱相同,有完整的电子线路,其中有真正的设备、座椅和开关。可能会将它挂在计算机飞行模拟器、而不是一架飞机上,但是,如果愿意的话,也可以将它放在飞机中。

原型的另一个特点是,它为在设计期间出现的重要问题提供答案。例如,通常回答“是否有足够的带宽来做 X?”这样的问题的唯一答案就是模拟做 "X" 那部分程序的原型(或者至少是与网络相关的程序部分)。如果不创建实际代码(也就是说,如果以人工方式模拟问题),实际上就回答不了这个问题。实际版本与模拟版本的行为可能不同。

因此,我在 Excel 中为“阿伦银行”实现了一个模型。在模型中,银行只是一个简单的电子表格,每一行记录一天的交易。可以通过在电子表格的适当单元内输入存款额来存款,并可以在另一个单元中看到当前余额和累计利息。对于实际的程序来说,这可能是一个糟糕的 UI,但是,这当然只是一个模型而已。

将模型提交给实际用户 
然后,我使用这个模型在我 7 岁的儿子菲利普身上尝试这个概念。试验获得了惊人的成功。首先,菲利普自己想出了复利的概念。


我说:“那么,在这个月末,你就可以取出最先存入的美元,还有银行为保存你的钱而付给你的五分硬币。”

他说:“那么,下个月,我得到的钱要超过五分硬币,因为我现在在银行中有更多的钱,是吗?” 

很明显,他喜欢这种不工作就可以赚钱的主意。证据就是,在几个月使用 Excel 模型的试验期内,菲利普没有取出一分钱。太棒了。

这个模型确实反映出有两处需要改进。事实上,菲利普经常询问他的帐户里还有多少钱。模型过程的一个具体效果就是如下修改“问题陈述”,以反映新的需求


重要的一点是:孩子们应该能看到每天的利息累计,每月发布一次利息信息是不够的。因此,银行每天都要计算复利,并且每天发布复利信息。存折要显示每天的发布信息,即使那天没有其它交易也要这样做。这样,即使没有存款,孩子们也可以看到利息是如何累计的。存折中还突出显示存款期间获得的总利息。 

第二个问题是在模型使用了一段时间之后才出现的。菲利普最终取出一笔钱去买一张他看中的 Pokemon 卡,但是他还缺大概一美元。“就像银行一样”,我答应借给他这些钱。也就是说,我将按他存款利息的两倍来收取他的贷款利息。这种额外的损失足以使他放弃取款(因此,我教他如何省钱的主要目的确实达到了),但是,我确实认为,将来有贷款的能力将很方便。因此,需要再次向问题陈述中添加内容:


孩子应该可以从银行借钱,但是这个过程也应该模拟实际的银行。贷款利率应该足够高(例如,是存款利率的两倍),以表明借钱是昂贵的,并且银行应该要求,每隔固定、相对短的时间(外面的银行是几个月一偿还)就偿还。孩子可以用存款来自动偿还。还是那样,因为练习的目的是要教孩子如何管钱,所以,银行必须可以为孩子显示贷款结算表,以使他们清楚地知道贷款要花费多少。另外,存折应该突出显示自动扣款,以显示减少的本金和所付的利息。如果未及时还款,父母将使银行对孩子施以罚款。


银行用“简单”利息的方法计算贷款利息-在每个还款期间,用当前未还清的本金乘以当前利率,从而计算出应付的利息。还款之后所剩的任何钱都可以用来减少本金。孩子应该可以在任何时候,通过在贷款帐户中进行额外付款(或比平时多付款)来减少本金。


计算还款的标准公式为: rate /= 1200; // Adjust rate to per-month
tmp = pow( 1.0 + rate, (double) number_of_periods );
return( (tmp * present_value * rate) / (tmp - 1.0) );


其中,rate 是年利率(即,如果年利率是 11.5%,rate 就是 11.5)。

无用功能 
我之所以没有添加第二个功能是因为菲利普实际上没有贷款,因此,我无法确定是否需要实现贷款功能。实现那些用不到的特性是没有意义的。事实上,那是很多现有程序的一大问题:它们有大量可能需要的特性,但实际上,没有人使用这些特性。这种“无用功能”除了在每一方面都使程序更昂贵之外,不做任何事:花更多钱去构建,花更多时间去构建,并且,因为公司必须收回构造成本,它还会向用户收取更高的费用。

金玉良言是:


程序应该只实现那些最终用户实际使用的功能,不要多也不要少。 

然而,总体设计应该足够灵活,以便以后可以轻易添加新特性。

至于目前这个程序,我决定先不添加贷款功能,以便尽快将程序推向市场。然而,我将尽快提出一个以后可以轻易添加该功能的设计方案。

用户、市场营销和销售 
关于模型要指出的最后一点是:Jacob Nielse 曾写到(抱歉,我记不起其出处),为两名用户演示原型的效果是为一名用户演示的效果的两倍,但是为三名用户演示的效果只是为一名用户演示的效果的 2.5 倍。为三名以上的用户演示是浪费时间。

使一名最终用户实际成为设计小组的成员是必需的,这样,不仅能帮助进行产品定义,还可以在设计和实现的整个过程中不断提出反馈意见。有两名用户就更好了,但是,第二名用户不必在现场,只需检查所设计的原型和模型即可。事实上,如果第二名用户不十分熟悉整个设计过程可能更好,这样,他/她提出的意见才更新奇和更公正。

如果没有真正的最终用户,如果愿意,还可以使用市场营销(不是销售)部门中的人员(用户代表)。区分市场营销和销售是很重要的。一个好的市场营销部门的主要目的是调研。市场营销是试图想出现实世界中做实际工作的人们真正需要什么样的程序的过程。他们用调查、面谈等方法来实现这点。“商业发展”和市场营销的概念密不可分。实际上,正式的问题陈述是市场营销档案,但必须由市场营销和技术小组协作指定,以确保可以及时完成程序。传统的特性与推向市场的时间之间的权衡是市场营销的决定。

另一方面,销售部门的工作是销售现有产品。销售部门绝对没有规划商业运作的权利,并且永远不应该被允许直接与技术方联系。销售人员应该向市场营销人员建议新特性,然后,市场营销人员验证该特性对于用户社区是否确实有价值。如果这些特性确实有价值,市场营销人员将随后与技术方协作,以将该特性添加到设计中,并最终添加到程序中。顺便提一句,不管添加特性有多困难,程序员都必须添加由市场营销人员指定的特性。市场营销人员需要提出产品占据市场所需的最小特性集。如果没有那些特性集,产品就不会成功。不允许程序员仅仅因为添加一个特性不方便就怠工,并妨碍公司的成功。

当设计方向由销售人员、而不是市场营销人员决定时,就完全出错了-很多人都经历过这种错误。某个客户打电话来请求一个新特性,销售人员随后将之变成“我的天哪,我们昨天就应该有这个特性”的请求。然后,一些不幸的程序员将会被强制停止有用的工作,并着手添加这个新的特性。三天以后,同样的事情再度发生,然后,添加第一个特性的要求被取消,取而代之的是一些新的“现在就要做出来”的特性。最终结果是什么也完不成。如果奇迹般地生产出一个有功能的程序,这个程序可能不会做任何有用的事。仅仅因为一名客户要求某一特性就添加该特性或修改设计是完全错误的;那样做的时候,您正冒着将您的软件公司变成只有一名客户的客户软件作坊的风险。真正的问题是:这个特性会对更广泛的社区有用吗?这就是一个市场营销问题。

这就是模型 
关于模型,已经讲了很多。下个月,我们将从用例分析和 UI 设计开始。

参考资料 

Extreme Programming Explained: Embrace Change(阅读:Addison Wesley,2000;ISBN 0-201-61641-6)中描述了 Kent Beck 的“极端编程”。 
要想看到模型与原型的真正区别,请查看有关如何建造波音 777 的 PBS 文档:21st Century Jet: The Building of the 777。 
Usability Engineering(San Francisco:Morgan Kaufmann Publishers,1993;ISBN 0-12-518406-9)中描述了 Jacob Nielsen 有关原型可用性的思想。

原文转自:http://www.ltesting.net