长期以来,我们一直遵循这样一个编程风格方面的原则:一个程序的功能要素不应该太大。如果程序中的某些部件的规模超出了易于理解的范围,就会造成大量的复杂性,这些复杂性很容易隐藏错误,正如在一个大城市中很容易隐藏罪恶一样。这种程序难以理解、难以测试、难以调试。
根据这个原则,一个大型程序必须要分割成一些小块,并且分割的程度应该和程序的规模相称。那么,如何来对程序进行分割呢?传统上,我们一般会使用称为自顶向下的设计方法(top-down design):程序打算完成7项任务,于是就把它划分成7个主要的子例程。第一个例程要做4件事情,于是就再把它分割成4个子例程。这个过程要持续下去,直到整个程序具有适当的粒度为止。这里适当的含义为:每个部分都大到足以完成一些实质性的工作,并且都小到足以作为一个可理解的单元。
有经验的Lisp程序员却以一种不同的方式来分割他们的程序。和自顶向下设计对应,他们称之为自底向上设计(bottom-up design):改变语言,使之适合于要解决的问题。在Lisp中,你不是仅仅用语言来编写程序,同时你还要对语言进行增进,使之更加适用于你的程序。在你编写程序时,你会这么想:“我希望Lisp具有某某操作符。”于是你就去把它编写出来。然后,你发现使用这样一个新的操作符会简化程序其他部分的设计。语言和程序在一起演化。就像是位于两个处在战争状态国家的边界一样,语言和程序之间的边界线不断地重新划分,直到最后停留在山川、河流区域――最适合于你的问题的一个自然边界。最后,你的程序看上去就像是使用专门为它设计的语言编写的。当语言和程序相互非常匹配时,代码也会变得更加的清晰、短小、高效。
值得强调的是,自底向上设计并不仅仅是一种以不同的顺序编写同一个程序。当以自底向上方式工作时,通常得到的是一个完全不同的程序。得到的不是一个单片机式的程序,而是一个具有更多抽象操作符的、语义更为丰富的语言,以及一个用该语言编写的更短小的程序。不光得到了结果,你还得到了更强大的表达能力。
我们在编写代码时,一旦剥离出了那些仅仅做一些薄记工作的部分,剩余的核心部分就会变得非常短小,我们把语言的抽象层次提得越高,从顶部到达它得距离就越短。这会带来如下几个好处:
1、 通过使语言做更多的工作,自底向上设计所产生出的程序更加短小、更加敏捷。一个短小的程序就不必再分割成很多的部分,而具有较少的部件则意味着程序将更加地易读和修改。具有较少部分的程序也意味着部件之间具有更少的关联,因此出错的可能性就更少。正如一个工业设计师努力减少机器内部中的运动部件的数量一样,有经验的Lisp程序员也在使用自底向上设计来减少他们程序的规模和复杂性。
2、 自底向上设计鼓励代码重用。当你编写了两个或者更多的程序时,很多你为第一个程序编写的工具也会在后续的程序中发挥作用。一旦你具有了一个大型的工具基础库,编写一个新程序所需要的工作量将会大大低于使用原始Lisp所需要的。
3、 自底向上设计使得程序更加易读。是一个通用目的的操作符好理解呢,还是一个针对特定领域的特定目的操作符好理解呢?
4、 自底向上设计有助于理清自己的设计思路,因为它会迫使你总是去寻找代码中的模式。如果两个不同的部件在形式上非常相似,你就会被引导去注意这些相似性,并且以一种更为简单的方法去重新设计程序。
除了Lisp外,在其他程序语言中也可以在某种程度上实施自底向上设计。只要你看到了库函数,在那里就使用了自底向上设计。然而,Lisp在这方面提供了更为宽广的支持, 使之在以Lisp风格编程方面达到了一种:Lisp不仅仅是一种不同的语言,而是一种完全不同的编程方法的程度。
很显然,这种开发风格更适合于小团队开发。但是,它同时也延伸了一个小团队所能完成的任务的限制。在《人月神话》一书中,Frederick Brooks指出,程序员团队的生产力不会随着团队的规模线性增长。当团队的规模扩大时,个体程序员的生产力会下降。Lisp编程的经验则以一种更为令人振奋的方式表达了这一法则:随着团队规模的缩小,个体程序员的生产力会升高。一个小规模的团队会取得成功,这只是因为它更小一些。当一个小型团队同时也掌控了Lisp所使能的技术时,那么它就会更为彻底地取得胜利。
分享到:
相关推荐
Lisp语言的设计初衷便包含了自底向上的设计理念,它的可扩展性使得自底向上的编程成为可能且自然。Lisp语言本身就是由一系列Lisp函数组成的,这些函数与用户自定义的函数并无本质区别,同时,Lisp的代码可以表示为...
传统的自上而下方法有时无法应对复杂或开放式的需求,而自底向上设计则提供了一种新的编程范式。 《On_Lisp》强调了自底向上编程对于Lisp语言的重要性,并认为在Lisp之上,程序员可以构造自己的语言,并用这些语言...
- **自底向上的设计实践**:书中详细阐述了自底向上的设计思想,并通过具体的实例来展示如何在实践中应用这一方法。这种编程风格尤其适用于处理复杂或开放式的软件需求。 - **案例研究**:书中包含了许多具体的案例...
### Common Lisp:深入理解与应用 #### 一、Common Lisp概览 Common Lisp是一种功能强大的高级...无论是对于希望深入了解Lisp语言的开发者还是想要探索自底向上设计方法的学习者来说,本书都是一本不可多得的好书。
《OnLisp》倡导的自底向上的编程方法,是一种从简单的基本单元开始构建复杂系统的编程策略。这种方法强调先从细节入手,逐步构建起更为复杂的系统,与传统自上而下的设计思路形成鲜明对比。在处理复杂需求或开放式...
《On Lisp》是一本深入探讨Lisp语言宏系统和自底向上编程思想的经典著作。作者Paul Graham通过这本书向读者展示了Lisp的强大之处,尤其是其在编程语言扩展方面的灵活性。Lisp,作为一种历史悠久的函数式编程语言,以...
总之,《On Lisp》通过对Lisp宏功能的全面介绍,以及对自底向上编程思想的深入挖掘,为Lisp程序员提供了一种新的编程范式和思维方式。通过阅读这本书,读者将获得编写更加灵活、表达力更强代码的能力,同时也可以...
- 可以使用递归下降解析或者自底向上解析的方法来实现。 4. **环境与作用域**: - Lisp解释器需要维护一个环境,用于存储变量的值和函数定义。 - 作用域规则需要正确实现,包括全局变量、局部变量以及函数参数的...
1 详细给出了自顶而下的分析算法(第4章和第5章),包括递归下降和LL(1)分析方法、自底向上的分析、LALR(1)分析表以及Yacc分析器产生器工具的使用。 2 完整讨论了运行时环境的一般形式(第7章),从Fortran的完全...
这个计算器并不依赖于栈来解析和求解表达式,而是采用了另一种实现方式,这可能涉及到自底向上的语法分析或者递归下降解析等技术。 在C语言中,实现一个算术表达式计算器首先要理解基础的数据类型,如int、float等...
- 复杂性:C++遵循自底向上的编程方式,对开发者的技术要求较高,适合底层系统开发和特定算法实现。 3. Java Java是一种跨平台的、面向对象的编程语言,遵循“一次编写,到处运行”(WORA)原则: - 平台独立:Java...
分层设计方法遵循自底向上和自顶向下的原则,各层之间有单向依赖关系,以保持结构清晰。半序和全序分层是常见的设计模式,前者允许同一层内部的互相调用,后者则禁止。THE操作系统展示了这种分层思想,分为6层,每层...
4. 建立继承关系通常采用自顶向下和自底向上的方式。 5. 软件设计任务包括需求转换、数据结构和程序结构设计。 6. 数据流图中的操作可以是查询、动作或访问。 7. 软件测试的特点包括高开销、依赖人工和工具,且无法...
解析技术(如自顶向下解析和自底向上解析)则是根据这些规则来构建语法树的过程。 通过以上内容,我们可以了解到编译器工作的基本原理以及语言和文法的相关概念。这些知识对于理解和设计高效可靠的编译系统至关重要...
- **语法分析**:分为自顶向下和自底向上两种方法,涉及如何构建语法树来解析源代码结构。 - **属性文法**:介绍如何为文法添加额外的信息,以支持更复杂的语义分析。 - **中间代码生成**:讨论将源代码转换为一种...