9.2 原型法

我们在 4.3 中介绍了自顶向下逐步求精的程序设计方法。自顶向下设计是非常强大的程 序设计技术,但它也有不适用的场合。

自顶向下设计的第一步是顶层设计,这需要设计者对问题的全局有清晰的认识。万一要 解决的问题非常复杂,或者用户需求不是很完整、清晰,这时顶层设计就非常困难。另外, 设计者有时候会卡在自顶向下层次中的某一层,这就导致下层的精化无法继续,从而影响整 个程序的开发。即便前面这两个问题都不存在,自顶向下设计也存在开发周期过长、工作量 太大的缺点。

另一种程序设计方法是原型法(prototyping)。这种方法的思想是,先开发一个简单版 本,即功能少、界面简单的版本,然后再对这个简单版本逐步进行改善(添加或修改功能), 直至完全满足用户需求。初始精简版程序称为原型(prototype)。应用原型法来进行软件开 发的步骤大致如下:

(1)确认基本需求;

(2)创建原型;

(3)向用户演示或交付用户试用,获得反馈意见;

(4)改善原型;回到(3),重复(3)、(4),直至用户最终认可。 可见,原型技术不是对整个问题按照“设计、实现、测试”的过程来开发,而是先按此

过程创建一个原型,然后根据用户反馈再重复此过程来改善原型。这样,通过许多“设计- 实现-测试”小循环,原型逐步得到改善和扩展,直至成为最终产品。因此原型法也称为“螺 旋式开发”。原型法适合于大型程序开发中需求分析难以一次完成的场合,也常用在程序用 户界面设计领域。

原型法开发有很多优点,例如:用户可以通过实际使用的体验来评价软件产品是否合意, 而不是仅凭开发者口头的描述;开发者和用户可以在开发过程中发现以前没有考虑到的需求 或问题;开发者可以在产品开发的早期就获得用户反馈,避免在开发后期来修改设计,因为 越往后,修改的代价就越大。

原型法开发中的原型可以有两种处理方法。一种方法是,一开始构造的原型就是最终产 品的核心,后续工作都是对原型的改善,通过不断的积累和修改最后得到符合用户需求的产 品。开发过程中,原型尽管功能不完善,但一直是可用的,甚至可以作为在最终产品交付前 的替代产品。另一种方法是,初始创建的原型只是作为与用户进行交互的工具,通过不断展 示给用户看而获得反馈并改进。等到用户认可原型,该原型即被丢弃,开发者将基于用户已 经确认的需求开始正式开发产品。这种做法称为“快速原型法”,因为其主要目的是尽快构 造系统模型,强调的是开发速度。

我们在 9.1.3 中就采用了原型法来设计实现乒乓球比赛的模拟程序。 解决问题的关键是模拟乒乓球比赛,而比赛的最基本动作是打一个回合及记分,因此我们一开始就考虑如何模拟一个回合的比赛并给胜方得分。即:

if random() < prob: 
    pointA = pointA + 1
else:
    pointB = pointB + 1

经过测试,可以确认这段代码确实能够模拟具有特定得分概率的球员之间的比赛。在此 基础上,根据实际乒乓球比赛的规则要求,我们将回合扩展到局,又扩展到一场 3 局 2 胜的 比赛。在设计的前期阶段,我们做了很多简化,比如直接假设球员的得分概率为 0.55,直接 规定采用 21 分一局的规则等等。随着螺旋式开发的进展,程序功能越来越完善,所有被简 化的东西最终都会以完善的形式实现。总结这个开发过程,我们的模拟程序大致经历了如下 阶段:

阶段 1:建立原型,能进行回合比赛并为胜方记分;

阶段 2:扩展为能进行一局比赛;

阶段 3:扩展为能进行 3 局 2 胜的比赛;

阶段 4:球员的得分概率、比赛次数改为由用户输入;

阶段 5:添加结果分析,输出分析结果。

通过原型法来编程序,对初学程序设计的人来说是很合适的,因为可以从原型获得最终 程序的感性认识,并进而理解自己到底要写什么样的程序。

要指出的是,螺旋式开发并不是用来取代自顶向下设计的,这两种设计方法是互为补充 的关系。例如,对于大型的复杂程序,如果用原型法,可能原型本身也比较复杂,这时就可 以采用自顶向下设计来创建原型。好的设计者应该根据情况选用多种设计方法,这一切都要 通过实践来学习掌握。