这是给《程序员》2009年12期所写的一个补白。这一期我自己感觉最精彩的,是《设计模式》15周年这个专题。敬请关注。
在国内一般程序员的眼中,设计模式曾经是高手的代名词,是超越具体程序设计语言的神功秘诀。但是,大家也许不知道的是,设计模式几乎一出生就伴随着批评甚至嘲笑。
不要以为这是无知者的无畏举动。早在1996 年,软件技术界最顶尖的大牛之一、Google 工程总监Peter Norvig 就做过名为“ Design Patterns in Dynamic Programming ”的演讲 ,其中他敏锐地指出:
设计模式某种意义上是为解决面向对象语言(当时主要是指 C++ )本身缺陷的一种权宜之计。在 Lisp 这样的动态(函数)语言中,由于不需要管理类和对象,不需要解决类给设计上带来的限制, GoF 的 23 种模式中,有 16 种要么用不着,用语言本身提供的机制就可以了,要么实现起来要简单得多。比如, Factory 和 Singleton 可以用 MetaClass 实现, Factory 和 Command 可以用闭包实现,等等。
无独有偶,2002 年,另一位著名程序员 Paul Graham (他开发了历史上第一个 Web 应用,也是著名创业投资公司 Y Combinator 的合伙人)也在自己访问量巨大的博客上发文“ Revenge of the Nerds ” ,为他的最爱 Lisp 语言(以及类似的 Smalltalk 、 Perl 和 JavaScript )大唱赞歌。文中他对编程语言有非常精彩的论述:
“如果你要解决一个困难的问题,要考虑的不是要不要用一种足够强大的语言,而是面临这样的选择: 1. 使用一种强大的语言; 2. 实际上为语言写一个解释器; 3. 自己成为语言的人肉编译器。”他认为模式其实就是人肉编译器的表现。程序里出现的模式,往往是一种坏味。
最激烈的批评来自一位年轻但非常有才华的程序员 Slava Akhmechet ,他曾经用 Common Lisp 开发了Web 框架 Weblocks ,目前正在开发针对 SSD 优化的 MySQL 引擎 RethinkDB ,并以此创办了一家新公司。他在 2006 年写过一篇文章“ Functional Programming For The Rest of Us ” ,其中明确表示:“模式适用于所有软件开发?……这绝非事实。……函数式语言表达力极强。在函数式语言中不需要设计模式,因为语言足够高级,你可以直接用语言概念完成编程,完全消除设计模式。”他以 Adapter 模式为例子(同时不忘嘲笑一句,这和 Facade 有啥区别?估计得写上几页纸才说得清吧),认为如果语言支持 curry ,这个模式就无用武之地了。而善用模式匹配,可以简单地修改条件,又干掉了一大批设计模式。
从GoF 在《设计模式》出版 15 周年的访谈中可以看出,他们对 GoF 设计模式不适用于某些语言并无异议。那么,是否函数式语言中真的就不需要或者没有设计模式了呢?
其实不然。我们知道,模式实际上是一种思想,GoF 模式和亚历山大的建筑模式之间就只有一些哲学上的共同性。在函数式语言中,只要存在某些特定的上下文中有似曾相识的美妙的解决方案,那么模式也就出现了。事实上,这方面已经技术界已经做了不少工作。比如 Eugene Wallingford 的模式语言 Roundabout 和 Envoy , Darrell Ferguson 与 Dwight Deugo 的 Call with Current Continuation 模式,而 Thomas Kuehne 则总结了一套函数式语言的模式系统,可以生成良好的面向对象设计。更引人注目的,则是 OTP 小组撰写的 Erlang 设计原则 。 其中,设计模式被提到一个极为中心的地位。用来设计新应用的最佳方式是通过所谓的行为( behaviour ),包括 application 、 sup bridge 和 supervisor 等,而这个行为就是设计模式的代称……
了解这些对一般程序员有什么意义呢?《程序员修炼之道》书中说过“每年学一种新语言”,看来,该下手了。