2006年12月31日星期日

2007,我对Google的期望

猫窝看到了这个活动,所以我也来写写对Google的期望吧。以前tag人的游戏我都没参与过,现在有礼品我反而愿意主动参加,咔咔!

  • 要有原产自Google China的产品——否则都不知道Google China是做什么的,拿着印有“谷歌”的礼品感觉是次品。
  • Google Docs & Spreadsheets plug-in for Microsoft Office——无非就是用C++或C#写一些代码,通过GData协议访问Google的数据,然后就可以在Office中实现好像访问Sharepoint那样上传下载版本控制。有了这个东西,相信Google Docs & Spreadsheets能够很快普及。
  • 培养好开发人员社区——一个操作系统要拉拢用户,先要有足够多的运行在该操作系统上的软件;要拉拢软件,先要有足够多的开发人员。无论Google是否会做Google OS,对于它现在拥有的那么多产品线来说,培养一个好的开发人员社区是很重要的。多一些人用GData开发,也就多一些支持Google服务的网站或客户端,也就多一些人可能间接使用到Google的服务。
  • Google Checkout支持中国结账——现在想去Google Apps买个域名,因为附送Google Apps不用另外申请,可惜结帐要用Google Checkout,billing adress支持HK和TW都不支持CN,麻烦死了。
  • 更多面向小型组织的免费服务——现在只有个Google Apps算是面向小型组织的,其他都是面向个人的服务,而且Google Apps本身也没什么协作功能,这与37Signals的差距太大啦。在抓住个人用户后,Google就应该开始抓小型组织。

一本好的教材要先让读者有赢的感觉

我们的数值计算老师说,一个人对一个研究方向是否感兴趣很可能是完全靠偶然事件决定的,这就好像人第一次打羽毛球,如果你赢了几盘你就会感兴趣,如果你一直都赢不了你就会没兴趣。

一本好的教材如果要让读者有兴趣读下去,也必须开头先让读者有赢的感觉,一旦如果读者感到frustrated了这本书的命运也就肯定是“束之高阁”了。正如我之前在《我喜欢的教材与我讨厌的教材》中说到的,讲矩阵开篇应该先说说方程组可以用矩阵来求解,这也正是让读者先有赢的感觉。

如果日后我有机会自己写本书,也一定要确定有一个好的开头,确保让读者尝到甜头并且乐意读下去。

2006年12月27日星期三

地震导致海底光缆断开

上网好慢啊,国内网站还可以,国外网站都不用上了,还要几天才能修复。这个样子,我的Blogger怎么维护啊,我怎么获取技术资料啊!

2006年12月21日星期四

每一个女生都曾经是非常有灵气的

“每一个女生都曾经是非常有灵气的”,这句话是Piggest说的,在我某次赞她省实小才女时。

经过了一些事情后,我对这句话思考的结果是:When a baby comes to a new life onto this planet, he's sitting on a rocket that flying high in the sky. Then, most of them lands.

大部分人最终都会放弃他们的才华选择着陆,这就是我今天要说的事情。着陆有可能是因为诱惑,随着人的成长,你的才华发挥出来了,你就发觉你可以放弃掉部分才华去换取一些非常有诱惑力的东西,至少是看起来有诱惑力的东西吧。这种情况通常发生在20岁左右,甚至20岁之前,因为在初中或者高中就发现生活充满诱惑也是时常有人遇到的。着陆也有可能是因为责任,来自对家庭的责任会让你自愿的放弃部分原有的自由发挥空间。这种情况可能会发生在30岁左右吧,不知道呢,或许也有因为家庭压力大很小的时候就放弃了的。

在我高三的时候,尝试在拿到保送后将我的成绩给软着陆了,结果不那么成功,有些东西的运动轨迹变成了平抛甚至垂直下落。无论怎么说,我算是着陆了,但发现在这拥挤的地面上我难以生存——这里的人太多了,想舒服的伸个懒腰都不行。所以我决定不能再这样生活下去,一定要回到三维空间上去,不能留恋这个二维平面上的诱惑。我要做我自己爱做的事情,而不是在一个粒子密度高的环境下让别人的布朗运动影响着我的前进路经。

其实着陆往往和成熟挂钩,你能够在其他人的布朗运动影响下前进,甚至反作用于他人,那叫做有EQ,那样可以teamwork。然而teamwork又如何?我不是反对teamwork,我曾经知道自己的个人能力有限所以才积极拥抱teamwork,因为我发现好的teamwork能够发挥1+1>2的效能,然而这不代表我盲目支持teamwork。盲目地根据partnet限制自己的发挥,希望达成teamwork,然后换取更大的总发挥效率,很有可能导致的效果是1+1+...+1<1,最终整个team的效率比一个人自己发挥的还要低。

地面上没有什么生物能够轻易杀死一只飞鸟,即使成群结队。所以如果你有能力保持着在天空飞,就别跑到地面上结队,反正来自地面的威胁不可能真正伤害到你,除非你已经在濒死状态。当然,只要求你耐得住寂寞,至少在你成功加入一个飞行梯队之前。诚然,能保持在天上飞的动物是少数,所以要成功加入一个梯队也比在地面上结队要难得多,因此做好寂寞的心理准备是必须的。地面上所谓的诱惑,无非是看起来的“人才济济”——是不是人才的都可以先来挤一挤,然而你自己能否挤得过别人,就要看天赋了,任何人生下来都有天赋,不过又各不相同。

当然,不着陆的话往往会给人看做不成熟,就如某些大师级人物不受什么物质诱惑也没有什么责任观念。然而要问这样的人物所创造的价值,放到与地面上的团队比较,或许也在前20%。如果能够把他放置到适合飞行梯队中,那么整个梯队发挥的效能就肯定是整个星球上的前1%。

2006年12月17日星期日

Microsoft WPF/E vs Adobe Apollo

整个.NET社区都在庆祝WPF/E开始CTP,且慢,看看河对面的Flash社区好像也在举行隆重的庆典哦。

AVM2开放源代码

这几个星期发生在Flash社区的震撼事件,包括Adobe将ActionScript Virtual Machine 2(AVM2)的核心源代码捐献给Mozilla组织,变成了一个叫做Tamarin的开源项目。Tamarin的目标是实现一个高效的ECMAScript 4th edition(ES4)引擎,它会成为现在Firefox中代号为SpiderMonkey的JavaScript引擎的新核心,同时也用于运行ActionScript3的AVM2。

如果你想知道Tamarin有多震撼,先来看Tamarin和现有SpiderMonkey的执行效率对比,其中强类型代码(Typed Code)模式是指将JavaScript转换为ActionScript3,并且将function与prototype转换为class:

(摘自:Tamarin vs. javascript Performance

看到这样的执行效率比较,再想一想IE那个执行效率比FF还要低得多的JavaScript引擎,或许将来Apollo应用的配置要求这样写:四核处理器加Internet Explorer或双核处理器加Mozilla Firefox,哈哈……我的意思是,如果你一定要用IE你就要多投资金到处理器上换取等效的JavaScript执行效率。

Tamarin开放源代码的战略意义是很实在的,这样Adobe就可以让开源社区服务于它的Flash Player了。Tamarin作为一个标准的ES4引擎,虽然现今只有AVM2和SpiderMonkey基于它,但这也足够形成一个强大的战略同盟——Adobe或Mozilla社区对Tamarin的改进都会让双方同时受惠。将来可能有更多软件考虑引入基于ES4的脚本语言支持,如果选用Tamarin的话将会让其开发者社区便得越来越壮大。哪天再出来一个神通把它tune up一下的话,其执行效率将可能远远抛离IE,这时候同样的脚本应用只在Flash或FF中流畅运行,你想不放弃IE都不行。

Adobe Apollo

另一个震撼的事件是Adobe的Apollo即将来临,这家伙将有十足的实力在全平台上与WPF/E对抗。

首先Apollo支持Just In Time(JIT)编译,这样其跨硬件平台能力就可以和Java/.NET比了。.NET所谓的跨平台是狭隘的,JIT主要是指跨硬件平台,软件平台则直到WPF/E才真正肯跨出了第一步,提供对MacOSX的支持。Apollo在挑选浏览器引擎时却费尽了心思,就为了选一个将来容易跨越更多软件平台的。

Apollo最终选中的浏览器引擎是开源的Webkit。Adobe官方宣布明年上半年正式发布的Apollo 1.0将支持Windows和MacOSX,但如果你了解一下Webkit这东西就发现它其实有足够的潜力实现大小平台通吃。Webkit本身作为Safari的核心,所以确保了MacOSX平台的支持;其次它也是KDE上KHTML浏览器的核心,进军Linux也应该没问题;最后它连Symbian Series 60(S60)也都支持,Adobe只需要去和Nokia握握手或许就能让Apollo进驻S60的智能手机,要知道在智能手机上S60的市场占有率可比Windows Mobile(WM)多得多。

反过来看看WPF/E,估计也是2007年上半年能够发布1.0正式版,官方支持的平台也是Windows和MacOSX,但MS已经支持其Linux的支持将依靠第三方来实现,也就是不会用官方的WPF/E for Linux支持。至于移动设备,将来就算能支持估计还是仅支持WM,这样适用范围还是受到了很大的限制。

2006年12月14日星期四

重新开始做做算法设计的竞赛题

期末考前要先提交20题,这对我来说不难,不过做起来也挺有feel的。或许以后有时间还是要多做做题,重新找回感觉,把思维速度调回去。

2006年12月11日星期一

我不想仅仅做一个coder!

“我不想仅仅做一个coder”,这是最近才发现的事实,算是发现得早还是晚?

我不是一个优秀的Coder

“我不是一个优秀的coder”,这是一个摆在眼前的事实。跟很多其他同年龄的人对比起来,或许我真的已经coded了不少东西,而且结果也有一定的质量,但当我见到过真正优秀的coder后我明白到了自己不是一个优秀的coder。

在我的高中里,有一位比我低三个年级的同学,他接手了我创立的网络社团的负责人位置,让我见识到了什么才是真正高效的coding。我与第二任负责人的风格都是设计型甚至是幻想型的,也就是说我们从来不愿意通过coding去实现一个别人已经做过的东西,我们必须要有一个非常原创性的idea我才会开始coding,如果在coding的过程中发现这东西的原创性不足,又或者够原创性但缺乏实用价值,那就会停下来思考和等待新的idea,直到新的idea又有原创性又有价值了才继续coding。然而这位第四任却是一个100%的coder风格,他不会发时间去想这东西是否原创,只要有需求他就去coding,然后再考虑向其中加入一些原创性的或者是实验性的东西。

他一个学期下来就做了一套学生自助建站系统。当学生申请个人网站时,他仅仅需要人手审核申请信息,之后系统就会自动创建目录分配空间,将该网站选择了的模块(例如论坛、blog、wiki等)复制到该目录,修改好这些模块的配置让它们能够正常运作。整个系统中唯一要老师帮忙的就是配置域名泛解释。这东西你可以说没太多原创性,都是辛苦活,他要做的就是纯粹的coding,然而一个在重点中学读书的高中生能够在一个学期内完成确实了不起。而且在这个学期中他还做了其他小网站,都是属于功能单一仅仅为了满足学校某方面需求的那种。

这位同学手上有一张MCSE认证,开发主要用ASP/ASP.NET,有时候疯狂到用C#自己写一个基于模板返回内容的HTTP服务器,“这就是一个纯粹的Microsoft Coder”,我们的指导老师是这样说的。如果一个“纯粹的Microsoft Coder”是这个样子的,那么以我现在掌握的技术和我coding的速度来看,我又差多远呢?看起来非常非常远……

Farmer, Worker and Coder

最近看了很多文章,然后才有了文章开头的想法。我看到有人在讨论coder的命运,我觉得farmer和worker是怎么过来的,coder也就将会怎样。

在国外coder只需要高中学历,因为这是一门学历和经验参半的手艺,太高的学历没用,还要补上相当的经验才有价值。在国内coder显得有价值,这是国情造成的虚高,也就是你本来就不值那个价位只不过看起来像是那个价位而已。将来这个虚高不存在了,你就摔下来。所以今天拿着学士学位的coder要明白到,自己的真实身价与高中生等同,虚高的消失是不可逃避的,你唯一能做的就是在这个时期内让自己的实值上升,这样虚高完全消失后你还能有回原来的身价。coder怎么做也是coder,除非你确信你有能力做coder中的#1,否则就永远是那个身价,也就和worker、farmer一样,要逃出这种困境只有一条路可以选择,那就是让自己真正的增值。只有增值为designer或者architect了,才能确保你不再是在coder的race中,而进入了另一场race。

挑战你的极限

我们的数值计算老师,一开学就学就说:你们计算机系的学生只有两条出路,要么赶紧转去学金融,要么考研,本科毕业出来工作就是浪费了你。其实浪费所指的应该就是毕业后你最多就当个coder,享受不知道何时会突然间没掉的身价虚高。数值计算课有1/3的时间给他用来吹水了,吹的就是学习方式方面的事情,不过也挺有价值的。

他后来讲到,他在浙大读博士时获得了公费去香港城市大学的机会,去到后才发现要拿到学位非常难,但是公费去了拿不到学位回大陆是非常大的罪过,所以就拼了命地去学习合做研究。在香港城市大学拿到博士学位的那一刻,他才明白到为什么国外的学生抛博士帽的那一刻是如此兴奋,因为这真的是一个relief,地狱式的生活终于过去了。然而只有经过了那样的地狱式训练,你尝试过挑战自己的能力极限,你才能够真正学到一些东西,好像现在大陆的学校那样轻松及格拿学位是学不到什么的。

在他讲这番话之前,我一直都想不通自己在这4年里要干什么,因为你有无限的东西可以去干,但每一项的结果好象都没什么价值,这个问题困扰到我有点点obsessed,因为我想不到什么东西有价值去做我就不去做了。现在我终于明白了,我所比较的那些选项之所以没什么价值,是因为我把那些艰巨的、挑战我极限的选项都一早剔出了,留下一些可以保持现在安逸生活的选项,这些当然不可能有什么价值。

我要想实现自己的目标,就必须挑战自己的极限,这是不能逃避的事情。之前虽然轻轻松松生活了两年多,浪费了很多时间,但站在这里后悔更浪费时间,不如直接开始努力让自己重新进入那种充满压力的奋斗状态。

The True Obsession

真正的obsession其实在最后,做了非常有价值的事情又如何,那将是自己真正想要的吗?

高中毕业自广东奥林匹克学校的学生,有一部分会保持着原来搞竞赛或者拼高考时的精英主义和拼搏精神,感受不到也拒绝感受任何草根气息,仅需要享受的就是#1的感觉,这部分人不会坠入这个obsession中;而另外一部分人,例如我,则会因为开了眼界而坠入obsession中。

我们看到的景象是,很多同样来自重点中学的同学享受着很好的生活,物质方面不会显得贫乏,而感情方面相对有充足,身边新奇好玩的事情都可以去体验,而个人进步速度也保持在适当的水平。我们中学6年的训练类似体校不过没那么严格,但也曾经为竞赛而放弃了很多东西,当看到天赋与你相当的人能够花更少的力气享受更好的生活的时候,谁会不心动?甚至我们会自信以自己的能力能把事情做得更好。

然而我们的结果都不乐观,在花了两年时间尝试去适应这种生活后,发现这完全是在自己能力之外的事情。我个人已经直接把这种行为称作“邯郸学步”的了,既没有成功转变为新的生活方式,同时也因为脱离了原来的生活方式而导致自己失去竞争力。最终我们还是放弃了追求眼前某些人享受的美好生活,努力做回原本自己所擅长的东西,那就是无尽头的竞争与地位攀爬。

留下来唯一的疑问是,我们那6年经过的真的是one-way-path吗?是不是进入了这个岔道就必须一辈子以这种方式生活下去?我们不能选择停下来并学习如何去组织一段美好的生活吗?提这些问题是因为,顺着这条路走下去我们或许能够获得别人眼中所谓的成就,然而这不一定是我们当中每一个所想要得到的结局,肯定会有一些人希望能再来一个岔道并让他们走回去。

2006年12月7日星期四

随需写作 / On Demand Writing

Cat in dotNET从今天开始提供On Demand Writing服务(beta),如果您希望我在将来的文章讨论某个您感兴趣的主题,您可以到On Demand Writing Wish List写下您的建议,然后我会尽快对该建议给出答复。

在我看到Wish List的建议主题后,我首先会考虑我对该主题是否足够的熟悉,是否已经做了充足的研究。如果我对该主题不熟悉,并且短时间内不准备深入研究,我就不会写该主题的文章了,因为我觉得确保文章质量非常重要,我不熟悉的主体就不能乱写。在这种情况下,我有可能将该建议主题转发给其他可能感兴趣的作者,或许有一位作者能在该主题写出一篇好文章来。

如果建议主题是我熟悉的,但我还没有做充足的实验研究,那么我将答复您该主题的文章可能需要经过比较长的时间才能完成。这是因为我要确保文章中代码的可重复实验性,所以我写到文章上的每一个实验我都要先自己做一遍。

On Demand Writing服务现在是beta阶段,我暂时无法估计读者的反应会是怎样的,有些细节日后可能还会调整,但无论如何我会尽力确保文章质量。如果您现在想到什么好的主题,可以马上到On Demand Writing Wish List上写下来。如果您希望关注On Demand Writing将来发布的文章,您可以考虑订阅Cat in dotNET

深入理解 ASP.NET 与客户端缓存 (Part 2 - ASP.NET 支持)

在上一篇中,我们知道了HTTP属性与客户端缓存的关系,现在就可以着手用ASP.NET来控制这种缓存。需要注意的是,ASP.NET的Cache是用于服务器端缓存的,所以和我们正在讨论的事情完全无关,我们在这里要讨论的是如何通过HTTP属性控制客户端缓存。

页面缓存

在ASP.NET中,如果你需要添加HTTP属性,可以使用HttpResponse.AppendHeader方法,例如在Page的代码中直接执行Response.AppendHeader。HttpResponse.AddHeader方法是与之等效的,不过仅用于与ASP代码兼容,所以我的建议你最好不要使用。通过AppendHeader方法,你可以将上述Last-Modified属性和ETag属性写入返回中。

接着我们考虑如何从请求中读上述属性然后判断如何返回。我们可以使用HttpRequest.ServerVariables读取请求中的属性,然后和当前的值比较,如果比较结果表明内容无变化,我们就可以设置HttpResponse.StatusCode为304,然后返回空内容;如果比较结果表明内容变化了,那就还是按一般的方式完成整个返回。

这很麻烦,对吧?所以ASP.NET内置了HttpCachePolicy类,让我们可以直接控制有关属性,我们可以通过HttpResponse.Cache访问此类的实例,而如果在Page中我们可以直接通过Reponse.Cache访问它。这个类的使用方式在MSDN中有详细的描述,所以我就不再解释了。由于它的实现也依靠上述HTTP属性,所以使用AppendHeader控制上述属性时,就会破坏掉HttpCachePolicy中的设置(如果你设置了的话)。因此直接使用AppendHeader与通过HttpCachePolicy间接控制这两个方法中,同一时间最好仅用其中的一个,如果你需要灵活性就使用前者,如果你需要简单设置就是用后者。

资源缓存

ASP.NET内置了Cache和HttpCachePolicy,这让Page的缓存已经足够方便,所以让我们来看一看非Page该怎么缓存。事实上资源文件(例如js和css)的最大可能请求数量比Page要多得多,因为一个Page通常链接几个资源文件。

编译嵌入资源

我们先来看看编译控件是如何缓存资源的。系统自带的很多控件都是带有资源的,因为他们需要这些小图片、脚本或样式来确保它们的正常运行,这些资源编译时选择为嵌入到dll中,之后无论控件发布到哪都会附带有这些资源。这些嵌入到dll中的资源以特定的形式引用,在控件呈现为HTML代码时就成了WebResource.axd开头链接,例如:
<script
  src="/WebResource.axd?d=7wVzVzBOs3_HEjhM5umRSQ2&amp;t=632962899860156250"
  type="text/javascript">
</script>
WebResource.axd注册为由AssemblyResourceLoader处理,这个IHttpHandler专门负责从dll中将资源文件提取出来,然后返回给客户端。

留意WebResource.axd后面的两个参数,d是资源的标示,它表明了当前请求的是哪个资源;t是该dll最后编译的时间戳,如果dll重新编译了t就会跟着改变,这就让浏览器知道这是一个新的URL,不应该再使用原来的缓存。

需要强调的是,这并非是一个具有兼容性的做法,它只能确保资源更新时缓存过期,但不能确保没更新的资源成功缓存。根据RFC2616,浏览器操作分为安全与不安全两类,GET和HEAD应该是安全的,因为除了获取信息它们不对外界造成任何影响;POST、PUT以及DELETE是不安全的,因为它们对外界造成影响,所以你刷新POST后的页面时浏览器会提示你是否确认再次提交数据。RFC2616中提到,对于安全操作除非服务器端显式声明过期,否则客户端有权直接取缓存来显示,因为无论客户端是从服务期端取还是从缓存取都应该是不对外界造成任何影响的,然而有一种情况除外——就是当URL中存在QueryString时。

当URL中存在QueryString时,这个请求被认为是可能对外界造成影响的,所以当客户端进行这个请求时必须通过服务器端完成,也就是不允许使用缓存。RFC2616如是说了,但并非每一个浏览器都如此做了。IE和Firefox违反RFC2616对有QueryString的URL进行缓存,而Opera和Safari则遵守此规矩每次重新获取内容。也就是说,ASP.NET的这种资源地址在Opera和Safari中是决不会被缓存的,例如你的ASP.NET应用在MasterPage使用了ASP.NET AJAX的ScriptManager,那么打开每个页面时有关的脚本文件都要从新下载。

非编译嵌入资源

如果我们当前在写一个ASP.NET网站,有些资源是直接以文件形式存在的,不是编译嵌入到dll中的,那么我们就没办法享受上述系统提供的便利了,但我们可以自己实现类似的机制,并避免上述某些浏览器不缓存资源的问题。详细的实现方式将在本系列文章的下一篇中讨论,如果你不想错过其中的精彩内容,请订阅Cat in dotNET

2006年12月6日星期三

深入理解 ASP.NET 与客户端缓存 (Part 1 - HTTP 协议)

前言

这个系列的文章要讨论的是如何通过ASP.NET服务器端技术来优化客户端缓存策略,而且让这种策略变得可配置和可扩展。我们要了解的知识从HTTP协议中相关属性对客户端缓存的影响,到ASP.NET如何控制这些属性来实现我们的缓存策略。

HTTP基础知识

由于讨论涉及到客户端缓存,所以还是先要简单介绍一下HTTP协议是如何控制客户端缓存的,这里涉及到HTTP头的Last-Modified、ETag等属性。

Last-Modified

  • 在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
    Last-Modified: Fri, 12 May 2006 18:53:33 GMT
  • 客户端第二次请求此URL时,会在头部加入一个属性,询问该时间之后文件是否有被修改过:
    If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
  • 如果服务器端的文件没有被修改过,则返回状态是304,内容为空,这样就节省了传输数据量。如果服务器端的文件被修改过,则返回和第一次请求时类似。

ETag

  • 和Last-Modified类似,由于RFC2616(也就是HTTP/1.1)中没有说明ETag该是什么格式的,只要确保用双引号括起来就行了,所以你可以用文件的hash,甚至是直接用Last-Modified,以下是服务器端返回的格式:
    ETag: "50b1c1d4f775c61:df3"
  • 客户端的查询更新格式是这样的:
    If-None-Match: W/"50b1c1d4f775c61:df3"
  • 如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。

Expires

这个属性就如我们在ASP中使用HttpResponse.ExpiresAbsolute一样直接,声明某某时刻过期之后浏览器就应该重新请求该URL,使用格式为:
Expires: Sun, 10 Feb 2002 16:00:00 GMT
注意HttpResponse.ExpiresAbsolute在ASP.NET中是不建议使用的,现在我们应该使用的是HttpResponse.Cache.SetExpires。

Pragma

通常我们用到的值就是no-cache,这和在Cache-Control中使用no-cache值是一样的,Cache-Control在下面讲。Pragma的使用格式如下:
Pragma: no-cache

Cache-Control

这是一个集合型属性,它里面能够包含很多子属性,并且允许用户扩展新的子属性。常见的子属性包括:

  • max-age - 以秒为单位的超时,覆盖Expires属性。
  • public - 允许保存在共享缓存中。
  • private - 只允许保存在私有缓存中。
  • no-cache - 不允许缓存。
  • no-store - 不允许缓存在持久介质中。
  • no-transform - 不允许转换存储系统。

实际应用

了解这些HTTP属性,是为了让我们在ASP.NET中实际应用它们,这将在本系列文章的下一篇中讨论,如果你不想错过其中的精彩内容,请订阅Cat in dotNET

2006年12月3日星期日

AJAX 在中文社区的“集体信仰动摇”?!

最近好像在中文社区又多了关于AJAX的讨论,很多都是说AJAX仅仅是过渡技术,又或者说AJAX现在有些滥用了,反正就好像一场狂热下来大家又成了怀疑论者了。

Microsoft Expression

看起来最震撼的事情应该是Microsoft Expression系列被越来越多人知道,很多人都在想WPF在如此强大的设计器支持下能否干掉AJAX。首先说一下Microsoft Expression是什么,这是一个和以前的Macromedia Studio非常类似的工具集,其战略目标应该也非常类似。

以前Studio的成功在于3大产品为设计人员组成流水线,Fireworks设计的图可以直接切片放入DreamWeaver使用,又会者提供给Flash作为素材,而Flash设计完后同样可以直接插入DreamWeaver设计的网页中。现在的Expression则分为Graphic Designer、Web Designer、Interactive Designer这3大产品,Graphic Designer设计的图可以直接提供给Web Designer或Interactive Designer使用,Web Designer用于设计符合Web Standards的页面,而Interactive Designer用于WPF的交互界面,这两者的设计结果最终都放入Visual Studio中添加后台代码。

暂时看来,Web Designer和Interactive Designer是平行产品,也就是Web和WPF并不存在哪个更优的说法。Web Designer已经经过Beta1了,估计正在进入RTM阶段,所以应该会最早发布。Expression的出现对于程序员来说可以说是好事情,因为在工具上就已经给程序员和美工划分了明确的艰险,这样就可以避免程序员和美工互相推卸责任,界面上的互动效果说不清应该由谁来负责。同时Web Designer是用于设计符合Web Standards的页面的,这就要求美工不能仅仅懂绘图和切片而不懂XHTML+CSS。

Web Designer的出现,应该是美工的噩梦而不是程序员的噩梦,因为终于有一个理由要强迫美工去学好Web Standards有关的技术了。以往拖着美工去看Macromedia的首页(现在是Adobe的首页),告诉他们这是符合Web Standards的门户页设计的顶峰之作,他们会不信。跟他们说,这并排的3个竖栏都是用嵌套<ul />方式排的,所有圆角效果、阴影效果都是CSS而不是切片,他们会说用老的方式排出来同样的效果也没什么不好,除了在移动设备上不好看。现在塞一个Web Designer给他们,界面上优先显示的就是CSS设计功能,让他们设计一个Adobe那样的首页来,他们自然会明白技术差距之远。

至于Interactive Designer和WPF对Web的直接威胁,暂时还是不大的,因为WPF/E才刚刚开始CTP,其适用范围还很有限,比AJAX的支持范围要窄多了。现在AJAX在主流的PC浏览器上都已经实现,并且Opera和Nokia也正在实现AJAX在移动设备上的支持。WPF/E的真正对手是Flash,Macromedia鼓吹了那么多年的RIA都没多少人响应,Flex也不好卖,再杀进来一个WPF/E逼到Flex 2要贱卖了。但就算对Flash来说,WPF/E其实只算得上一个未来的对手,因为它现在仍显得过于“贵族化”——只有花得起钱享受XP/Vista/MacOSX级别界面的用户才有资格享受WPF/E,相对来说Flash则已经算是个“草根明星”了。

AJAX滥用

说到滥用,我们必须承认我们确实滥用了,而且问题还很严重。说到底这是因为我们在为技术而技术,很多场合程序员说了算,而国内程序员的界面设计能力还有待提高。

首先错误来自大家对AJAX使用上的本末倒置,我们看到AJAX通过减少刷新来达到改善用户体验的效果,所以我们开始追求无刷新,而最终变成了技术服务于无刷新,而功能服务于技术,这正所谓之本末倒置。而实际上,应该是来自界面上的需求推动了AJAX的发展,只有当界面需要避免刷新时才使用AJAX。

在这方面,我也不是专家,所以只能建议大家多去看看《About Face 2.0》之类的界面设计书籍,先学习如何设计界面,再学习如何在界面上使用AJAX。简单来说,不刷新是为了不打断用户的思维,让用户连贯性的完成一系列的操作,不需要每次都等待白屏过去然后重新滚动到他操作的位置。然而这是提高用户的好体验的一方面,同时我们还需要降低用户的坏体验。最坏的情况是用户在网站上受了挫折(frustrated)而离开,例如导航无法让他去到正确的位置或者让他获取到所需的信息,又例如用户更改输入提交了几次但每次都有新的提示告诉用户不符合某某输入规则。

AJAX给了机会我们更好的避免这些问题,例如通过AutoComplete获得更佳的搜索导航效果,或者异步的Validation尽早通知用户输入所需要符合的规则及如何更改去符合这些规则。然而除此之外还有很多其他更好的设计。在我们忙碌着做一个AJAX式的弹出日历式日期选择控件,国外的Calendar服务则已经提供了更好的输入方式——它们能够直接识别"Tomorrow 7:00pm dinner with Kathy at home"或"2nd anniversary on Oct 5th."这样的纯文本输入,然后自动从中提取出事件的时间、地点、人物、主题等信息。

现在我们将AJAX的底层技术拿出来作学院式研究没什么不好,但如果你要做的是一个面向最终用户的产品,那在设计时就应该先将AJAX放一边,优先考虑的是用户角色以及他们的需求,如果他们的需求包括到AJAX就把AJAX放上日程,否则就不要管AJAX。国外很多网站的AJAX使用都非常恰当,例如BaseCamp,用户需要连续执行的操作(例如添加多个todo或者将多个todo标记为完成)就提供AJAX支持,这样用户的思路不会被打断,但是无上下文的可打断的操作则保留整页提交的方式。

最后,如果你希望继续关注我的文章,欢迎订阅Cat in Chinese订阅Cat in dotNET

2006年12月2日星期六

装上了 Opera Mini 3.0

一直想尝试mobile blogging,可惜总找不到适合的平台和发送方式,直到装上了Opera Mini 3.0。

Opera Mini 3.0的启动页有一个发送照片到blog,看起来挺好玩,于是我就去Opera Community去注册了一个帐号,然后尝试拍照发送上去。在OM3里面,已经内置了拍照功能,不过限制了分辨率为160*120,拍照后就自动上传到你的blog(当然是指你在Opera Community的那个blog啦),接着提示你可以添加标题和内容,然后点一下发布就搞定了。

现在有聊没聊都喜欢周围乱拍,然后写一点点文字就发上去,哈哈。大家来看看我的移动博客,名字叫做Cat in Mobile(feed)哦,里面会keep住发布一些随手拍随手写的东西。

P.S.原来Opera Community的blog和album支持MMS发布,只需要将MMS发送到指定的email地址就行了,我开头也怀疑cmwap能否成功发过去,结果发现真的能发,那就是说非Opera Mini用户也能享受Opera Community对mobile blogging的支持咯。