十一、原型与便签
我们需要构建原型,原因是为了分析和揭示风险,并以大大降低的代价、为修正提供机会。与轿车制造商一样,我们可以把原型用于测试项目的一个或多个具体的方面。
我们往往以为原型要以代码为基础,但它们并不总是非如此不可。与轿车制造商一样,我们可以用不同的材料构建原型。要为像工作流和应用逻辑这样的动态事物制作原型、便签就非常好。用户界面的原型则可以是白板上的图形、或是绘图程序或界面构建器绘制的无功能的模型。
原型的设计目的就是回答一些问题,所以与投入使用的的产品应用相比,它们的开发要便宜的多、快捷的多。起代码可以忽略不重要的细节——在此刻对你不重要, 但对后来的用户可能非常重要。例如,你在制作GUI原型,你不会因不正确的结果或数据而遭到指责。而另一方面,如果你只是在研究计算或性能方面的问题,你也不会因不正确的结果或数据而遭到指责。而另一方面,如果你只在研究计算或性能方面的问题,你也不会因为相当糟糕的GUI而遭到指责;甚至也可以完全不要GUI。
但如果你发现自己处在不能放弃细节的环境中,就需要问自己,是否真的在构建原型。或许曳光弹开发方式更适合这种情况。
应制作原型的事物
你可以选择通过原型来研究什么样的事物呢?任何带有风险的事物。以前没有试过的事物。或是对于最终系统极端关键的事物。任何未被证明的、实验性的、或有疑问的事物。任何能让你觉得不舒服的事物。你可以为下列事物制作原型:
- 架构
- 已有系统中的新功能
- 外部数据的急结构与内容
- 第三方工具或组件
- 性能问题
- 用户界面设计
原型制作是一种学习经验。其价值并不在于所产生的代码,而在于所学到的经验教训。那才是原型制作的要点所在。
怎样使用原型
在构建原型时,你可以忽略哪些细节?
- 正确性。你也许可以在适当的地方使用虚设的数据。
- 完整性。原型也许只能在非常有限的意义上工作,也许只有一项预先选择的输入数据或一个菜单项。
- 健壮性。错误数据检查很可能不完整,或是完全没有。如果你偏离预定路径,原型就可能崩溃,并在“烟火般的灿烂显示中焚毁”。
- 风格。在纸上承认这一点让人痛苦,但原型代码可能没有多少注释或文档。使用原型的经验,你也许会撰写大量文档,但关于原型系统自身的内容相对而言却非常少。
因为原型应该遮盖细节,并聚集所考虑系统的某些具体方面,你可以使用非常高级的语言实现原型——比项目其余部分更高级(也许是像Perl、Python这样的语言)。高级的脚本语言能让你推迟考虑许多细节,并且仍然能制作出能工作的代码。
制作架构的原型
许多原型被构造出来,是要为在考虑之下的整个系统建模。与曳光弹不同,在原型系统中,单个模块不需要能行驶特定的功能。事实上,要制作架构原型,你甚至不一定需要进行编码——你可以使用便签或索引卡片、在白板上制作原型。你寻求的是了解系统怎样结合成为一个整体,并考虑推迟细节。下面是一些你可以在架构原型中寻求解答的具体问题:
- 主要组件的责任是否得到了良好的定义?是否适当?
- 耦合是否得以最小化?
- 你能否确定重复的潜在来源?
- 接口定义和各项约束是否可以接受?
- 每个模块在执行过程中是否能访问到其所需的数据?是否能在需要时进行访问?
根据我们制作原型的经验,最后一项往往会产生最让人惊讶和最有价值的结果。
怎样“不”使用原型
在你着手制作任何基于代码的原型之前,先确定每个人都正确理解你正在编写用过就扔的代码。对于不知道那只是原型的人,原型可能会具有欺骗性的吸引力。你必须非常清楚地说明,这些代码是用过就扔的,它们不完整,也不可能完整。
别人很容易演示原型外表的完整性误导,而如果你没有设定正确的期望值,项目出资人或管理部门可能会坚持要求要部署原型。提醒他们,你可以用轻木或胶带制造一辆了不起的新车原型,但你却不会在高峰时间的车流中驾驶它。
如果你觉得你所在的环境或文化中,原型代码的目的很可能被误解,你也许最好还是采用曳光弹的方法。你最后将得到一个坚实的框架,为将来的开发奠定稳定的基础。
使当地使用原型,可以帮助你在开发周期的早期确定和改正潜在的问题点——在此时改正错误既便宜、又容易——从而为你节省大量的时间、金钱,并大大减轻你遭受的痛苦和折磨。