很久很久以前,在一个离这儿不远的王国里,国王为了做一个测验,把他的两名顾问召进宫来。国王给他们展示了一个闪闪发光的金属盒子,盒子顶上有两个插槽,旁边有一个控制按钮和一个控制杆。
“你们觉得这是什么?” 国王问。
其中一名顾问,也是一位工程师首先回答道:“它是一台烤箱。”
国王问:“如果要为这台烤箱配备一套嵌入式计算机系统,你的具体设计是什么?”
工程师回答说:“我将使用一个四位的微控制器,然后编写一个简单的程序,读取火候调节按钮的当前位置信息。我把火候信息量化 - 从雪白到漆黑,总共 16 焦度级别。预置的烧烤时间存放在一个仅有 16 行的以焦度级别为索引的数据表中。然后,启动加热器,读取预置烧烤时间,计时结束后,关闭加热器,弹出面包片。给我大约一周时间,我就可以拿出这个系统的原型。”
第二名顾问是一位计算机科学家。他很快意识到了工程师缺乏远见想法的危害性。他说:“电烤箱不只是用来烤面包片的,它还可以加热冷冻鸡蛋饼。我们之前看到的东西,实际上是一台早餐加工机。我们国民的生活异常丰富,他们需要多功能的机器,比如,一台能烤香肠、煎培根、炒鸡蛋的早餐加工机。功能单一的烤面包片烤箱很快就会过时的,如果现在考虑不周,两到三年后,我们就不得不重新设计这个烤箱。
鉴于这一事实,我们应该设计一个更加聪明的解决方案。首先,创建一个早餐食品类。然后,从这个类派生出一组子类:面食类、肉类、禽蛋类等等。面食类进一步派生出面包类、松糕类、煎饼类、蛋饼类;肉类派生出香肠类、肉串类、培根类;禽蛋类派生出炒鸡蛋类、水煮蛋类、荷包蛋类、煎蛋类以及各式各样的蛋卷类。
对于干酪火腿煎蛋卷这个类,我们需要一些特殊处理。它必须同时继承肉类、乳制品类和禽蛋类的特性。因此,缺乏多重继承机制无法解决这个问题。程序运行起来之后,它必须可以正确地创建对象实例,然后向对象发送『开始加工』的消息。该消息触发何种操作要取决于对象的类型,这样的话,同一条消息就可以激活从烤面包片到炒鸡蛋的各种不同操作啦。
基于以上所述,我们在分析阶段,必须将核心需求界定为加工不同种类的早餐食品。在设计阶段,我们还要进一步明确由此衍生的其它需求,比如,我们必须采用一种拥有多重继承功能的面向对象语言。另外,诸如鸡蛋已经晾凉,但培根还没有烤好的情景完全不能接受,所以,多任务并发处理的功能和机制也是必要的。
千万别忘了用户界面。控制杆不适于加工多种食品,火候控制按钮也容易让用户摸不知所措。用户更喜欢购买那些具备友好的图形化界面的产品。
当早餐加工机通电之后,用户应该在屏幕上看到一名牛仔。点击这名牛仔之后,屏幕上就会显示『启动 UNIX v.8.3』的信息(UNIX v.8.3 版本将在早餐加工机上市前发布)。系统完成启动之后,用户就可以打开下拉菜单,在菜单中点选他们想要加工的食品。
在设计阶段,我们首先详细定义了软件的功能特性,接下来我们要为具体实现选择一种适当的硬件平台。带有 8 兆内存、30 兆硬盘以及 VGA 显示器的英特尔 80386 机型应该足够用了。如果你选择一种支持多任务、多重继承、以及内置图形化用户界面开发包的面向对象语言的话,那么当你编写程序时就会轻松许多。(与之相比,那种首先确定硬件环境,然后再把自己禁锢在四位微控制器上的思路是多么愚蠢啊!)
国王把这位计算机科学家扔进了护城河里。自那之后,国王和他的臣民们一直过着快乐的生活。
参考:国王和电烤箱
感谢:Qingniu 帮助审阅及完成校对。