Archive for 2010年4月

技术的暴力美学

2010/04/27

When in doubt, use brute force.
—— Ken Thompson

Keep it simple, stupid!

在『天涯』上看到一个帖子提到米格-25。这个前苏联空军中神秘的家伙当年经常在北约的雷达上以三倍音速一闪而过。在以色列曾经遭遇 F-4 并且被后者占据尾追位置发射了空对空导弹,结果是 F-4 看到米格- 25 在导弹发射之后突然加速离开。以当时北约国家 —— 主要是美国 —— 对航空技术的理解,要达到米格- 25 展示出的能力,苏联非掌握钛合金加工工艺不可 —— 在三马赫速度下产生的高温中,除了钛以外,任何低密度金属都会变成橡皮泥,可是即使是今天人类对钛金属的加工能力仍然很有限,完全无法令其成型为航空器零件。还有,为了完成被赋予的防卫广阔的西伯利亚的任务,西方认为米格- 25 必然拥有精巧的机载电子设备。

当 1976 年一个叛逃的苏联飞行员给西方送来一架米格- 25 的时候,后者迫不及待的要看看心目中尖端的机身工艺和电子技术。结果,发现这个三倍音速飞行的家伙竟然是个大钢锭 —— 几乎完全用不锈钢这种在西方看来连普通飞机都造不了的重金属。整架飞机用可称为『狂暴』的发动机才体现出邪恶的航空特性。那个能蹲下一个成年人的喷口最能说明其狂野,不光巨大,而且固定在最大状态,完全没有任何调节机构 —— 在维持三马赫速度而产生的高温下,任何多余的机构都是巨大的不稳定因素。困扰了西方十几年的关于如何实现三倍音速的机身加工就这样被苏联用暴力一举攻克。

还有西方幻想中先进的机载电子设备,不过是把大量的电子管塞到硕大的机头中。如果在地面打开机头的电子管雷达,能把前方 100 米内的生物烤熟。

北极熊独一无二的风格把技术和暴力美学联系到一起。这是人类在技术有限的前提下追求极至的精神。如果有一天人类认识宇宙的能力走到尽头,还能够依靠这种精神在探索的路上走很远。刘慈欣的《三体II · 黑暗森林》和弗诺 · 文奇的《天渊》幻想的就是这种无奈但又令人神往的境地。只是半个世纪之前那个神秘的红色帝国已经在这个境界肆意驰骋了。

Open Source 的界限

2010/04/20

最近一件有意思的事情是 Oracle 质问询问 Open Solaris 社区从一个 Open Solaris 这样的 open source 项目如何盈利。老实说比起 IBM 这种虚伪的家伙,我更喜欢 Oracle 的直率 —— 本来么,这个问题几乎人人心中都有。那么,为什么有的 open source 项目 —— 比如 Linux kernel、WebKit、GCC 可以蒸蒸日上;而另一些,比如 MySQL、Open Solaris 则奄奄一息呢?

其实答案还是在于那句老话,open source 是程序员写给自己的工具,它的生存不取决于盈利,不沿循普通的商品交换的资金流动途径,而在于直接提高其创造者社区的生产力。一个 open source 项目能否生存,在于其用户群能否成为自身的维护者和改进者。所以,第一等天然的 open source 项目是程序开发工具。第二等天然的 open source 项目是各种各样的库。同样的功能,提供 GUI 和提供 API 对于一个开源项目来说是生死攸关的差异。使用 GUI 的人极难成为一个产品的维护者。使用 API 的人不是在真正的『使用』产品,而是在创造自己的产品,同时他们有能力也乐于成为他们所依靠的 open source 项目的维护者和改进者。所以作为开源软件 WebKit 之类的库能够得到比 FireFox 之类的成品浏览器更好的发展。事实上,要求 FireFox 把自身的结构整洁化以便能够剥离出其『核心』功能供其它类型的产品使用一直是业界对 FireFox 的一个要求。

一个 open source 项目提供的能够将被其他开发者自由的集成到其它产品中的紧密度是它能否生存的关键。在这一点上,GPL 许可证的项目都游走在生死线上,因为它们很难把自己作为一个非 GPL 产品的不可分隔的一部分。只有 Linux kernel 可以算一个例外,因为 kernel 的特殊边界保证了它可以集成到其它非 GPL 产品中。而 LGPL 和 BSD 的项目就可以生活的好一些。诸如 MySQL 之类的产品,GPL 版只能作为独立的服务集成到商业产品里,自然不如 SQLite 这样能够被无缝集成的项目发展得好。

网络改造

2010/04/13

长久以来家里的网络由一套繁复的配置构成。首先是网通的 ADSL modem 连接电话线;然后是关闭了无线功能的 Netgear 无线路由器连接 ADSL modem,负责 ADSL 拨号;最后是 Apple AirPort Express 用桥接(bridge,也就是 AirPort 本身没有 IP 地址)方式把 Netgear 的网络扩展到无线。这么麻烦有两个原因:第一,Netgear 无线路由器太旧,所以 Mac OS X 10.5.6 之后的系统和 Netgear 无法正常工作(网速奇慢);第二,ADSL modem 太旧,Apple AirPort Express 没法驱动它无线拨号。

这么凑合着用了一年多,最近不知何故网速越来越慢。于是用 MacBook 直接连接 ADSL modem 想看看故障出在哪个环节。发现原来家里的 MacBook 和 MacBook Pro 也都没法在这个 modemo 上拨号。总之只要是 Apple 的设备和这个 modem 就不对付。还好在别人家的 ADSL 上用 MacBook (Pro) 成功拨号连接过,所以能证明问题不是出在 Mac 上(或者至少只是一个对旧协议的兼容问题)。

这一年凑凑合合用网络的体验,加上发现这个 modem 不能支持 Mac,终于决心请半天假让网通的人过来修一下。网通的人来了之后看了半天没看出什么所以然(老是叨唠在 PC 上出什么 618 错误在 Mac 上看不到),拿个新型号的 modem 一连我的 MacBook 就好了。赶紧掏钱让来人留下新 modem 离开。

打发走网通的人之后赶紧用 AirPort Express 连上新 modem,傻了,ping 外网不通。换上 Netgear 的路由器,傻了,新 modem 的指示灯也不闪。靠,刚才光顾着用 MacBook 连上高兴,忘了当面用路由器试一下了。心想打电话兴师问罪之前还是确定一下,用 MacBook 连上接着新 modem 的 Netgear,ping 通了 —— 原来这个新 modem 连无线路由器的时候灯闪的频率很低,绝了!

那么接下来就是 AirPort Express 的拨号问题了。我从来没在别人家用过这个 AirPort Express(只用过 MacBook (Pro) ),所以不好说网通的问题是不是已经被新 modem 解决了。又走了几遍 AirPort Configuration Utility 的 Wizard,还是没什么改观,只是记得以前配置的时候选项不是像今天的 Wizard 显示得这么少啊。忽然发现了这个『 Manual Setup 』按钮,点进去果然气象万千。

发现这个 DHCP 的地址段被配置成了 10.0.1.2。赶紧改成 192.168.1.2(如果设置成 10.0.x.x 的话,在 Internet -> PPPoE 这个 tab 里显示的 AirPort Express 的 router —— 估计是缺省网关 —— 总是 192.168.x.x,而不是从 ISP 传过来的)。

重启之后,终于拨号成功。

于是,我想,是不是这一年多不能用 AirPort Express 直接拨号的原因都是因为这个而不是什么旧 modem 不兼容?吓!没精力深究了。反正旧 modem 用 MacBook (Pro) 也拨不通不是?反正得换。下面是换下来退休的 modem 和 Netgear 路由器。

最后,这次改造的成果是网络快了不少。看来上面这两位里某个(或者两个)就是罪魁祸首。终于可以重新享受在床上看美剧的乐趣了。

唯实用主义

2010/04/11

Joel 的 Blog 是个很有意思的关于软件开发的网站。里面有不少睿智的看法,比如『抽象泄漏』。但是有时候 Joel 的实用主义实在有些过度。只要两个方法都能解决同一个问题,就对它们进行无限制的无差别化,这就失去了从更高层次分辨优劣的能力。比如这篇 2003 年的《Biculturalism》,试图和 Eric Raymond 的《Art of UNIX Programming》唱唱反调。

试图和《Art of UNIX Programming》唱反调的 Blog 不止这一篇,比较新的还有这篇微软雇员写的。我觉得,以一篇 Blog 的篇幅想挑战一本书的观点,前者天然的处于下风,除非能一针见血的指出后者根基上的肤浅。可惜,Joel 的 Blog 只是说 Raymond 的观点稍稍过于执着;微软雇员的那篇则是在自设了很多假定的前提下玩逻辑游戏。如果你只是想说对手的观点稍稍有些过激(而不是全然推翻),或者想玩复杂的逻辑游戏,在篇幅和对手差一个数量级的情况下大多是自取其辱 —— 你很难有比对手更细致的分析,也很难把一个逻辑推导所需的前提假设的历史根源阐述的比对手更清楚。

回到 Joel 的这篇《Biculturalism》,开篇头一句『By now, Windows and Unix are functionally more similar than different』。看到这句话,非但没有感到 Windows 和 UNIX 之间的分歧有越来越小的迹象,我脑海里首先想到的就是kernel mode 下的 Windows GDI [1] —— 今天主流操作系统里唯一放在 kernel mode 里的窗口管理和图形界面系统,还有和 GDI 紧紧绑定的 window-based toolkit [2]。也许细心的读者会提醒,人家 Joel 说的是 functionally,你说的差异是 architectural。那么,架构上的差异是否完全对功能透明呢?我看 Joel 自己也不完全这样认为(比如『抽象泄漏』)。就像 Apache Web Server 在 Linux 上缺省采用多进程,在 Windows 上采用多线程 —— 架构上的差异导致的性能差别也会让功能的可用性发生质的改变。

Joel 说,UNIX 的文化在于崇尚为程序员提供便利,Windows 的文化在于崇尚为用户提供便利,我们最终是为用户而不是其它程序员提供产品。说这番话的时候 Joel 一定忽略了 Raymond 书上的引用的 Ken Thompson 的这一句话:

This is a consequence rather than a goal. I abhor a system designed for the “user”, if that word is a coded pejorative meaning “stupid and unsophisticated”.

问题在于,忽略了架构上的简洁的系统,是否还能可以提供完全相同的功能?比如我们提到过的,Windows 把 Toolkit(按钮、下拉框、文本框 ⋯⋯)放到窗口管理的 GDI 架构中,每一个控件都是一个窗口,其中还夹杂了直接访问硬件显存的 Direct Draw 窗口;而 UNIX 的窗口管理器一般采用 Toolkit-Agnostic 方式,窗口管理器只知道窗口的内容是一组二维像素,其中的 Toolkit 完全由应用程序空间的代码绘制。『实用主义者』会说,哪个用户会关心这些?不过,用户总是有设计者原本意想不到的应用场景。比如,今天的应用软件很多时候都加入了平滑动画功能 —— 当窗口的内容改变的时候,软件会显示一系列的中间状态。像图片旋转 90 度这样的操作,往往会短暂的显示中间的旋转状态。通常在旋转的过渡状态矩形图片的角会超出显示区域(因为我们都知道矩形的对角线比边长)。在一个 Toolkit-Agnostic 的窗口管理方式里,因为图片不过是一个像素组,超出的部分会被自动 clip。而在每个控件都是独立窗口的系统中,像 Direct Draw 这样的浮动窗口的显示在这种情况下是很难不显示出丑陋的一面的。如果这个例子只是个美观问题,那么用户还有更为严肃的应用场景。现在使用 VNC 一类的远程控制软件的用户很多。VNC 这类软件在 Linux 和 Mac OS X 上很少出问题。因为 VNC 对于传输基于像素的 Toolkit-Agnostic 方式的显示处理方式单一。而在 Windows 上,VNC 程序遇到不同类型的控件就会有很多问题 [3]。

所以,当 Joel 声称 Windows 和 UNIX 在功能上趋同,而且 Windows 更注重最终用户的时候,他既忘记了自己提出的『抽象泄漏』理论,又忘记了用户总会用意想不到的方式来使用你的软件(stupid and unsophisticated)。这也是唯实用主义在嘲笑别人热衷于设计的内部简洁的时候总是犯的两个错误。

脚注

  1. 关于 GDI 处于 kernel mode 这个问题,按照一般的思路人们会归于旧的 PC 硬件的性能遗留的历史问题。有趣的是,事实正好相反。在 NT 4.0 之前 GDI 是在 user mode 的。
  2. Window-based Toolkit,即每个控件是一个独立的窗口。这样的设计下,窗口管理器必然介入控件的层次关系的管理和消息的分派。与之对应的是 Toolkit-Agnostic 窗口管理,即窗口管理程序不了解控件是如何存在的。整个窗口内容是一个像素矩形区,比如在 Mac OS X 里,控件完全由 Cocoa 或者 Carbon 库生成和负责 sub-window 级别的消息分派(这两个库连接到应用程序的进程空间)。UNIX 的 X 是提供一定程度的 window-based toolkit,不过现代的 Linux/UNIX 程序一般建立在 GTK/QT Toolkit 之上,绕过了 X 本身的控件,此时 X 也作为一个 Toolkit-Agnostic 管理器存在。
  3. 当然这不是 VNC 协议本身的问题,而是具体 VNC 程序实现的问题。不过关键在于 Windows 的架构让 VNC 程序的实现和测试比 Toolkit-Agnostic 下的 VNC 程序更复杂也更费时费力。