首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

3.9 经验教训

马尔可夫程序已经有了很长历史。其第一个版本是Don P. Mitchell 写的,后来由Bruce Ellis 做了些修改,它在80年代被大量应用到各种文献分析(deconstructionist)活动中。这个程序一直潜伏在那里,直到我们想到把它用在一个大学课程中,作为讨论程序设计的一个例子。我们并不是简单地捡起已有的东西,而是用C语言重新把它写出来,通过遇到的各种问题重新唤醒我们的记忆。而后我们又用几种不同语言重新写它,用各语言独特的习惯用法表述同样的基本想法。在这个课程之后,我们又多次重写这个程序,设法改进其清晰性和表现形式。

在这整个过程中,基本的设计并没有改变。最早的版本使用的也正是我们在这里给出的方式,虽然其中确实用了第二个散列表来表示各个词。如果我们还要重写它,基本情况大概也不会有多大变动。一个程序的设计根源于它的数据的形式。数据结构并没有定义所有的细节,但它们确实规定了整个解的基本构造。

有些数据结构选择造成的差异不太大,例如,是用链接表还是用可增长数组。有些实现方式比别的方式更具普遍性—例如,很容易把Perl和Awk 程序改造成使用一个词或三个词前缀的程序,但要想使这个选择能够参数化,就会遇到很多麻烦。面向对象的语言有它们的优越之处,对C++或Java的实现做点小修改,就可能使它们的数据结构适合英语之外的其他文本,例如程序(在那里空格可能是重要的东西),或者乐谱,甚至产生测试序列的鼠标点击和菜单选择。

当然,即使数据结构本身差不多,在程序的一般表现方面,在源代码的大小方面,在程序执行性能方面也可以存在很大差异。粗略地说,使用较高级的语言比更低级的语言写出的程序速度更慢,但这种说法只是定性的,把它随意推广也是不明智的。大型构件,如C++的STL或脚本语言里的关联数组、字符串处理,能使代码更紧凑,开发时间也更短。当然这些东西不是没有代价的,但是,性能方面的损失对于大部分程序而言可能并不那么重要。比如马尔可夫这样的程序,它不过只运行几秒钟。

当系统内部提供的代码太多时,人们将无法知道程序在其表面之下到底做了什么。我们应该如何评价这种对控制和洞察力的丧失,这是更不清楚的事情。这也就是STL版本中遇到的情况,它的性能无法预料,也没有很容易的办法去解决问题。我们使用过一个很不成熟的实现,必须对它做一些修正后才能够运行我们的程序。但是,很少有人能有资源和精力去弄清其中的问题并且修复它们。

目前存在着一种对软件的广泛的不断增长的关注:当程序库、界面和工具变得越来越复杂时,它们也变得更难以理解和控制了。当所有东西都正常运转时,功能丰富的程序设计环境可以是非常有生产效率的,但是如果它们出了毛病,那就没什么东西可以依靠了。如果问题牵涉到的是性能或者某些难于捉摸的逻辑错误时,我们很可能根本没有意识到有什么东西出了毛病。

在这个程序的设计和实现过程中,我们看到了许多东西,这些对于更大的程序是很有教益的。首先是选择简单算法和数据结构的重要性,应该选择那些能在合理时间内解决具有预期规模的问题的最简单的东西。如果有人已经把它写好并放在库里,那是最好了。我们的C++ 程序由此获益匪浅。

按照Brooks的建议,我们发现最好是从数据结构开始,在关于可以使用哪些算法的知识的指导下进行详细设计。当数据结构安置好后,代码就比较容易组织了。

要想先把一个程序完全设计好,然后再构造它,这是非常困难的。构造现实的程序总需要重复和试验。构造过程逼迫人们去把前面粗略做出的决定弄清楚。这正是我们在写这些程序中遇到的情况。这个程序经历了许多细节方面的变化。应该尽可能从简单的东西开始,根据获得的经验逐步发展。如果我们的目标只是为个人兴趣而写一个马尔可夫链算法程序,很可能就在Awk 或者Perl里写一个,可能也会不像这里这样仔细地打磨它,而是随其自然。

做产品代码要花费的精力比做原型多得多。例如可以把这里给出的程序看作是产品代码(因为它们已经被仔细打磨过,并经过了彻底的测试)。产品质量要求我们付出的努力要比个人使用的程序高一两个数量级。

练习3-8 我们已经看到马尔可夫程序在许多语言里的版本,包括Scheme、Tcl 、Prolog、Python、Generic Java、ML以及Haskell。从其中每一个,都可以看到其特殊的挑战性和优越性。在你最喜欢的语言里实现这个程序,并考察它的一般风格和性能。

补充阅读

标准模板库在许多书籍里都有介绍,包括Matthew Austern的《类属程序设计与STL》(Generic Programming and the STL,Addison-Wesley,1998)。对C++ 语言本身的参考文献当然是Bjarne Stroustrup的《C++程序设计语言》(C++ Programming Language第3版,Addison-Wesley,1997)。对于Java,我们参考了Ken Arnold和James Gosling的《Java程序设计语言》(The Java Programming Language第2版,Addison-Wesley,1998),对Perl语言的最好描述是Larry Wall 、Tom Christiansen 和Randal Schwartz的《Perl程序设计》(Programming Perl 第2版,83 O’Reilly,1996)。隐藏在设计模式后面的基本思想是:大部分程序所采用的不过是很少几种不同的设计结构,与此类似,实际上也只有不多的几种基本数据结构。说的远一点,这与我们在第1章讨论过的编码习惯用法也是很相像的。这方面的经典参考文献是Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides的《设计模式:可重用面向对象软件的要素》(Design Pattern: Elements of Reusable Object-Oriented Software,Addison-Wesley,1995)。Markov程序原来称为shaney,其传奇经历刊登在1989年6月号《科学美国人》杂志的“趣味计算”专栏里,该文重载于A. K. Dewdney的《神奇的机器》(The Magic Machine,W. H. 84 Freeman,1990)。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论
    图书导读