工具-不会用不丢人,怕会用才丢人

工具就是进行生产劳动时所使用的器具。工具的目的在于提高生产劳动的效率。感慨于一些真正的Geek的blog,我也想了一些工具对于我的重要意义,用来作为下一段的目标。

人家说工欲善其事必先利其器,还有磨刀不误砍柴工,实际上在说明工具对提高工作效率真的非常有意义。

今年的我,上游离于前端开发和后端开发之间,同时我还要在两个不同的团队(ThoughtWorks StudioCruiseMingle两个产品开发团队)之间切换,所以对于我来说频繁的需要Context Switch(工作环境切换)。两个团队所使用的技术也不同。

  • Cruise是一个标准的Java团队,大家的开发工作站都是Ubuntu环境,IDE是Intellij IDEA,源代码控制是Mercurial(aka. HG),自动化构建脚本基于Ant,持续集成工具就是自己开发的Cruise。
  • Mingle团队是标准的JRuby on Rails团队,大家开发机器是Macbook pro或者Mac mini,编辑器是TextMate(JRuby部分有IntelliJ IDEA的工程),源代码控制是Git,自动化构建脚本基于Rake,持续集成工具有两个,其中提交前使用的precommit CI是基于我们公司的开源产品CruiseControl.rb,而主持续集成服务器是基于Cruise(也就是前面那个团队的产品)。
  • 两个团队所使用的敏捷环境是Mingle,用过Mingle的朋友知道,这个NB的工具的可配置性很高,这两个团队的Mingle项目模板区别很大。
  • 这两个环境的区别还是相当大的,而且每次我切换了团队(大约2个月的周期),我很有可能就需要很大的更新我的Macbook pro上面的各种库。
  • 当我做前端开发的时候,我还要切换与我的Mac上的Photoshop CS3和Mac的VMWare Fusion上的Fireworks中(使用Windows的Fireworks的原因是授权,我的正版授权是Windows的)。使用Fireworks的原因是我们的设计师使用它,所以我需要使用它来调整一些小的设计。
  • 在做Javascript逻辑的部分,我需要在Firefox 3/2、Safari 3、IE6/7(VMWare Fusion)之间切换,每个浏览器都有不同的附加调试工具(主要的三个Firebug、Inspector、IE Dev toolbar)。

我想对于一个强悍的程序员(最近比较崇拜的delphijhdcola云风等神人)来说做这样的环境切换也许还是可以的。可是对于我这个不善于multi-task工作的人来说,马上让脑子适应不同环境,熟练使用不同的工具就成为了一个挑战。

所以,结果是,这一年中,我基本上对于这些工具很少深入学习,基本上就是凑合着使用,如果没有通用的快捷键我就懒得去翻手册学习了。结果就是使用HG的queue功能(超级有用的qnew、qrm、qpop、qpush系列)的时候经常把自己搞崩溃(今年居然有和李彦辉教授在pair的时候搞丢了2个小时内的修改,相当丢人),所以后来在使用HG的时候异常小心,生活在心理阴影下面。而对于Git,我居然完全没有使用过stash功能(和HG的queue类似)。昨天胡凯还问我是否用过bisect,是一个折半查找坏提交的功能(在HG和Git里面有等价的功能),我完全没有使用过。因为这些精巧的基于命令行的源代码控制工具对于程序员来说非常之重要,从这个角度体现了我对于工具的不求甚解达到了什么程度。突然想到梅兰芳里面十三燕那个很棒的台词“输不丢人,怕才丢人”,用不好工具没事,但是害怕学习用工具那就是很丢人的问题了。

那么自我分析的结果就是,由于环境切换,我缺少了专注,形成了对学习环境中的工具的恐惧,最后影响了我的工作效率。

下面的内容用来自勉,分析一下工具对于我到底有多么的重要(也就是说这个是我使用和学习工具中比较Happy的部分)。对于还没有注意到工具重要性的朋友,可以关注一下,看看是否有所借鉴。

  1. 关于GTD:去年看了不少退墨的文章,我深感这种意为减轻压力的“Todo list“对我的重要。最早我使用了文本文件来记录,每天一个文件。但是后来发现跨天完成的任务使用这种方式不好,需要手工拷贝。所以后来按照每个Context(家、单位、电脑、手机…)放一个文件,然后使用日期作为风格,跨天的任务我就拷贝一下,这个文件本身放在EverNote里面实现多平台共享。但是后来我发现这样也不好,因为不明显,也不好做计划。再后来我开始使用iGTD,发现似乎不错,它的结构比较简单,而且它分开了context和project两个概念,所以像“OpenParty、Mingle、Cruise、梦想”也有了自己的归宿。GTD的做法,please google之。
  2. 关于工作和休息的切换:一开始我惊艳于Livid修改过的TimeOut这个软件,但是它运行的经常很慢。后来我使用了原版的AntiRSI这个抗劳损软件,它的原理就是根据你设定的时间提醒你做短休息(一般是15分钟,站起来休息30秒),还有长休息(一般是45分钟,站起来休息5分钟)。再做结对编程的时候弹出它可能你的pair会有意见,但是你需要通过它的实际效果来感动他们。结果是Mingle的队友已经基本上都在使用它了。
  3. 分布式版本控制工具:DVCS可以帮助你更好的管理本地分支,让分支变得轻量,而且它还可以帮助较大的分布式团队更好的管理自己的本地主干。而且他们里面还有很多帮你管理提交习惯的工具,比如前面提到的提交队列工具,可以鼓励你使用更加频繁的本地提交。当然使用分布式版本控制工具的前提就是你要仔细阅读一下hand book,学习一下他们的基本概念和原理,这样才能达到更好的效果。
  4. Feeds工具:我使用Google Reader阅读文字型RSS Feeds,使用iTunes订阅Podcast。
    • 阅读工具多了去了,你的选择很多。但是要做的是学会更好的使用这些工具。今年从Patrik lightbody那里学会了重构Rss Feed订阅的重要性,要减少一个feed使用多个tag进行管理,因为一般鼓励在一定时间段里面保持未读feed不要积攒太多(这就失去了持续阅读的能力),但是如果使用多个Tag标记feed,那么在统计未读条目的时候往往会重复统计,会造成很大的阅读压力,而且对于给自己的不同feed组定不同的优先级也不利。
    • 所以我首先做的是将所有的订阅单一化,分类清晰了很多。分类有一个小技巧,不要对个人博客按照主题打标签,比如以前我给robbin的博客打上java的标签,而livid打上了apple的标签,那么在我决定要看哪个标签下的主题的时候就会感觉很迷惑,因为个人博客都没有固定主题,所以这些标签就编程没有意义的误导了,所以我现在对于这类feed直接标记为“Interesting Person(有意思的人)”,我可以给这些人很高的优先级。
    • 另一类是如GizmodoLifehacker这种信息门户型,他们每天要更新50+的新条目,所以我把他们放到一个单独的如news portal这样的分类里面,我可以给他们很低的阅读优先级。
    • 不同优先级的条目在Google reader里面还可以对应列表/展开的方式查看,可以很好的提高使用效率。再有就是Google Reader的快捷键,在吃午饭的时候,右手用来吃饭,左手可以通过一个空格健来实现滚动和查看下一条,s是标星,Shift+S是共享,这个基本上就可以实现单手阅读了,很方便。
    • Podcast是坐地铁上班时很重要的学习工具:因为地铁和很多交通工具非常拥挤,即使带上书也没有空间看(尤其时备上电脑上班的我们)。所以在非常拥挤的时候我会选择听音频的Podcast,如锵锵三人行(了解时事)开卷八分钟(了解好书,不过越来越没意思了)、Ruby on Rails Podcast(Rails的)、RailsEnvyTackSharpJDD主讲的关于摄影)等等。在不是那么拥挤,也就是胸前有10厘米以上空间的时候,我会选择看视频Podcast,最精彩的是TED Talks的演讲,不错的有Apple Quick TipsX-Play Game Previews等。用这种方式消磨时间比用PSP好很多。这是一个购买iPod touch 2的理由^__^
  5. 信息分享服务:这个又是一个很大的话题。大家在聊天的时候经常感觉很有收获,原因是兴趣相投的人在互通有无可以带来很多的有用信息,而不是像电视的新闻节目或者报纸那样给你带来没有针对性的噪音。社会化网络SNS实际上是个很好的分享有用信息的平台,可是我不是很喜欢facebook等给我带来的参与压力,所以我一般通过一些通用的分享服务来满足自己的需求。
    • 我一般通过Last.fm来实现音乐播放历史的跟踪,通过它的推荐服务来发现一些我喜欢的音乐。这实际是一个相关度算法的应用场景,它不同于简单的试听型的网站(现在国内的xiami.comkedou.com我觉得基本上属于这种类型),它的目的不是给你知道的音乐听,而是根据你听过的音乐推荐你一些音乐听,收集音乐品味的过程叫scrobbler,我在使用iTunes放音乐以后会被自动同步到last.fm并用来做数据挖掘。使用Last.fm服务需要注意的就是要及时更正你的mp3-tag信息,这样你提交的数据就不会是垃圾,这对未来享用推荐服务非常重要。但是现在我发现的一个问题是,由于中文有简体和繁体,所以很和多时候Last.fm的亚洲歌手的名字都会出现多个版本,这给推荐带来了难度,也许国内的服务上可以帮我们解决这个问题吧。使用iTunes的朋友可能苦恼于mp3-tag信息乱码,那么使用Glider开发的ID3Mod2这个软件。
    • 看电影和看书通过豆瓣就很爽了,我对它使用的很初级,但是豆单等已经聚合过的相关分组已经可以给我看电影很多启发了。使用豆瓣这样的工具我们要做的就是尽量及时的更新你的阅读列表,这样豆瓣得到你的更多数据,那么推荐也会更加准确。
    • 我非常珍惜Google Reader的share功能,尤其是share with note。因为这个几乎是最好的和靠谱的朋友分享信息的手段,我一直认为这个是最好的一个人肉过滤器,你的朋友圈子越准确,得到的share也就更符合你的品味。自己在share的同时,可以看到你的share的朋友就和你做了非面对面的交流。而且有的时候如果你1个月没有读feed,已经无从看起的时候,完全可以把他们置为已读,然后去看朋友的分享。这减少了很多信息过滤的成本。
    • 最后一个重要的分享服务就是Twitter了。Twitter解决了你不能和所有的你想交朋友的人聊天的缺憾,这样你可以轻松的follow业界大牛,如d2hkent beck等。它也是一些重要信息的最快速发布场所,同时也是一个重要的社交场所。在使用Twitter以后我发现我甚至越来越少的在使用IM软件了。使用Twitter这个工具你需要做的就是有节奏的发信息,而不是三天打鱼两天晒网,这样大家不会因为你太贫而退订你,也不会因为常年见不到你的twitt而忘记你。
  6. 信息存储服务:网上看到好东西我们经常想收藏,这种行为叫做网摘,最早我使用CyberArticle(荣幸的买了正版,用的很High),而后用了Linux,所以改用Scrapbook,作为firefox的插件它是跨平台的。此时我的同时推荐我使用在线的Google记事本,这几个软件都能很好的做网摘。但是这几个软件的缺点是缺少协作,那么后来最常见的就是社会化书签应用,delicious,在浏览器装个插件以后它可以帮你用tag管理书签,好处是还顺便帮你做推荐服务,很方便。后来我发现并非只有这些数据需要存储,我们还需要网络磁盘服务,这类服务很多,我个人倾向于使用Dropbox,它的好处是各个平台都有客户端(Win、Mac、Linux),而且是用户空间磁盘系统,用起来和本地磁盘一样,它同样可以用来在项目组之间共享一些文档、电子书等。最后,我还推荐一个类似M$的OneNote的免费在线文档、及数据存储服务EverNote,我用它来存储一些简单的文本文档,还有用它写一些视频note,因为它有一些方便的工具帮你来做音频或者视频的记录。(对了,还有梦断代码里面描述的难产的软件Chandler,它是一个本地的数据中心软件)
  7. 快速启动服务:就是使用键盘快捷索引的启动工具,有代表性的是QuickSilver(是Mac下的,详情看Robbinlu的这篇blog),它显然比Mac自己的Spotlight好用(而它又比win下的很多桌面搜索强很多很多)。通过培养这样的软件可以帮你极大的提高效率。Windows下有launchy也很不错。
  8. 还有很多,但是我没有必要一次全部说完……

下面要分析一下我做的不好的地方,迎来跟踪我的改进:

  • 没有认真的学习Git和HG的用法,没有很好的贯彻他们的最佳实践。
  • 没有很好的学习shell。很少给自己写脚本来提高每天工作的效率。对很多*nix命令还很不了解,如wc、du……,对于微语言awk等不了解,这就限制了我制造自己的组合工具的能力。
  • 没有学习如何使用Mac的automator和appleScript。
  • 对于C语言的了解太初级,还是大学上课的水平,而它又是读懂很多code的关键(我并不想成为c程序员)。
  • 没有很好的整理好自己在各个网站的帐号。所以经常忘记去使用这些服务。
  • 没有很好的整理自己家的硬盘,没有对里面的电影和音乐进行过删减。因为数据也会过期,如果总是舍不得那么它们都被积累为工作噪音。所以要勇于与过去告别。
  • 没有好好学习Photoshop和Fireworks的使用,总是在使用低效的重复劳动。
  • 没有管理好自己的博客。我今年做了的事情就是把blog从BlogJavaLive Space移动到了朋友的机器上的wordpress上,但是由于访问速度比较慢,而且离线的时候写东西不方便,我今年也很少写blog post。
  • 没有学会使用一个有效的照片库软件,iPhoto的分库功能我最近才知道,不过没有认真整理(要减少单个iPhoto Lib的大小,这算个最佳实践)。我也应该学会使用一个LightRoom或者Apeture那样的面向摄影的后期软件。
  • 没有学会使用图片分享服务,我游离于flickr、picasa web和好看簿之间,前两者现在都有了iPhoto客户端,但是我还没有很好的使用。在9的内容做好后,我要更好的利用图片分享服务。
  • 没有很好的学习Ruby on rails,虽然一开始仔细阅读并且也用1.0的rails写了些小应用,但是我的知识没有及时更新。
  • 没有很好的清理自己的数据遗迹,我这个人很注意备份,但是没有注意清理过期的备份,想个好的工具来解决它,如TimeMachine。
  • 没有使用好Facebook和Linkedin这两种SNS,它们实际上能够帮助我很多
  • 没有利用好我买的图书,书是学习工具,而不是收藏品,我没能很好的阅读它们。

暂时先准备写到这里,其它的关于工具的话题我会另开post来总结。(最后更新于2008年12越21日)

[转载]Ruby的并发的一些基本限制

因为是feedburner的feeds,所以我就转过来。

Concurrency is a Myth in Ruby


Concurrency introduces parallelism into our applications, and threading is, of course, one way to achieve concurrency. But it turns out that in Ruby, this relation is not transitive: execution parallelism is not the same thing as threading. In fact, if you’re looking for parallelism in your Ruby application, you should be looking at process parallelism instead. So why is that?

Ruby under the covers: Global Interpreter Lock

To understand what’s going on, we need to take a closer look at the Ruby runtime. Whenever you launch a Ruby application, an instance of a Ruby interpreter is launched to parse your code, build an AST tree, and then execute the application you’ve requested – thankfully, all of this is transparent to the user. However, as part of this runtime, the interpreter also instantiates an instance of a Global Interpreter Lock (or more affectionately known as GIL), which is the culprit of our lack of concurrency:

Global Interpreter Lock is a mutual exclusion lock held by a programming language interpreter thread to avoid sharing code that is not thread-safe with other threads. There is always one GIL for one interpreter process.Usage of a Global Interpreter Lock in a language effectively limits concurrency of a single interpreter process with multiple threads — there is no or very little increase in speed when running the process on a multiprocessor machine.

Deciphering the Global Interpreter Lock

To make this a little less abstract, let’s first look at Ruby 1.8. First, a single OS thread is allocated for the Ruby interpreter, a GIL lock is instantiated, and Ruby threads (‘Green Threads‘), are spooled up by our program. As you may have guessed, there is no way for this Ruby process to take advantage of multiple cores: there is only one kernel thread available, hence only one Ruby thread can execute at a time.

Ruby 1.9 looks much more promising! Now we have many native threads attached to our Ruby interpreter, but now the GIL is the bottleneck. The interpreter guards itself against non thread-safe code (your code, and native extensions) by only allowing a single thread to execute at a time. End effect: Ruby MRI process, or any other language which has a Global Interpreter Lock (Python, for example, has a very similar threading model to Ruby 1.9) will never take advantage of multiple cores! If you have a dual core CPU, you’ll have to run two separate processes.

JRuby is, in fact, the only Ruby implementation that will allow you to natively scale your Ruby code across multiple cores. By compiling Ruby to bytecode and executing it on the JVM, Ruby threads are mapped to OS threads without a GIL in between – that’s at least one reason to look into JRuby.

Process parallelism

The implications of the GIL are surprising at first, but it turns out the solution to this problem is not all that complex: instead of thinking in threads, think how you could split the workload between different processes. Not only will you bypass an entire class of problems associated with concurrent programming (it’s hard!), but you are also much more likely to end up with a horizontally scalable architecture for your application. Here are the steps:

  1. Partition the work, or decompose your application
  2. Add a communications / work queue (Starling, Beanstalkd, RabbitMQ)
  3. Fork, or run multiple instances of you application
  4. Not surprisingly, many of the Ruby applications have already adopted this strategy: a typical Rails deployments is powered by a cluster of app servers (Mongrel, Ebb, Thin), and alternative strategies like EventMachine, and Revactor (equivalents of Twisted in Python) are gaining ground as a simple way to defer and parallelize your network IO without introducing threads into your application.

虽然本文是介绍Ruby1.8、1.9和JRuby对线程的不同实现。但是却清晰的解释了线程安全的意义,还有为什么MRI(或者同样使用GIL的CPython)需要使用多进程模型部署。再延伸我们可以知道Apach上面的Mod_rails(Passenger和Ruby Enterprise Edition)还有Mod_python的神奇之处,他们都hack并实现了使用fork让进程共享内存。最后本文还同样引出了为什么传统Ruby和Python应用只有使用多进程才可以利用多个CPU,还有为什么Twisted和EventMachine使用了单进程单线程+event IO的模型。

找到了我的Mac下的git-svn不工作的问题

前一段时间把Mingle的svn用git-svn在本地clone了一个git repository,不过后来非常奇怪的是git svn的时候提示命令找不到了。没有在意。

今天需要用git svn rebase一下这个repository,所以到处搜索为什么?最后发现了问题在于我使用macports安装的git-svn,但是升级的时候却使用了git install,结果造成了系统中安装了两个配置不同的git-core包,而包含git-svn的却没有被激活。

执行

tin@tw-dell:git_mingle >port installed The following ports are currently installed: … git-core @1.6.0.2_0+bash_completion+doc+svn git-core @1.6.0.2_0+doc (active) …

就是说+svn的git-core目前没有激活,那么好办了。

tin@tw-dell:git_mingle >sudo port deactivate git-core @1.6.0.2_0+doc —> Deactivating git-core 1.6.0.2_0+doc tin@tw-dell:git_mingle >sudo port activate git-core @1.6.0.2_0+bash_completion+doc+svn —> Activating git-core 1.6.0.2_0+bash_completion+doc+svn

其中先deactivate现在激活的git-core,再activate+svn版本的git就OK了。 如果你还没有安装,这样安装:

sudo port install git-core+svn+bash_completion+doc

–EOM–

iPod touch 2入手

托同事从香港给带了iPod touch 2,好兴奋的拿到了这个iPhone的替代品。因为我一直以来很像有一个像样的掌上设备可以有空做做开发,而iPhone/touch可以说是不二之选,因为从艺术的眼光上看他们很完美(起码我这么看)。而且多点触摸带来的交互革命激发了我作为UE边缘认识的兴趣。

iPod touch 2多了录音功能,所以也可以配合fring实现skype通话,不过前提是你需要购买带mic的耳机,目前似乎只有Apple原装的,要220港元,好贵,所以暂时还没有出手买这个。但是机身先下手了。是从国美(香港)买的,因为很多retail的地方都售空了。

现在的iPod包装实在是简单,连说明书都没有,只有一个简单的开箱指南,还有一个基本的连接iTunes的说明,仅此而已,不过倒是这样就够了,因为可以把你的眼球固定在touch上,让你自己好奇的去探索。我觉得激发用户的探索意识是很好的一种让用户产生沉浸感的营销方式,而且从苹果一向的交互设计理念上来说,他们非常注重启发式探索,并且尽量让你本能的达到自己所期待的结果,这个正是交互设计的重点所在。

那么不废话这么多,上图。图是上周一晚上照的,最近生活节奏太快,现在才抽空出来显摆^____^

InfoQ“构建的可伸缩性”文摘

InfoQ上面的一篇文章《构建的可伸缩性和达到的性能:一个虚拟座谈会》
http://www.infoq.com/cn/articles/scalability-panel
这篇文章很好,给了你很多做可伸缩性的线索,记录下这些点滴。推荐感兴趣的人去InfoQ阅读原文。

  • ab & httperf: 它给我们提供了一些自动化的负载测试,因此对比于我们从firebug中获得页面级的计时,使用这个工具可以获得会话级的计时。
  • firebug:
  • Ganglia是非常优秀的。同时Nagios或Zabbix(举个例子)将告诉你何时资料遭到破坏,使用少量加工你就能够让ganglia给你提供任何东西。
  • 对于MySQL,Innotop + slow query log 帮了大忙
  • GDB和DTrace是用于C++的基础架构。core或 pstack是个颇有价值的工具
  • 我们使用各种工具来重现问题并调试它们(包括栈的问题)——Visual Studio、 Eclipse、WinDbg、cdb、Purify、Fortify、dtrace以及许多定制的东西,为我们的架构所构建的东西
  • 从某点上讲,伸缩性已经从领域问题(即,如果你不使用内存缓存或者一个等价的分布式哈希表和基于内存的缓存)转移了,而你仍然处于“领域”范围
  • 当今静态内容的可伸缩性已不那么重要了,那只是花钱的问题并需要公司有好的社会组织的问题
  • 不要试图在部署之前就捕获性能问题。你不可能重建真实环境中的条件,因此你不可能得到真实可靠的测量结果
  • 监测。非常仔细的监测
  • 墨菲法则(一种幽默的规则,它认为任何可能出错的事终将出错)确保了你没有严密跟踪的衡量标准就是那个对你不利的标准!
  • 除非你知道当时正在执行什么业务功能,否则一个CPU测量是无意义的
  • 你只能通过使用软件实现伸缩性。“语言是不能伸缩的。框架是不能伸缩的。而架构是可以伸缩的。”

关于javascript库的一个回复

我以前写过一篇说说我对moo、prototype、JQuery的看法在我的blogjava博客里面(现在我已经不更新了,完全使用这个wordpress的博客)。今天也是在Google Reader里面看到JavaEye的另外一个朋友lifesinger的一篇文章:大胆预测下几个JS框架的走势,我个人不是非常同意,所以写了如下回复,也发在我的blog吧。

完全不同意lifesinger的说法:

1、JQuery会走的比较远。因为Django会走的比较远。而且JQuery的内部设计很好,如果说它不好估计是没有理解它的核心理念。而且John Resig的确是个勤奋的福音传播者,它的js使用理念很好,所以这个库会随着它的plugins库的数量质量的双重提高,占重要位置。同时浏览器效率的的提高也会给它注上强心剂。

2、YUI的api设计不好。作为oo的库它不好,作为fp的库它更不好,所以它不会有多好。不过在widget类库里面它肯定继续占重要地位,因为YUI的widget的确兼容性很好。

3、moo我很喜欢,但是它的演化保持了小众的特点,小步前进,api设计上比较偏设计师的想法。做大型项目的时候你回发现moo没有对如何组织你的项目给很好的“风格”上的建议,所以它也就会在大型项目上哑火。

4、Ext,我看没什么大的希望了。因为它的授权问题,基本上它已经不在是开源社区友好的(它也许可以做自由软件社区友好吧)。而且作为一个UI Widget库,它并没有把可访问性放在重要的地方来重视,所以随着UI的可访问性要求的上升,它的默认皮肤带来的eyecandy估计就没法盖过usability的缺失了。

你没有提到Prototype,它目前还是js lib的第一名,随着活跃的RoR社区的继续推进,它应该还会持续足够的市场份额。而且它和JQuery同属于有强烈“风格”的库,所以即使项目很大,它还可以保证代码的可读性与可维护性,这对于很多项目来说是至关重要的。

关于dojo我不说了,以前说过:说说我对moo、prototype、JQuery的看法的回复里面有。

说说我以为的RIA与Rich client

中午徐X和米高讲了一下Rich client的架构。其中徐X讲的是如何从单机分层系统到Rich client。

实际上最早的单机分层系统的UI部分激发了OO作为界面的编程模型。然后分层模型为了C/S结构发生了一些变化,目的是共享数据和通信,但是由于OO在远程调用上面的失败应用(Corba,EJB,Dcom),所以让人对OO产生了怀疑(实际上只是用错了地方)。而后又发生了B/S的变化,是一种完全的中心共享方式,原因是HTTP的无状态性造成客户端很难保存state,所以就有了完全中心共享状态的架构。而后通过通讯的增强(Ajax),客户端的状态保持逻辑通过异步通信来增强,所以产生了更好的用户体验。但是对状态同步的进一步要求和对会话状态保持的进一步要求让Ajaxian了的应用还是有点难以承受,所以Rich client又回归了。当然回归的时候同时带来的还有新的编程模型,如基于标记的声明式编程模型,还有更方便View-Model同步(通知)的数据binding机制,布局管理器,绘图支持能力,多线程能力,内嵌的视频编解码能力。其实WPF作为Windows上的新型UI编程模型他的确从Mozzila的XUL还有Adobe的mxml吸取了一些经验。上面这些是徐X阐述的主要内容,很精彩(最后的编程模型是我加的注释)。

而后米高做了一些技术层面的对比,主要是对比了Web和rich client的区别,不过我比较失望^___^,因为对比有失偏颇,原因是米高只用了5分钟准备ppt。

最后是我的意见。我现在已经不想割裂的分开Rich client和Web上的RIA,实际上目前他们已经有走向统一模型的趋势。

去年在InfoQ写文章的时候我就表达过这个意见。今天徐X也强调了,经典的MVC实际上很重要的是解决了数据共享(同步通知问题)与状态(会话)保持的问题,所有的架构问题其实都围绕了这个问题。首先RIA里面已经开始了layout数据分离的加强过程,比较明显的就是声名式的组件组合配置,还有数据绑定模型,这个在Flash和Silverlight还有JavaFx都有着重的解决,而且方向都很类似。其中Silverlight其实是一个减缩版的WPF。然后我们从架构方面来思考,解决状态共享和传递是通过增强的双向通信能力来完成的,很多RIA框架在开始提供web socket模型,这样让通讯超过无状态的且单向的HTTP,包括HTML5(目的是扩展Web上常用的一些Object,增强Web的编程能力,且让很多元素得到正确的语义,这个与XHTML2的关注点不同)的草案里面也有Web socket(类似socket的编程对象,可以实现二进制协议的面向连接的通讯)的提案。当然些努力就是让实现消息传递的开销更小,时效性更高,配合线程概念的支持,就可以实现复杂的基于消息的异步界面逻辑(这会极大的扩展RIA应用的能力)。因为通讯其实是解决状态共享的一个方向,通过高效的消息通知达到多个消费端的状态共享。另外一种解决Browser端状态同步(这里主要指客户端与服务器的数据库同步)的方法就是离线存储能力,这样削弱客户端对服务器的依赖。这种解决方案的代表就是各种Gears,Google gears,dojo offline等等,他们在浏览器里面嵌入sql lite一类的数据库,让客户端有自己的结构化存储能力,对于没有多客户端数据同步要求的应用来说离线方式可以让客户端形成完整的编程模型,通过sync机制在连线的时候进行数据同步是一种非常帮的RIA发展方向,从这个角度它已经是Rich client了。

那么可以扩展一下。我们知道Lotus Notes有服务器端replication的模式,离线会存在本地,连线的时候再同步。而对于另一些应用,极端地如Skype,他对实时的同步要求很高(当然它属于通讯类应用,也就是3C中的Communicate,而不是Content system),Skype的解决方案就是p2p。如果RIA有了socket(当然还有跨域支持),有了多线程,那么p2p是不是也不算难事了呢?状态同步通过p2p来实现,虽然不是可靠的通讯方式,但是却符合Internet的最大努力原则,所以我觉得这两种技术的结合的确很容易让RIA和Rich client不在有明显的界限,未来的目的就是融合。所以,要注意的是为什么微软拼了命在推Silverlight,而且拼了命的公布了Mac和Linux版本的Silverlight,其重要原因就是让WPF的模型渗透到RIA,用Rich client围攻RIA,来解决Adobe用超级NB的Air这个RIA衍生来围攻Rich client的困难。

这样,我们知道2年前开始声音渐强的Offline storage和越来越强的绘图,data binding的意图了吧,融合已经开始了,目标当然就是吃下这个大平台,然后成为最大的赢家!

关于Javascript的入门图书

犀牛书绝对的过时,也绝对的不友好。在开始的时候,作为一本系统讲解javascript的书,它非常注重阐述规范,所以在那个时代它是最好的图书。但是现在,作为js技术的入门图书,我们有一些更好的从javascript的精髓和基本理念入手的图书,读完他们你就可以体会到规范为什么是这个样子,从记忆角度来说理解后的记忆要强过死记硬背,所以用这些图书入门是更好的选择。

Update: 有位Sina的同事说道犀牛书还是要有一本的,目的是作为参考书。我倒是觉得这个完全可以依靠网络,因为大部分时候我们就是想索引一下方法,或者看看方法签名和解释,这个时候通过在线服务绝对要好过翻书。服务里面gotapi是个不错的选择!

在国内看翻译的推荐看:

1、大辫子nicholas写的Javascript高级程序设计

2、John Resig写的精通Javascript (Pro javascript)

ppk on javascript这本书也不错,比较实用,但是个人感觉没有精通Javascriptt这本讲的清楚。

如果看原文可以期待:

1、John Resig的Javascript Ninja,未出版,但是有样章。

2、Js大神Douglas Crockford的Javascript The good parts.

上周和钱钱讨论Programming Ruby这本书的时候我们也持这个观点,它曾经是一本非常棒的入门书,因为那个时候它是第一本非日文的Ruby图书。但是这本经典书到了现在已经有了很多不一样的竞争者,像钱钱同学推荐的Every day scripting with ruby就更偏实践,更容易让你入ruby的门。

一端简单的向iframe里面注入css的javascript

随手实验了一下这个是好用的(当然这个iframe要同源,否则安全限制无法修改)。原因是我们的系统里面有iframe输出后台的log,里面的样式都是默认的,为了后台无侵入,所以用js修改样式。这样就可以(也可以注入css文件,这样更干净)。注意contentWindow的写法在IE略有不同。

var css = $('testframe').contentWindow.document.createElement('style');
css.type = 'text/css';
css.innerHTML = 'body {font-size: 7px; color: red;}';
$('testframe').contentWindow.document.getElementsByTagName('head')[0].appendChild(css);

短小精悍的Javascript模板引擎

今天看到Jonh Resig的博客里面提到了他在他的Secrets of the JavaScript Ninja这本书里面介绍的一种简单的模板,代码如下:

// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
var cache = {};

this.tmpl = function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :

// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +

// Introduce the data as local variables using with(){}
"with(obj){p.push('" +

// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t") .replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");

// Provide some basic currying to the user
return data ? fn( data ) : fn;
};
})();

这段代码非常简单,但是却有不少trick。而且这些trick十分的优雅(John resig一向擅长写优雅的javascript)。非常值得读一下。思路就是把一段模板引擎里面的求值代码标记出来,将其余代码用单引号包裹起来,所以代码会分为文本和求值两种部分,压入一个Array,最后join。把这个逻辑用string的形式初始化一个Function对象,然后cache起来就成为一个高效的javascript模板引擎了。不过这个引擎只有求值赋值的功能,没有更加复杂的逻辑控制如if, else, for这些循环,但是在求值部分增加一些正则判断来处理这部分逻辑也是可行的。我非常喜欢的Trimpath Javascript Template估计也是这个思路(虽然经常用,但是由于代码可读性的问题一直没有仔细阅读它的源码)。

这段代码里面的闭包用法也很不错,可以防止命名冲突和全局变量的污染,不过这个写法估计大家都比较熟悉了。

模板的用法就不赘述了,如果你想用这个微型模板可以看看John Resig的JavaScript Micro-Templating