《天长地久》

昨天晚上看完最后几页文字,我忍不出流出了泪,和王一样,没有声音,内心却极其悲恸。

我不知道为什么我会流出眼泪。或许是很久没有流泪了,身体里面有许多毒素需要排解一下。又或许是其他的生活琐事压抑地透不过气来,正好找到这个机会顺大便排解一下,可我知道这不太对,因为我搞不清楚究竟是什么让我一直压抑着。也可能是做大人很久了,想念起小时候在父母的环抱下,什么都不用担心地享受眼前的宁静和安详的光景。总之,我还是流泪了,很难过的,也很享受的。

我不觉的我流泪是件难为情的事情。因为我看了王小波的小说《天长地久》。

说起王小波来,我一直是后知后觉。先是听说有这么一个人,风格很特别,也很有趣。看到同学写的文章,人家说,哦,这是仿小波的风格。我觉得文章看起来蛮有意思的,于是对王小波也有了初步的好感。后来就随便找了些他的文章看看,会心笑笑,也就继续我那琐碎的日子。后来碰到了我老婆,碰巧也是个王小波迷,还有好多他的文集的书。三本某某时代,有点厚重,翻阅了些,看到了些有点黑暗和颓废的世界,于是就没有继续去看。近日,随便拿了本《天长地久》的文集,打算路上乘车的时候消磨时间。书名叫做《天长地久》,可《天长地久》只是其中的一篇小说,还有许多其他的系列,包括剧本。王小波猝死之后,他老婆整理了包括没有发表的那些出的一本册子。所以有点追忆的意味在里面。我开始不知道这些,只是随手拿来翻翻。先看第一篇,讲昆仑奴和破楼的,还有一起住在破楼里的小胡。觉着最有趣的是那句“古今一般同”,或者是它的变体“古今无不同”。又看了一篇《夜行记》,同和尚之间的对话煞是有趣,最后的辩证结果也像是抖了一个包袱,可有些玩味。老看这些古时候的东西,究竟还是闷了些。于是我一跳,翻到第二篇的第一部小说,天长地久。

说的故事是王 17 岁去云南插队的生活。那时候和小红,大许三个人一起度过的快乐而纯朴的日子。不知为什么,我对那段日子特别亲切,总好像也曾经经历过。我妈也是 17 岁那年去云南的,然后很多年后认识了我爸。在他们属马的那年生下了我,于是我也是属马的了,我们一家三口三匹马。我到现在还一直记得有张黑白照片,妈妈那时候就有些胖,笑眯眯的坐在竹椅上抱着还是婴儿的我,爸爸穿了件有些破的白色汗衫,站在一边开心地笑,瘦瘦的但很精神。旁边是一洼用竹篱笆圈起来的菜地,再旁边还有幢下面挑空的竹楼。看得出那天的阳光很灿烂。王他们三个在林子里看着湛蓝湛蓝的蓝天的时候,我也仿佛也看到了那样的天。小时候野到外面去玩的时候,也会一个人躺在草垛上看着蓝天出神,心里也像这片湛蓝的天,平顺的没有一丝褶皱,开阔的望不到边。那时候就觉得这是非常美妙的事情。王那时候和小红在一起,小红的可爱和调皮,还有温存,让王的内心有说不出的味道。他们三个留在队里写检查的时候,小红跳出来说一起去河里游泳玩水,及至后面跳在水里上下翻动,还有爽朗调皮的笑声,这都让我想起了我妈妈。这是另一张照片,妈妈还是小小姑娘的时候,站在河边,胖嘟嘟的,扎了个小辫子。妈妈和我说她小时候因为是兄弟姐妹里面最小的一个,所以最放肆,也最调皮。专门和男孩子一起玩,还一起去游泳。所以我猜想得出那时候会是怎样一个情形。王花了很多的篇幅说三个人在一起的快乐而单纯的时光。朴素的文字把那个年代最真实的一面展现在我眼前。我觉得我也投入进去,成了王的一部分。王那么的喜爱这段时光,反复表达希望可以三个人永远在一起快乐的生活。这让我略微感到些不安,似乎接下来会发生些什么。

接下来小红得了脑瘤,死了。

是的,事情就是发生地这么快,来不及准备好就已经结束了。我抹干了眼角溢出来的泪,合上书的时候,我一直在怀疑,这究竟是真的发生过的事,还是仅仅是王的一个梦。可又好像是我的梦,真实地发生在我还没有出生的那段岁月里。王对心爱的人的消逝无比心痛,就如字间喷溢出来的一样。而如今,王小波猝死,黯然离我们远去,生活是多么可笑。哪一天会轮到我们呢?不知道,但似乎结局是那么地肯定,不容置疑,也同样那么地可笑。小红说,“天多蓝啊。我有时觉得它莫名其妙。我觉得,我是从那里来的,将来还要消失在那里。”

合上书的时候,才发现书名竟然就是叫做《天长地久》。

目标驱动抉择

人们普遍喜欢带有圆角的设计,Apple 的产品充分体现了这一点。网页设计也不例外。Google 很多产品的简洁风格都在应用了圆角设计后儒雅很多。

至于圆角设计的实现,不一而足。最原始的是使用设计好的背景图片,带来显而易见的缺点就是不够灵活,无法自适应内容大小的变化。最轻松的是使用样式表定义,不过目前并非所有的浏览器都支持。再接下来就是下面两大类的实现技巧了。

其一,使用 Javascript 处理特定的容器对象。在 DOM 树上动态增加若干辅助的 div 然后通过 CSS 定位等技巧按像素级画出圆角的效果。优点是,保持 xHTML 的语义整洁;缺点是需要等待页面完全加载后才能渲染,页面数据大时可以见到延迟渲染的效果,圆角不够光滑,没有次像素辅助,圆角大时比较生硬。

其二,使用圆角小图片。有些配合表格,有些直接使用额外的 div。然后配合 CSS 在角落处应用定位好的背景图片。优点是无须 JavaScript 介入,所以一旦 CSS 加载完成(通常都比较快),页面上马上出效果,圆角可以较平滑;缺点是 xHTML 不再纯洁,冗余元素众多,并需要事先准备若干小图片。

如何选择?这看设计以何为目标。通常,开发人员(比如说我)倾向于第一种,符合了完美主义,优雅的行事风格。维护起来也轻松,还能顺便展示一下与时俱进的工作态度。这是以设计人员为导向。Google 怎么做的?很遗憾,Google 并没有遵循严格的 xHTML 设计,到处使用 table。当然不是滥用,而是用心良苦地用。因为它的设计导向是访问者。从访问者的角度看到的都是第一优先级,保持语义和高维护性处于次优先级。所以 Google 使用了第二种,并且作了很好的折衷和平衡。

这样的抉择思想同样适用于程序开发。

极限编程的敏捷思想,就是以快速实现最小系统为导向(这符合利益最大化的商业原则)。敏捷的目的并不是要赶最终项目的进度,而是要及时得到客户的反馈信息,以便减少后续开发走弯路的可能性。没有反馈,敏捷是没有意义的。很多项目开始的时候,客户都不清楚最终应该需要什么样子,所以我不同意这种情况下在一开始就使用测试驱动开发。只有反馈和需求明确的部分,使用 TDD 来确保质量才是有意义的。具体操作的时候,作为项目的主体,开发人员常常会不自觉地陷入某些细节纠缠不清,似乎不满足自己的美学需求就不算通过,无法继续工作。还会经常替客户考虑长远的更高更大的问题,以便将来到这一步时,现在的“优良设计”可以优雅地适应,自己可以减少很多工作量。可实际问题是,那一天会到来吗?有多远?这之前还有什么更重要的需要做?有相当一部分情况是,没有那一天,或者局势早就变得面目全非。这样说来,当初的铺垫所花费的时间和精力都是白费的。再好的代码实现,没有用处就等同于垃圾,并且搭上成本,连垃圾还不如。客户和用户不明白这些,也没必要关心这些。所以每个阶段,只需要关心和思考客户要什么就 ok 了。这么说来,很多开发人员会抱怨,那这一阶段完成后,客户要求改动,可能会牵涉到底层的数据,需要修改很多连带的东西,那我不是死定了?没错,很遗憾,开发人员在这个产业链中充当的只是生产劳动力的角色,这个角色有多辛苦没人关心,人们只关心这个项目是否好用有用,是否可以带来现金。敏捷开发的终极目标就是节约成本,扩大利润空间,赚钱是第一导向。所以生产者可能出现的弯路和复杂劳动都是在此导向下次优先级的,是可以屈就的。当然任何有人情味的人都不希望看到开发人员如此受苦,但没有办法,将来的需求就是风险,要规避风险必须有代价。敏捷开发就是用来拯救开发者的 -- 必要的开发不能少,但绝不浪费多余的。在每一个阶段使用最小系统实现,在当前阶段就确保了最低陈本,风险最低。如果各种原因导致项目流产也就不至于损失更多。下一个阶段时,重新评估,并在此阶段下最小实现。结合对减少每个阶段的时间长度的控制,通过得到的反馈来调整阶段目标,就可以时刻保持风险最小化。因为即便哪一天有重大的需求变更而导致大量的代码重写,也可以向客户有理有据地要求额外的报酬,开发者也能相对平衡些。当然在开始时没有全面完整地了解需求则另当别论。

总的来说,就是目标驱动抉择。目标是什么?优先级就该怎么分。如果要赚大钱,就去做生意;如果要在技术领域成为专家,就可以不计成本死命钻研;如果只是糊口,就去找一份符合自己兴趣的工作,完成老板交付的任务。不要考虑任务是否合理和公平,只管去敏捷实现,这才是你的价值。如果你坚决认为任务的荒谬或者老板的不可理喻,那就到了该去考虑换一份工作的时间了。

Google 希望用户开心,所以宁可代码稍显丑陋。敏捷开发希望及早收钱,所以宁可将来再投入更多。

Google Ads

IE 下 JavaScript 调试

本来在 FireFox 下用 FireBug 是一件很美好的事情。可绝大多数的项目都还需要在 IE 下面调试。开始的结果总是惨不忍睹。除了 CSS 要加很多 trick 之外,如果 JS 报错,就麻烦了。IE 只是很笼统地给出一些错误信息,给出一个内部的行号,字符位置和抛出的异常名称。很难在此基础上发现并解决实际的问题。就算用了 FireBug 的 Lite 版本,也好不到哪里去。只能靠经验摸索,恼人得很。

今看到 gugod 介绍 Jash 貌似不错的样子,有机会在接下来的工作中用用看。

jQuery.js 和 Prototype.js

实在忍不住要写点什么了。我被这两个 JavaScript 搞死了。它们都让我又爱又恨。

Prototype.js 出来得早,随着 Rails 的开发而逐渐扩大影响力,成为 Rails 框架下御用 JS 框架。所以秉承了 Ruby 语言的一系列概念,非常清晰地用组织良好的类,对象扩展的方式,增加了各种常用的 handy 函数或者方法。所以叫做原型么。学习曲线低,顺手拈来。

不过这种循规蹈矩的做法很快让书写它们的人感到厌倦。很多操作都要加上类名,繁复、生硬、罗嗦。于是 jQuery.js 得以进化为,用最自然的,类似伪代码的形式,完成相同的功能,并具有更好的可读性。比如:

$(".rborder").corner("5px").parent().css('padding', '1px').corner("round 5px");

一气呵成,痛快极了。想象不出还有什么写法可以比这个更简洁达意。而 jQuery 的哲学就是:写最少的代码,做最多的事情。

而这种写法,像极了 shell 下面使用管道符串联起来的一系列命令,简单、优雅、强大、灵活。喜欢用 Perl 写代码的一个原因,也是因为其中的 map 和 grep 组合所构造出来的类似效果,清晰、流畅、自然。所以 jQuery 是很讨开发者的欢心的,用起来舒服。

用起来舒服,这件事本身没什么伟大的,可一舒服,写程序的人就兴奋起来了,就会很高兴地去发明些什么,这种内在激发的驱动力一爆发,就造成了现在 jQuery 插件遍天下的格局。这和 Rails 本身敏捷而富有艺术性的气质所带来的全球影响力的爆发是一致的。

不过这带来了一个问题。插件满天飞,怎么保证质量和兼容?自由带来的多样性是件好事,太多了就分不清楚谁是谁了。虽然 jQuery 提供了统一的 svn 仓库,不过各式的插件的文档,测试,演示等等,各自为政,颇为凌乱。或许需要一个类似 CPAN 一样的统一管理介质?

jQuery 对 DOM 对象的操作很容易--主要是很舒服,可要处理数据的时候,就不那么舒服了。我总是对 prototype.js 中的 inspect(), join() 念念不忘,可 jQuery 没有,好不容易看到一个 Array 的插件,提供的功能也是捉襟见肘。所以我目前的结论是,对页面元素的控制上,用 jQuery,对数据的处理上,用 Prototype.js 。

还好,jQuery 只是在自己的命名空间里面东奔西跑,按照标准的方式,两者可以共存。不过 jQuery 为了 write less,默认情况下,将自己的类捆绑到 $ 函数上,于是,这一强大的内激效应让一些插件的作者忘掉了这只是一个快捷方式,只要在插件内部也使用这种写法,就会和 prototype 冲突。比如说:ThickBox 3.1

开会去了…