2012年2月17日星期五

《Ruby 元编程》书评

远超预期的惊喜
在出行前的一天拿到这本书,翻了几页,感觉不错,心里很有些纠结。要出远门的原因,衣物和工作设备之外的东西要尽量精简。 书籍方面反复挑拣,正在读和很想读的几本书,也都只好先放下,最后带上了这本新书和一本工作用书。

在飞机上拿起这本书后,一边读,一边用笔勾划记录,三小时的班程,一气读完了半本。 然后在大巴、城铁和地铁上,一直到放下行李,阅读到半夜,翻到附录C结束,才满足的放下。

这么多年来,只有三本书给过我这样的体验:编码的奥秘、《设计模式》(GOF),和这本 Ruby元编程。 如果考虑编码的奥秘不算技术书籍(科普或教育类),那么本书和《设计模式》是仅有的两本。

动态语言的《设计模式》
事实上,我不是 Ruby 程序员,也不是 Ruby 语言的爱好者,甚至不算是 Ruby 语言的用户。 我是有十年学习经历的 Python 爱好者,前 C# 、 CPP 、 Delphi 程序员、 现在是专业的 Objeictive C 工程师。 在读到本书之前,Ruby 对我来说,是一个有趣,但是没有足够的兴趣去深入的技术。

这本书和 《设计模式》 的一个共同之处还在于,它同样是讨论编程模式的书籍,甚至可以毫不夸张的说,本书堪称动态语言的 《设计模式》。

这本书以 Metaprogramming 为主题,深入讨论了基于 Ruby 的各种编程模式,而这些模式,可以通用于各种动态甚至静态语言。 在阅读过程中,我不断的联想起过去在各种语言中学习到的知识,现在,它们被本书的作者 Paolo Perrotta 用 Ruby 语言, 用他构造的精彩的文字编织起来。

在本书中,我找到了 Python 的参数化 yield、decorator,元类,MixIn, Perl 的 eval,C# 的 using (Python的with),闭包, Smalltalk 的 extend(objective c的category),lambda、block 等等等等。通过这本书,不仅仅了解如何在 Ruby 中使用这些技巧,还有如何用 Ruby 实现它们,或如何用 Ruby 的语义来解释它们。从而,理解这些东西以后,也就可以将它们应用于 Python、Perl、PHP、Objective C,甚至 C++ 和 Java。书中的知识,完全可以视作是动态面向对象领域的《设计模式》, 特别是附录中总结的各个条款。

通过这本书,我们还可以了解到为何 Ruby 看起来如此与众不同,它的设计目的,实现方法。我们会了解到 Ruby 中大量的内置方法, 其实不仅仅是魔术方法,它们其实是基于一个很小的理论集合建立起来的公理体系。 Ruby 语言的设计,关键字只是一部分, 基本对象的设计甚至更为重要,基于一组精心设计的接口方法和一个作用域理论,就形成了 Ruby 优雅的语义模型。 程序员在编写 Ruby 代码(甚至是其它动态语言,甚至 objective c)时使用到的各种方法, 都是基于这个很简洁的理论内核推导演绎而成。这里面的魔法非常少,但是完整的描述了动态面向对象的各种设计方法。 甚至可以说,Ruby 是 Samlltalk 族系的 Lisp。读过这本书,我们可以理解,为何 Perl 社区的传奇人物唐凤会评价" Ruby 就是没做广告的 Perl6"。

这本书,我强烈推荐给 Ruby 程序员、爱好者和其他对面向对象知识、程序设计理论有兴趣的人。无论你是否使用 Ruby , 只要可以读懂书中的代码,就足够从中受益了。这并不需要很好的基础。当年我读《设计模式》的时候,对Smalltalk一无所知, CPP 也不算非常了解。现在读这本 《Ruby 元编程》之前,其实也只读过 Ruby 和 ROR 官网的 Tutorial, 但是靠对 Python 和 Perl 的了解,同样可以顺利的阅读本书,相反还从中学习到了大量的 Ruby 语言知识。

深入 Ruby 编程的化境
本书可以当之无愧的称为 Ruby 编程的高级技术教程。虽然全书讨论的话题紧紧围绕"元编程"这一主题, 但是涉及了软件开发的很多问题。分析问题、解决问题、构造测试的各种步骤,对 Ruby 的运用出神入化。 而且基于故事背景讲述,语言生动自然,言之有物,绝不会让人感到乏味,可以说是针对 Ruby 语言的优秀教程。

精彩回顾
在阅读本书时,有很多片段令人赞叹。我这里举几个印象比较深刻的:

一切皆对象

曾经有个说法,Python 是面向对象的,Ruby 是面向类型的。本书回答了这个问题,Ruby 确实是完全面向对象的, 而且,它在语义上更为纯粹。Ruby 可以用自身的代码完整的解释自己的对象模型,包括核心的基础类和方法。设计 Ruby 语言,包含了设计它核心的对象和对象方法,这在现代的编程语言中是常见的,但是 Ruby 做的特别彻底和优美, Ruby 很好的继承和发扬了 Smalltalk 的思想,它对面向对象模型的抽象,就像 Lisp 对程序语言的抽象一样彻底。

Ruby 的对象模型中,对象、类、本体类(Eigenclass)、作用域、消息、self 等重要概念, 和它们的实用意义,都在本书得到了阐述。

作用域的封装、访问、互操作

Ruby 有严格完整的作用域限制,在本书中有详细讨论,包括不同作用域之间如何互相隔离,又如何在它们之间传递信息。 基于作用域,衍生出了 block ,然后是 lambda 和 proc 的使用、原理、区别。

扁平化作用域、洁净室、闭包等概念,都在实例中讲解清楚,Python 程序员可以借鉴这些知识,深入了解 yield 和 nolocal 等知识。

书中还讨论了类和模块的区分。

eval 族系

Ruby 有 eval、instance_eval、class_eval 三个不同的eval函数,它们可以接收字符串或代码块, 这比 Python 的 eval 要复杂,但是从理论高度理解,就会发现它们相当的严谨和简洁。 这些方法可以帮助我们构造或访问特定的作用域,或许会让 Python 程序员想到 yield 的使用。而 Objective C 也已经加入了很多 block 支持。

Perl 的 eval 经常用于异常处理,本书也讨论了 Ruby 的一些异常处理技巧。

提到异常处理,文中专门有一个例子模拟了 C# 的 using 关键字,这个关键字曾经是我面试 C# 程序员时的考题内容。将这个例子稍加扩展,就可以编写一个类似 Python 2.7 中多参数 with 的实现。

Eigenclass ,面向对象和类型约束

Ruby 引入了 Eigenclass 概念,它优雅的解决了 duck typing 和对象类型之间的矛盾。 instance_eval , class_eval 和 method_missing 等方法,组成了 Ruby 的动太对象操作集。它们使得 Ruby 在类型约束和动态对象之间游走自如。 相对于 Python 的 duck typing 风格和 Java 的静态约束,Ruby 更为平衡, 允许用户自己选择约束与自由的平衡点。相对于在 Java 中使用反射或 Python 中使用约束,Ruby 无论倾向哪一种风格,都不会付出太高昂的编程代价。

学习这部分知识时需要注意的时,Ruby 中的单件(Singleton)不代表通常意义的单例模式, 而是通常说的动态对象,即 duck typing。

MixIn 和其它类型扩展方法

类型混入(MixIn)在 Python 中也是重要的元编程技巧,著名的 Python 编辑器 Ulipad 就大量使用了这种技术。Ruby 对 Mixin 的支持更漂亮,也更灵活,这个技术在书中反复使用。

Ruby 同样继承了 Smalltalk 的 extend(这里指 Smalltalk 的 extend , Ruby 的 extend 则表示了不同的含义) 方法,这个技巧在本书一开始就有介绍,并且反复使用。

Objective C 虽然没有 Ruby 这样丰富完整的面向对象语义(相对来说,objective c拥有 C 级别的运行效率和底层访问能力),但是学习 Ruby 的各种类型扩展技术, 可以帮助我们更好的理解和运用 Objective C 中的 category 等技术。

符号与文本

对文本直接 Eval 当然非常灵活,特别是 Ruby 具有 Perl 和 PHP 的变量内插能力, 但是它也有其缺陷,书中详细讨论了这个问题,介绍了一些应对方法。LISP 程序员相信会注意到 Ruby 有在符号和文本之间进行转换的能力,这就像 LISP 宏和 Python 自省的结合,好吧,Ruby 也有自省,而且更强大。

Objective C 程序员也可以从中增强对 SEL 和 @selector 等概念的理解。

本书中多次使用的类宏,不同于 LISP 的宏,虽然它也是一种生成技术。这一点 LISP 程序员不要简单代入。在我看来, LISP 宏与 Ruby 类宏的差异,比它与 CPP Template 的差异更大。

属性、访问器与幽灵方法

属性封装、访问器等概念在多种语言中都有体现,本书用 Ruby 的各种内置方法和设计方法, 向我们展示了这些概念在语义上到底是如何被设计和理解的。学到这些知识,对 Python、 和 C# 等领域的程序员,理解日常工具中出现的 property 技术,也有很大帮助。

深入阅读 method_missing 相关的知识,不仅可以了解 Ruby 的动态属性和方法技术, 还可以帮助我们深入了解为何 Smalltalk 观点中的对象是消息驱动, 而非表面看来简单的函数执行。Objective C程序员也可以借此更好的理解 KVO、KVA 等技术。

请深入阅读

阅读本书对于编程语言控、设计方法控,是莫大的享受,即使我这个从来没有实用过 Ruby 的门外汉,也感到了不能自拔的愉悦。我这里只是凭印象选择了一些让我激动的点来介绍。 书中的精彩,只有自己去阅读才能体验。

除了方法讲解和生动的故事实例,本书还穿插介绍了很多 Ruby 的第三方资源, 包括著名的 ROR。

我向我的同行强烈推荐这本书,阅读它,各种不同技术的使用者都会不虚此行。

说说反话
尽管读完这本书以后,或许你也像我一样对 Ruby 产生了浓厚的兴趣,但是我要提醒本文的读者, 不要误认为 Ruby 是解决一切问题的完美方案。Freedom 不是无代价的, Smart 同样不是无代价的。 Ruby 强大、优美、完备的语言设计,需要付出很高的性能代价。

相对来说,尽管我不断的在文中提及 Python 比之 Ruby 的模型,如何简陋,但 Python 的确有性能优势,它剪裁了 Smalltalk 理论中的一部分,通过建立在 C 语言环境上的字典模型实现出来。这使得它的动态模型非常容易理解,并非像 Ruby 这样充满了魔幻和神秘感。而且 Python 代码很容易获得更高的性能。尽管 Ruby 的近几个版本在性能方面有了长足的进步,但是 Python 仍然远远的将其抛在后面。前有 Bigworld、 EVE、stackless Python,后有 Torando 这样的高性能应用,充分证明了 Python 作为架构级技术,在性能方面有足够优秀的表现。恰到好处的语言设计, 也使得它在开发效率上,仍处于最优秀的几种语言之列。

对于喜欢脑力风暴的 GEEK 程序员,即使有了 Ruby ,也不等于其它语言就不值得学习和使用。性能、 表现形式,或特定领域的突出表现,都会促使我们做出选择。例如 Perl 的锋利,LISP 的美感, LUA 的轻捷。但是无论你是哪一种语言的使用者,只要你对面向对象、动态模型或编程有兴趣, 我都诚挚的向你推荐这本 《Ruby 元编程》。

CSDN 链接 http://blog.csdn.net/ccat/article/details/7269765
豆瓣书评链接 http://book.douban.com/review/5309900/

1 条评论:

Saint John 说...

Ruby的instance_eval方法在创建DSL时相当有用,不知道Python有没有类似的方法呢?目前我是直接将外围作用域的locals()传到方法里执行实现的,刘老师有更好的建议吗?谢谢