2007年2月25日星期日

还有新鲜感吗?

ZDNet有个家伙,用了19个月的Vista,说至今仍然感觉到Vista有新鲜感,大家可以去看看他的文章:Windows Vista - 19 months of usage and counting

在跟别人聊起这新鲜感的事情的时候,我说这19个月的测试版是当然可以让人保持新鲜感的,因为不断的有upgrade和fix——原来有问题的功能变得没问题了,原来没问题的功能变得更好了,这当然让人能保持新鲜感。然而如果连续用19个月的正式版呢?正式版发布后,或者准确来说你给钱购买后,就不会再增加什么新功能,因为你以前给钱了,出新功能不可能赚到更多的钱,这时候新鲜感就会自然下滑。当然,XP SP2是个例外情况,因为XP的安全问题严重,必须增加安全中心这个新功能去巩固用户信心。

说完这段话,突然感觉到这是个类似GF和Wife的隐喻,在你最终结帐之前可以不断更新功能,这样你也就有持续的新鲜感,但结账之后就……

不过现在Web2.0啊,大家都标称自己是永远beta,永远在改进,其实和mm的关系应该也能这样啊。有很多人的思想被限制在当今的一夫一妻婚姻制度里面,对以前的一夫多妻不敢恭维,对将来的制度也不敢想象,就如此固步自封,其实是不对的。我们应该尝试去探索一种新的人与人之间的关系,例如好像我这样,寻求一个永远beta的mm,咔咔!

现在的软件已经开始进化,Software as a Service(SaaS)慢慢会流行起来,甚至连Vista也被设计为如此——将来Vista的升级就会如同一种服务一般设计,你了一付费使用这种服务了,就能得到升级,这种升级是能够确实让系统功能能够得到明显更新的。购买费用足够高的Ultimate版本,其实也算是包括了购买服务的费用,因为Ultimate版本在Windows Update时能够下载所谓的Ultimate Extras更新,属于能够明显增加系统功能的更新。看来突出长期的服务长期的交易将成为潮流……

Anyway,其实没必要将那么多SaaS之类的东西,我在说的是新鲜感。我不会随便换操作系统,安装任何一个操作系统都经我细致调教以保证在我通常的使用情况下能够有best performance,但我希望它好像Vista那样能够有不停的增值服务,甚至更多的更新以保持新鲜感。嗯……没错,我说的就是这个东西,我需要一个类似这样的mm,我不需要结婚。如果可以,我需要一种新的license来维护这种关系双方的利益,但不要婚姻法。

2007年2月23日星期五

Code is Configuration

Ruby on Rails强调Convention over Configuration,也就是习惯优于配置,这对我来说是一个很有吸引力的特性。.NET是配置优先的(据说Java也是),最好什么都不是硬编码而是可配置的,开发出来的产品最终可以在部署时根据实际情况配置,或者再被调用时按照调用者的需求配置。为什么RoR可以是习惯优于配置呢?如果什么都硬编码了,遇到需要改动的情况怎么办?按照我现在对RoR的理解,思考了一下,寻找到一种可能的解释——RoR的代码也就是配置!

在.NET里面,函数或者是指令,都是描述行为的。一组指令组成一个函数,代表着一组顺序执行的行为;之后一组函数组成一个类,代表着一类行为的聚合。而RoR指令给人的感觉却不是这样,RoR中有些指令完全可以认为是描述性的,就好像配置一样,而且是顺序无关的。

举个例子,创建数据表的migration,你可以认为它是ruby语法写的CREATE TABLE,而且它做的也就是CREATE TABLE,但实际上它是schema!它已经描述了数据表是怎样的了,而不仅仅是生成数据表,生成数据表仅仅是migration执行时瞬时的行为,生成数据表之后Rails自动提供ORM功能,不再需要另外的schema或者自动生成的code来重复描述schema。这正是其符合DRY原则的地方,在整个RoR应用当中,只有migration这一处描述了schema,其它地方均无再次描述schema的地方。然后再对比一下我们在ASP.NET中的做法,重复描述数据表schema的地方实在不少,无论使用哪种ORM工具都如此,希望以后大家都能用上DLinq从而避免这个问题。

再举个例子,model中可以直接用helper函数指定每一个属性要符合的业务逻辑,从而提供验证功能。还记得我们在ASP.NET中这有多麻烦吗?首先,根据决不信任客户端提交原则,在View中要验证数据,验证一方面要能抵御恶意编写的提交,另一方面要对不符合业务逻辑的提交给出反馈,这辛苦了Validator控件,而且我们自己也要写不少代码(如果部分输入设计复杂验证逻辑的话)。接着,业务逻辑层再来一次验证,这是为了业务逻辑层的完备性,在脱离原有表现层而被第三方调用时也能确保数据的合法性。然而在RoR中却不用那么麻烦,在model中一次声明规则就行了,view中输入的数据如果不符合model的规则自然会在view中得到反馈,这种逻辑既是声明性的,又符合DRY原则。

最后,说说ASP.NET可以从RoR学习的规则。首先,MVC分离是有必要的,仅仅垂直分3层是不够的。我之前也有想过,为什么要在表现层提供众多的Validator控件,而不是在业务逻辑层提供验证相关的Helper类呢?这些Helper类,加上业务逻辑层反馈到表现层的通道,就能够做到只需要实现一次验证。或许Validator控件,也是简化表现层设计的一个做法吧,为了吸引别人学习ASP.NET,MS做了很多东西让它看起来很容易用,却让人难以全局协调。其次,一个类象征现实中一类事物的隐语仅仅是针对model的一个说法,其它时候我们更需要函数,类就仅仅是用来聚合函数。例如一条验证规则,这是一条配置,同时也是一个函数调用,需要完成验证这一顺序操作的是函数,而不是类。如果你要用类去表示规则,例如config文件映射出各个ConfigurationSection那样,这就增加了处理步骤,因为最终你还不是把类里面的属性读取出来交给函数处理这条规则。

2007年2月18日星期日

难得写影评

从来没写过影评,难得写了点相关的东西,原本发在TLF上面,得了原创精华,现在贴过来。

The Prestige 中的“执着(obsession)”

好像有不少人提问为什么Tesla不拿复制机去复制钱,为什么Angier要淹死自己,之类的问题。还记得Tesla关于obsession所说的吗(TLF版字幕翻译为“执着”)?这部电影里的人可以认为都为obsession所困,只有Cutter是清醒和实在的。

obsession可以翻译为“执着”,但显然有一定的贬义,因为这种执着首先强调的是你无法拒绝去想一样东西,你总是想着总是想着,没办法再专心干其他事情。其次,你想着的这个事情通常都是所谓的妄想,根本无法做到的,甚至你自己都清楚这一点,这显然导致所谓的“认知失调”,也就是你的两种认知互相矛盾。

你自己经历过obsession吗?如果你经历过,那么你很容易理解这些人的行为方式。如果你是一个很实在的人,不曾有过obsession,没有过例如患得患失之类的感觉,那就不那么容易理解了。

Tesla到死的时候都是被定为疯癫的物理学家,后来才追加那么多荣誉给他,可见他生时的obsession是多么的强烈——他在做很多常人认为常识之下根本不可能做得到的事情。Tesla发明了交流电相关的很多专利,还是无线电之父。想一下Tesla的那个true magic,无需导线都能点亮的灯泡,现实中的Tesla确实有研究过无线供电,不过电影里假设他已经研究成功。无线电我们已经用上了一个世纪了,然而无线供电却依然没有实现,可以想象无线供电在当时是多么天方夜谭的事情。无线电本来就可以用来赚去足够多的钱,交流电也是。Tesla完全不去赚钱,去研究无线供电,而电影中的版本则是在实现无线供电之后就帮Angier做那机器,事实上是可以理解的,这就是所谓的obsession。

Angier的也是obsession,他相信他所说的“一切魔术皆可复制”,另一方面Borden的魔术他复制不了,这是显然的认知失调。所以无论付出什么代价,他都想要超越Borden,这不是为了超越本身的个人感受,而是不再让自己所相信的“一切魔是皆可复制”受到自己所理解的现实的质疑。这种自己对自己的质疑其实是痛苦的。解释认知失调的常用例子是喜欢吸烟的人也知道吸烟有害,这时候一个人的两种认知——“我喜欢吸烟”和“吸烟对我身体有害”都无法辩倒对方,这两条都是正确的,这时候就会让人很不爽。而在Angier这个问题上,就不是不爽的程度,而是痛苦。

Angier还有另外一个obsession,就是她妻子死的时候的感觉。还记得他在洗手池憋气的情景吗?他没办法理解淹死到底是好的感觉还是坏的感觉,大多数人的常识,包括他自己憋气的结果,应该都是觉得被淹死是痛苦的事情,然而这时候非常不幸被Cutter说了一句“就像回家的感觉”,这就出事了……这同样是一个认知失调,两种理论都无法证明对方的错误,然而有第三方的办法可以证明,那就是把自己淹死。Angier选择了稍微更相信Cutter的说法,所以Cutter告诉他真相的时候也就再次出事了……

最后,Borden也不幸染上了obsession,这可能与他说过“我就有一个魔术你无法复制”有关,所以才一定要跑去后台看,这最终导致了他的死刑。当然也可能由于他确信自己的牺牲已经足够大,并且他看不出Angier有什么所谓的牺牲,所以他认定Angier做出一个更好的魔术来是不可能的事情。

个人认为,就算这部电影叫做"Obsession of The Prestige"也不过分,因为讲的就是obsession有关的故事。一个魔术,Cutter之所以说常人不能看穿它,是因为不愿意去往能看穿它的方向想,就在于常人都不希望自己是认知失调的,希望自己当前的认知是非常可信的,例如同情心驱动你尽量不去想笼里的鸟被夹死了这个可能。

为什么写“执着(obsession)”

写这篇评论,是因为在TLF看到很多很多人都会提问为什么某人不按照常规的利益最大化的思维来考虑,这是不是意味着只有少数人经历过明显的obsession?

有些事情曾经让我挺obsession的,所以我想知道这是怎么回事,是不是有另外一些人则能永远保持简单思维,不仅仅不会obsession,也不可能理解别人的obsession。

2007年2月16日星期五

学习 Ruby on Rails 真的很爽!

最近开始看《Agile Web Development with Rails 2nd Edition》,发觉感觉真的非常爽。虽然至今连Ruby语法都没完全懂,懂了的也没记住多少,但在看书过程中你会乐意模仿书中所有的例子,一个一个完成看看结果是怎样的,观察这个神奇的框架如何将你所书写的一点点代码转变为使用ASP.NET要不少代码才能实现的功能。

我不知道它是怎么实现的,但暂时我还不觉得我有必要知道它是怎么实现的,因为那种流畅的感觉太好了,所谓的"Convention over Configuration",让我完全可以凭感觉去写,而不是好像用ASP.NET的时候那样想着“你这buggy又trappy的家伙,幸好我知道你底层是怎样实现的,我可不会随便踩进你的陷阱”。既然我不用了解它,就能流畅用好,为什么我还急着去了解那么多呢?

至于"Don't Repeat Yourself"的好处,暂时没体会到。ASP.NET中要坚持DRY原则的话,要在设计上下点功夫,而我现在用RoR才写那么几行代码,根本谈不上设计。

已经很久没有一本书让我阅读过程之中有如此的兴奋感了。之前看《Programming Microsoft ASP.NET 2.0 Applications: Advanced Topics/ASP.NET 2.0高级编程》,虽然也很有feel,但那种feel不是学到新东西的兴奋,而是自己辛苦用reflector看代码查资料领会到的知识得到印证的感觉,觉得有这样一本系统讲述这些底层知识的书在手边,快速看一遍,以后就知道如何查找了,比用reflector慢慢最终慢慢理解要好多了。这种感觉准确来说,只是所谓的“松一口气”,ASP.NET给入门者的印象是很简单,然后你发现很复杂,接着你松一口气因为有人帮你将复杂的知识归纳好印成一本书方便你查阅。

看现在这本700多页的RoR的书,我能够一个晚上看50多页,因为一旦开始看了就真的不想停手。曾经有人评价RoR能让程序员惊叹“这不就是我梦寐以求的Web开发方式”,而阅读这本书的过程就让我信服了这个评价,并且推动着我一直想看下去,因为我总会想着“还有什么我梦寐以求的事情还没被我发现呢”。

2007年2月14日星期三

欲练 CSS ,必先宫 IE

“Win国天下,欲练CSS之人不在少数,大多不得要领,又或是走火入魔,全为IE所累。故曰:欲练CSS,必先功IE。”

曾经,我也属于为IE所累的行列,如今见到很多人仍然不愿意对自己的宝贝IE下手,所以决定特异写篇文章说说此事,以明辨IE到底是宝贝还是累赘。

好了,funny部分结束,按回我的习惯直入正题。之所以说IE不好,是因为IE会误导了你对CSS模型的理解,让你以为IE的理解是对的,之后无论如何你都无法用你的IE模型理论去为你那个无法在FF正常显示的CSS提供fix。更加坏的事情是,即使你仅仅针对IE设计,不考虑其它浏览器,由于IE模型绝对可以说是一只让人难以捉摸其脾气的怪物,所以你单纯为IE设计也会遇到众多难题,发现很多的效果总是绕来绕去都难以实现。

我们都知道,XHTML+CSS的目标就是实现内容与表现分离,理论上对于任何特定一份内容,我们都可以通过CSS实现任何我们想要的表现形式,或者细致地说是布局形式。虽然现实与这个目标有一定差距,但是CSS已经能够满足大多数常见的布局需求,这有CSS Zen Garden为证。然而如果你用的是IE,因为它难以捉摸,所以如果你想用一种简单优雅的CSS去让IE能够实现“任何你想要的布局形式”,那是不可能的,只有复杂繁缛的CSS才能够在IE上满足你的需求。我曾经提到过一种理论,“一个人对一个研究方向是否感兴趣很可能是完全靠偶然事件决定的,这就好像人第一次打羽毛球,如果你赢了几盘你就会感兴趣,如果你一直都赢不了你就会没兴趣”。IE在需要复杂繁缛的CSS这一点上,就足以令大多数的入门者却步。你总感觉到不得要领,你自然没兴趣学下去。

举一个例子说明这个问题,例如你不知道IE有hasLayout这回事,一个元素是否hasLayout对它的布局方式有重大影响,于是你肯定用最简单的思维去思考CSS,认为不同的CSS规则之间应该是松耦合的。“CSS应该被设计为简单优雅的”,你肯定会这样想,没错,它确实被设计为这样,不过IE不是这样去实现CSS罢了。我们用下面的代码去证明IE在quirks mode与standards mode之间的区别:
<div style="background-color: red; height: 30px">
  <div>Hello</div>
  <img style="float: left; width: 200px; height: 160px" src="blank.gif" />
  <div>Hello</div>
</div>

首先,我们用quirks mode看看结果如何,并且一个初学者看到这样的结果会去如何理解CSS规则。在quirks mode中,我们可以看到背景为红色的<div />包含了上面1行的文本,以及下面向左浮动的<img />(自然也就包括在浮动块右边的文本),在这里,我们可以建立两种认识:

  1. 容器是完整包含内容的,当内容的总高度比容器大的时候,容器就会自然伸展以确保容纳内容。
  2. 浮动块也属于上述条件所要求通过伸展以确保容纳内容。

以上规则是完全错误的,一个懂得标准CSS以及理解quirks mode的设计师将会如此解释他的理解:

  1. 因为IE在quirks mode中会将height理解为min-height,所以它认为<div />的高度不小于height指定的30px即可。而根据CSS标准,当height设置为30px时,高度就一定是30px,超出部分如何处理则由专门的CSS规则决定。
  2. 因为<div />被设置了height属性,在IE中这就让它hasLayout了,这就导致它一定要包含所有的内容,包括浮动块。而根据CSS标准,浮动块是无需被完全包含的,它就浮动在那里,除非遇到设置了clear属性的元素,否则后继内容只会侧移避让。

好了,相信这个对比足以说明问题的严重性了,通过IE的效果去理解CSS,最终只会让你的理解与真实的CSS相差甚远。详细的standards mode与quirks mode带来的标准执行差别,可以参考这篇文章:CSS Quirks mode and strict mode

然后肯定有人要问我,如果通过doctype确保使用的是standards mode,那是不是就没问题了呢?standards mode确实会让IE对CSS的解释合理很多,但事情并没有那么简单,这你可以通过实践去慢慢体会。你可以尝试在standards mode中设计CSS,并且尽力保持它们在IE/FF/Opera/Safari这4大主流浏览器中显示一致,随着设计的进行,你会发现这不是那么容易做到的。或许你不乐意花时间去fix其中的一些小问题,宁愿任由其中一些浏览器的用户看到比较丑陋的布局,但至少你已经了解到一个和上面例子类似的道理:不同浏览器即使同样在standards mode,其对CSS的理解仍然有所差异,而差异当中最多只可能有一个是正确的,甚至可能全部都是错误的。这篇CSS contents and browser compatibility就列举了众多浏览器对CSS支持的差异,一份CSS总会因为其中有一些规则在某些浏览器上是不支持的或者是buggy的,而导致你难以保持它们在不同浏览器上显示一致。

接下来可能还有人会问我,既然IE的市场份额最大(特别是在入门级的用户当中),又或者说我的客户指定使用IE作为客户端,仅仅针对IE设计CSS不好吗?为什么要针对FF之类的标准浏览器设计CSS然后再为IE进行fix?因为IE难以捉摸的脾气,让你无法将它的行为理解为一种简单优雅的规则,然后让你陷入CSS规则高度耦合的困境中。请看下面的例子:
<div style="background-color: red; border: 2px black solid">
  <img style="float: left; width: 200px; height: 160px" src="blank.gif" />
  <div>Hello</div>
</div>
<div>Hello</div>

现在,你在IE中看到的效果应该是左边出现<img />,然后两个<div />内的Hello都向右偏移以避让<img />这个浮动块了,其中上面的<div />仅仅占用移行的高度,因为它没有声明高度,所以就是自然高度,也就是一样,这些都很好理解,所有规则都是解耦的。然后向例子中增加对第一个<div />的width属性复制,看看结果会如何:
<div style="background-color: red; border: 2px black solid; width: 600px">
  <img style="float: left; width: 200px; height: 160px" src="blank.gif" />
  <div>Hello</div>
</div>
<div>Hello</div>

这时候第一个<div />完全容纳了<img />,把第二个<div />挤到下面了。这该怎么解释呢?我们可没有设置它的height属性哦,难道又犯之前例子所说的因为hasLayout而必须容纳所有内容?正解,这就是IE难以驯服的地方,一个应该是完全独立的width属性,设置之后引起了高度以外的其它影响,这让人无法尝试以一种简单优雅的方式去理解IE的行为。这就证明了,如果你要学习如何为IE设计CSS,就先要学习标准CSS,再加上对IE怪异行为的理解,比仅仅学习如何为一个标准浏览器设计要难多了。这时候你是不是想说,“如果客户愿意放弃IE,甚至全世界都愿意放弃IE,那就实在太美好了”,没错,这才是正确的想法,一心想着仅针对IE设计以求方便只会让你走火入魔。

最后,如果你已经有了一定的CSS基础,对CSS规则都理解无偏差,却缺乏组合CSS规则的想象力,无法做到所谓的“实现任何你想要的布局效果”,这也就是说,你的内功已练成,仅仅差一些表面的套路,这时候我推荐你去看《CSS Mastery/精通CSS》。看完这本书,相信你只会觉得自己缺乏布局的创造能力,而不会有布局却不知道如何实现。另外,如果你关注CSS方面的内容,可以考虑订阅我的blog:

过年之后,我可能会写一些与ASP.NET+CSS有关的文章,因为现在ASP.NET+CSS的开发并不方便,即使用了ASP.NET 2.0 CSS Friendly Control Adapters也如此,因此需要根据自己的实际情况定制配对的Control Adapter才能解决问题,这就是我接下来要研究的事情。

2007年2月12日星期一

IIS7 会重用那些不该重用 HttpHandler

首先,实现IHttpHandler时要实现一个IsReusable的属性,这个属性告诉ASP.NET此HttpHandler是否可重用。如果一个HttpHandler是可重用的,那么多次请求都有可能用同一个HttpHandler实例;而如果一个HttpHandler是不可重用的,那么ASP.NET应该确保每次请求使用的都是一个新构造的HttpHandler实例。

Page是设计为不可重用,所以每次请求都会导致构造一个新的Page实例,这是因为Page的生命周期不能恢复到初始状态,一个Page经历完生命周期后就不能用于处理下一次的请求。类似的,如果我们有一个HttpHandler有类似的性质,处理一次请求后其状态就难以恢复到适合于处理下一次请求,或者说恢复还不如构造一个新的,那么我们就应该设计为不可重用。

我在做一个通过IFrame提交的无刷新上传控件,这东西包括一些HttpHandler,为的是能够直接关联到axd后缀而用于路径无关的场合。其中有一个HttpHandler我直接继承自Page,并且写得好像aspx+cs编译出来的代码那样,在OnInit阶段构建完整的控件树。这个HttpHandler以前在XP的IIS5上一直没问题的,但到了Vista的IIS7就出问题了。

先说明,在IIS7我采用其新的配置模式,将<httpHandlers />配置在<system.webServer />节,而不是<system.web />节,这是模仿着ASP.NET AJAX的web.config做的。做好之后就发现问题了,这个用作HttpHandler的Page竟然时候抛出Exception,说Page上面有多于一个的HtmlForm。仔细检查后确认,我的Page代码确实仅仅添加了一个HtmlForm,并且这个Exception不会出现在编译后的第一次请求,于是我就怀疑Page被重用了,所以OnInit被多次执行,这才可能导致它有多于一个HtmlForm。我启用了Page的Trace,在Render中注释掉base.Render,并且用Trace输出Page上的HtmlForm数量,发现真的是每次请求都会导致多一个HtmlForm,这基本上可以肯定是因为Page被重用了。

然后我就用Google搜索,结果发现forums.asp.net上有人提出了完全一样的问题,他也是用Page来做HttpHandler。我想只有拿Page来做HttpHandler的人才会遇到这样的问题,因为一般自己写的HttpHandler都是无状态的,所以都是可以重用的。而那张帖子只有管理员回复了一句,“你最好去forums.iis.net问吧”。于是我就去iis.net搜索,结果发现没有人提到过这个问题,于是只好自己去论坛提问,可惜等了一天都没有人回答,看来IIS7普及之前iis.net的人气都不会上升(IIS7的默认欢迎页面链接到iis.net)。

最后,我选择了先采用Jeffrey Zhao建议的work around,就是再制作一个HttpHandlerFactory,它负责每次返回Page的新实例,然后在配置中改用该HttpHandlerFactory。这个解决方案实验证明是可行的,就是多一个类而已,不知道性能损失有多少。如果有人知道这个问题的官方解决方案的话,或者有一个更好的work around,请告诉我,谢谢。

2007年2月5日星期一

Microsoft AJAX Library + ADODB = ?

最近做了一个基于Web的纯桌面端数据库应用,非常轻量级的,在挑选库的时候最后还是选择了自己熟悉的Microsoft AJAX Library,而没有使用prototype、dojo、YUI之类的。一方面,是因为Microsoft AJAX Library比较贴近我熟悉的控件模型,另一方面要做的东西真的轻量级得只需要普通的控件,不需要拖放和效果,不需要封装新控件或widget。

过程

整个制作流程大概是这样的:

首先,我设计了一套CSS模板,使用Sharepoint Designer来做,配色方案是临摹着其他漂亮的table排版模板做的。在这个过程中,我真的觉得Sharepoint Designer非常好用,你需要做的仅仅是用XHTML将模板所需要用到的语义全部写好,然后开始在<style />内部加CSS,只要CSS技术过关,很快就能把整个页面格式化为你想要的效果,而Sharepoint Designer的IntelliSense则能够自动提醒你哪个class下面有哪个id或者有哪些element。在格式化好页面后,把CSS从<style />移动到独立的CSS文件,并添加对一些特定的浏览器的修正,那就搞定了。

接着,开始根据程序的需要,在XHTML上设计Page、Form等的一些常用结构,并且写了一些基本的函数来实现Page直接的导航,Form内的常见操作。我用的仅仅是函数,这些函数根据性质以类来聚集,但没有做一些代表实体的类(例如Page类),因为我相信这个东西足够简单,通过函数完成简单操作就行了,没必要将XHTML元素映射为类(控件)。在搞定了如此简单Page划分之后,Page之间就完全解耦了,然后我就可以独立设计每一个Page里面的逻辑,而Page之间的数据传递则通过切换Page的函数负责,这有点类似QueryString的做法。不过我这里Page的概念仅仅是一个<div class="page" />的元素,而传递的可以任意JavaScript对象。

数据库的操作,我反而没有做任何的封装,直接new ActiveX("ADODB.Connection"),然后就拿来用。很raw的形式,写起来的代码有点点像ASP的feel,不过ASP是直接输出XHTML,而我是构建DOM元素。实际上所有的CRUD操作都是以最直接的形式执行的,几乎不存在任何业务规则,所以也是直接把CRUD的操作封到函数里就行了。有趣的地方在于,Sharepoint Designer在一个对象赋值为ADODB.Connection后,竟然能在IntelliSense提示Open等方法,不知道这是对于ADODB等常用对象的支持,还是对于任何COM对象都提供支持。

最后需要做的,就是在XHTML上把整个界面填充完整,把函数钩上事件,这就完成了。没有任何数据控件,不曾用到ITemplate,用得最多的无非是TextBox和Button。

总结

即使完全不用于AJAX开发,甚至是没有服务器端的开发,Microsoft AJAX Library也是一个很好用的库。如果你习惯MS那套控件设计的思想与风格,那么Microsoft AJAX Library会显得很容易适应,不过前提是你已经有很好的JavaScript基础。

现在国外有一个争论,就是一个JavaScript的入门者是否可以使用库,还是说有能力自己写一个库的人才应该使用库。这个争论的来源,我觉得是因为现在的库还是太过像手脚架了,能够帮熟练的使用者提高开发效率,提高代码质量和软件健壮程度,然而对于入门者来说却会因为对基础问题的不理解或者理解偏差而到职他们在使用库的途中犯下更多的错误。

在这个问题上,我使用MFC时就有切身体会,我就觉得熟练使用Win32API的人使用MFC才能获得最大的便利,而入门者使用MFC则对着MSDN左翻右翻也不得要领。我不懂Win32API,曾经学过一点点MFC,站在VB Form或Win Form的角度来理解,总是觉得MFC设计很怪异,为什么如此多地方设计得如此命令式而不封装起来呢?在使用MFC过程中碰到自己无法解决的问题时就更麻烦了,然而懂Win32API和熟悉MFC的人却能很快告诉我——例如这是因为MFC自身的一个设计缺陷,或者是它迁就Win32API使用方法或风格的地方。

MFC就是一个如此的手脚架,让懂Win32API的人能够更高效地做一些事情,而不懂的人却无法得到抽象带来的便利,因为它并没有怎样抽象,只是将函数式API封装为对象。现在的多数JavaScript库也就是做到了这个程度,将最初的DHTML到如今标准化的DOM API进行封装,却没有太多的抽象,所以用起来还是要清楚它到底干了什么。这是因为遇到了问题有可能无法在高层解决,而必须回到低层解决。

回到争论上面来,我个人支持库的使用者必须有能力完全理解库这一立场。考虑一个不太了解JavaScript的ASP.NET开发者,他使用Microsoft AJAX Library,无论是使用XmlScript还是JavaScript,他的“活动范围”也就是sample的附近,一旦超出了这个范围,他就在“凭运气写代码”了,这时候代码质量可想而知。如果他开发出来的东西还有给其他开发者调用,那就更危险了。这种现象其实也普遍存在于ASP.NET的控件开发者中,对ASP.NET理解有限的开发人员制作出来的控件就有可能和给使用者带来麻烦。

至于什么时候能够有高度抽象的Web开发框架……想一想,MFC诞生于1992,而Win Form以来的.NET Framework诞生于2002,这估计要10年吧。或者乐观一点,VB Form的抽象也很好了,因此Win Form才那么多参考其设计,拿比较成熟的VB6来说吧,诞生于1998,也要6年。这样说来,可能也要到2012才会有高度抽象的Web开发框架出现。况且,抽象也依赖于硬件发展,当我们不再为“小小一段”ViewState占用多少流量与带宽而烦恼时,抽象才有可能实现。