Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2012-01-07) Extjs使用感受

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

在公司做项目时,后台管理页面都是用extjs来写的。这个过程很痛苦,因为手写js代码很容易出错,经常因为写错一个字母标点、少写一个参数,效果死活出不来,还抛一些奇怪的错误。这不能怪我们不细心,因为实在是太容易出错了。调试的过程异常痛苦,因为基本上得靠肉眼一行行地检查,无法发挥机器的优势,一卡就是一两小时。

这个感觉,在只看Ext那华丽的Demo,或者在动手写代码之前,是很难感受到的。我刚接手这个项目,看到公司其它产品华丽的界面时,在群里还欣喜地跟大家说,“使用Ext做出来的界面真好看,功能真强大”。当时刘松说,他们之前用Ext做项目时,调试过程太痛苦了,后来再也不想碰Ext或类似的js gui框架。我还奇怪,有这么多的Demo可供参考,这么多产品都用它做出来了,还会遇到那么多的问题吗?

现在果真体会到了。使用Ext做项目,靠的就是经验、记性和眼力,以及时间。Ext中的定义的一个类,初始化参数常常有几十个,传入不同的参数就可以得到不同的效果,不同的参数进行组合又能得到另外的效果。而这些参数只能查文档,编辑器是给不了提示的。但总不能每用到一个类就要去查文档吧,所以要牢记每一个参数和用法,才能加快开发速度,这时要靠记性。在输入参数的过程中,如果参数名里不小心输错一个字母,不会报错,但效果就是出不来,因为那个参数实际上被忽略了。这时只能靠一个个单词去看,跟文档对比,才能找到错误原因,这时要靠眼力。Ext的一些组件(特别是老版本,如我们公司使用的2.x版)在不同的浏览器下会有不同的显示效果,比如fieldstet在IE下正常,在firefox下里面东西全被隐藏了。所以我们还得知道如果去绕开这些bug,这要靠经验。每当遇到一个新bug,或者死活查不出原因的时候,那就只能靠时间去耗了。

所以,使用Ext,在你在熟读其源代码并且累积了大量的使用经验之前,基本上可当成是体力活,因为可以让机器帮我们完成的事情太少了。

还有更麻烦的。

Ext本身是希望以一种面向对象的方式来开发和使用,以实现组件化。但是因为Javascript语言本身的语言特性,这一点在实际使用过程中比较痛苦。在Javascript中,一个function中的this指代的对象实际上是不确定的,它默认是调用者,还可由fun.call与fun.apply的第一个参数决定。所以当你在一个函数中使用this.xxx()这样的方法时要非常小心,因为如果这个函数在其它地方被调用,它很可能就出错了。在写Ext代码时,很多功能都是通过回调函数来实现的,如果在里面调用了外层的某个方法,经常会报错“xx方法未定义”,原因就是this指向的对象错了。

要解决这个问题,有三种方式:

  1. 使用Ext提供的scope参数,把外层的this赋过去;
  2. 在外层定义一个变量,如var self = this,在里面直接使用self来引用外层对象
  3. 都使用全局变量,直接引用,丢开面向对象。

这三种方式都有各自的局限性:

  1. 第一种,每个需要回调的地方,如listeners等,都需要加一个scope:this,很繁琐;当在回调函数中还需要回调,有三四层的时候,那就可怕了,光这些scope就能把人看晕。
  2. 第二种,我们经常是以json的方法去传参数,但有时候没有机会去定义var self=this,或者要在多个地方定义var self。而且在代码中看到self时,还得去找到底它是在哪个地方被定义的,才知道程序到底在调用谁的方法,麻烦。
  3. 第三种,写出来的代码没有条理性,本来是有嵌套关系的,都成了平级,有时候还会发生命名冲突,读起来费劲。

我刚接手项目时,看到里面使用的某些js文件,里面的代码都是用第三种方式写出来的。在阅读的过程中非常痛苦,对了理解那几千行的代码,我花了几天时间才看懂。所以我模仿Ext本身的写法,把一些功能按类的方式组织在一起,看起来清楚多了。我要求几个同事在写Ext的过程中,也按这种方式来写。但是不久就发现,这样实在太容易出错了,随便写两句代码就会报一个“某某方法没定义”的错误,很麻烦。然后改成了第二种,但情况并未好转多少,总在为在哪儿定义var self而发愁。最后又回到了第三种,完全放弃了复用,大家都靠记忆力来写吧。

在Javascript中按面向对象方式来写代码,是件吃力不讨好的事情。这跟Javascript的语言特性有关。曾经jquery有一个竞争对手叫mootools,它按面向对象的方式来设计api,对于我们Javaer似乎比较有吸引力。但是最终结果大家都知道吧,jquery全胜。

所以在Ext中,最好的方式就是先写一些通用性的代码,把参数定义好,放在一个地方当作模板,用的时候把它拷过去改改。只有在需要定义一些小的复用性很高的组件时,才有必要按Ext的方法,构造一个类出来,注册到Ext中。其它时候怎么舒服怎么写吧。

正是因为这个原因,使用Ext做项目时,要写很多重复代码。哪怕是非常相似的功能,也很难复用,所以开发效率并没有随着项目的积累而提高,反而还会增加维护量。我们在Java或者其它语言中累积到的设计经验,在这里用不上;我们没有好用的工具来帮助我们减少错误;我们会变成Ext的“熟练工”,适应它,而不是掌控它。

所以对于一个缺少Ext资深熟练工的团队,使用Ext是一件风险很大的事情,因为我们没有办法预估它到底要花多少时间,人品值是一个重要因素。一个功能,如果一切顺利,也许一两天就搞定,但是,也很可能花上一周。在制定工作计划的时候,经理只会按照最顺利的情况来给你预定时间。如果你对项目经理说,“做这个功能需要8个小时,因为可能会遇到一些问题卡住”,项目经理会怎么想呢?“这么简单的功能,就画几个界面,也要8个小时?3个小时都够了。出错那怪你自己不细心,自己加班补吧”。

所以用Ext做项目很累,直到你忍受不了而离职,或者熬成熟练工。

所以我打算彻底抛弃Ext,远离dojo/qooxdoo,也许vaadin/gwt才是正确的道路。

comments powered by Disqus