王垠:解密“设计模式”

来源:王垠的博客

有些人问我,你说学习操作系统的最好办法是学习程序设计。那我们是不是应该学习一些“设计模式”(design patterns)。这是一个我很早就有定论,而且经过实践检验的问题,所以想在这里做一个总结。

总的来说,如果光从字面上讲,程序里确实是有一些“模式”可以发掘的。因为你总是可以借鉴以前的经验,用来构造新的程序。你可以把这种经验叫做“模式”。可是自从《设计模式》(通常叫做 GoF,“Gang of Four”,“四人帮”)这本书在 1994 年发表以来,“设计模式”这个词有了新的,扭曲的含义。它变成了一种教条,带来了公司里程序的严重复杂化以及效率低下。

王垠:解密“设计模式”

GoF 借鉴的是一个叫 Christopher Alexander 的建筑师的做法。Alexander 给一些建筑学里的“设计模式”起了名字,试图让建筑师们有一些“共同语言”。可惜的是,Alexander 后来自己都承认,他的实验失败了。因为这些固定的模式,并没能有效地传递精髓的知识,没能让新手成长为出色的建筑师。

照搬模式东拼西凑,而不能抓住事物的本质,没有“灵感”,其实是设计不出好东西的。这就像照搬“模版”把作文写得再好,也成不了作家一样。

我孤陋寡闻,当听说这本书的时候,我已经学会了函数式编程,正在 Cornell 读 PhD,专攻程序语言设计。有一天由于好奇这书为什么名气这么大,我从图书馆借了一本回来看。我很快的发现,其实这本书的作者只是给早已经存在的编程方法起了一些新的名字而已。当时我就拿起一张纸,把所有的20来个设计模式跟我常用的编程概念做了一个映射。这个映射居然是“多对一”(many-to-one)的。也就是说,多个 GoF 设计模式,居然只对应同一个我每天都用的概念。有些概念是如此的不值一提,以至于我根本不需要一个名字来描述它,更不要说多个名字!

其中极少数值得一提的“模式”,也许是 visitor 和 interpreter。很可惜的是,只有很少的人明白如何使用它们。所谓的 visitor,本质上就是函数式语言里的含有“模式匹配”(pattern matching)的递归函数。在函数式语言里,这是多么轻松的事情。可是因为 Java 没有模式匹配,所以很多需要类似功能的人就得使用 visitor pattern。为了所谓的“通用性”,他们往往把 visitor pattern 搞出多层继承关系,让你转几道弯也搞不清楚到底哪个 visitor 才是干实事的。

其实,函数式语言的研究者们早就知道 visitor pattern 是怎么得来的。如果你想知道如何从无到有,一步一步“发明”出 Java 的 visitor pattern,可以参考?Dan Friedman?跟他的学生 Matthias Felleisen 合写的的另一本“小人书”《A Little Java, A Few Patterns》(发表于 1997 年)。

王垠:解密“设计模式”

而 interpreter (解释器)模式呢?看了作者们写的例子程序之后,我发现他们其实并不会写解释器,或者说他们不知道如何写出优雅的,正确的解释器。如果你想知道如何写出好的解释器,可以参考我的博文《怎样写一个解释器》。

你说我在贬低这本书的真正价值,因为 GoF 说了:“我们的贡献,就是给这些编程方式起名字。这样让广大程序员有共同的语言。” 如果这也叫贡献的话,我就可以写本书,给“空气”,“水”,“猪肉”这些东西全都起个新名字,让大家有“共同的语言”。这不是搞笑吗。

这不是我的一家之言,Peter Norvig 在 1998 年就做了一个演讲,指出在“动态语言”里面,GoF 的20几个模式,其中绝大部分都“透明”了。也就是说,你根本感觉不到它们的存在。这就像我刚才告诉你的。

王垠:解密“设计模式”

在这里 Norvig 的观点是正确的,不过需要小心一个概念错误。Norvig 对“静态语言”的概念是有局限性的。有的静态语言其实也能传递函数作为参数,而且不像 Java 那样什么都得放进 class 里。这样的静态语言,其实也可以避免大部分 GoF 设计模式。而“动态语言”这个概念,在程序语言的理论里面,其实是没有明确的定义的。“动态语言”其实也能进行某些“静态类型检查”。不过在 1998 年,我还是个啥都不懂的屁孩,所以这里就不跟 Norvig 大叔计较了。

既然老人们都有历史局限性,那么为啥我还跟 GoF 找茬?本来这本书很老了,如果没有人再被它误导的话,这篇博文也就不必存在了。可是当我在 Google 实习的时候,我发现几乎每个程序员的书架上都有一本 GoF!我在 Google 实习了两次,第一次的时候代码全都是我一个人写的,所以没有使用任何 GoF 设计模式。代码直接,精巧而简单。当我第二次回到 Google,发现我的代码里已经被加入了各种 factory,visitor,…… 其实啥好事也没做,只不过让我的代码弯了几道弯,让人难以理解。

可见一本坏书,毁掉的不只是一代程序员。鉴于如此,特发此文。各位新手,希望你们敲响警钟,不要再走上这条老路,写出代码来让大家痛苦。

至于如何学会写真正好的代码,我在另一篇博文里再讲。

1 2 收藏 9 评论

相关文章

可能感兴趣的话题



直接登录
最新评论
  • 我相信设计模式是新手的圣经,刚进入程序世界的时候大家并不知道 猪是猪 水是水 所以统一的方法的命名很重要,而且方法论也可以给新手更好的指导,有如张无忌学太极,最后忘记了招式才学到了精髓,所有的设计模式中心无外乎就是抽象与实现,让程序更加健壮。

    再折作为高手也不能否定 设计模式 存在的重要性,就像思想每个人都有,只有思想家才可以通过提炼将原本虚无的内容通俗的描述出来,让普罗大众接受。

  • 最为一个新手程序猿学习JAVA之时就抱着THINK IN JAVA看,里面提到各种设计模式:工厂、适配器、策略……不得不说虽然有些设计模式很繁琐但是其体现的思想很有用。于形,设计模式提供博主提到的“统一”;于心,设计模式就是让我们学到其解决问题的思想。

  • ee   2013/03/08

    设计模式也逃不开语言,设计模式大多针对面向对象,你真的了解面向对象了许多模式自然而然就应该使用出来,而不应该看很多设计模式才搞清楚, 当然悟性不够或者用的语言本身就很糟糕的话就只有看了。

  • 飞翼   2013/03/13

    楼主这么评论设计模式,真可笑!就好像一个人爬到了山上高处,然后回过头来,志得意满的对着山下那些人说,你们不要去看地图!不要去摆弄指南针!(低层语言、设计模式等)……你看,其实有导游图,也有对讲机,(所谓函数式编程、动态语言等),你们真是图样图森破!不懂这些高级的便利的东西!而且,最重要的,你们要有悟性。悟性,懂么?(指领悟面向对象思想的精髓)
    而且对于楼主到底爬到了多高、是否懂引导人,也要抱一个大大的问号。

  • jason   2013/03/20

    伯乐在线连这种文章也转载,岂不是误人子弟?就作者这种水平,这种态度,他能做好团队协作?也许他个人对编程语言的机制很了解,但对于他的实际工作效能,我表示怀疑。毕竟,软件界的个人英雄主义早就被证明注定是悲催的。

    • 黄余粮 站长 2013/03/20

      赞同你大部分的观点。大多数时候,写代码必然是要考虑后期的可维护性和扩展性等等。

      不过,作者在文中的一些观点,例如:“照搬模式东拼西凑,而不能抓住事物的本质,没有“灵感”,其实是设计不出好东西的”。我个人认为还是很有道理的。为了模式而模式,作者在Google遇到了,拿出来“晒晒”也挺好。

  • EG-Tails   2013/03/21

    作者有些太经验主义了。设计模式本就是从经验中提炼出来的理论知识,作者就如“飞翼 ”所评论的,抛去理论,再回过头拿经验说事。只不过抛去现有理论对于拓展思维还是有好处的。

  • kunner   2013/03/31

    装B

  • 张书艾 游戏服务器程序 2016/10/16

    看见有人骂作者装B,但是实话说,我看过设计模式的感觉也是,这些所谓的模式,在我不知道设计模式的之前,平时也在用。而且这些详细区分的名字让人难以记忆,本身就是程序及大型程序经常用到的设计方式,总结了一下,起了个名字。给新手一本这样的书,单看理论,跟流程图,没有什么意义。

跳到底部
返回顶部