个人简介 曹晓钢,满江红开放技术研究组织创始人,在软件开发方面有着多年的经验积累,热衷于开源理念与开源软件的推广。此外他还有多本译作及原创书籍出版,如《深入浅出Hibernate》、《深入Java虚拟机》、《J2EE Development Without EJB中文版》等,曾是《Dr. Dobb's Journal》中文版编委会常任委员。
感谢上海卡内基信息科技有限公司提供场地支持!
1. 请评价目前市场上流行的企业应用开发框架。
从Web角度来说的话,如果说我拿到一个新的框架,那我会从几个方面来评价它,第一方面,它对Web端事件模型是如何封装的;第二点,他对组件是如何支持的,特别是对业务组件如何支持的。举例来说,在页面上面,我希望显示企业信息的时候,或者说客户信息的时候,那么我希望能够直接引用一个客户信息这样的组件,就能够显示出包括客户的名称、客户的简称、客户的预付款金额、客户的帐务情况,这样的一些完整的组件。可能这样的一个业务组件,并不是现在很多的Web框架所主要考虑的一个内容,但是我相信,从真实的实际的应用开发角度来说,到这个角度(程度)是不可避免的事情;第三点就是说业务框架,集成框架如何来处理数据绑定的事情,如何跟后端的ORM能够进行有效的集成,如果说我跟后端ORM是没有任何集成的,那么实际上,就变成结构化的东西,在后端必须自己做这件事情。如果是能够集中ORM集成,那么我后端的MetaData能够多大程度上简化前端的开发,这是一个要考虑的一个问题。
那么在从这几个方面,我觉得,我就能够把握住这个框架到底对我是不是有用的,到底是不是能够适应企业开发的一个应用。那么当然了,还有其他的一些特性,比如说性能问题,比如说对扩展性的一些把握,还有对可测试性的一些问题,虽然对Web的开发来说,它的性能,它的可测试性是一个非常大的问题,包括Dojo,包括qooxdoo这样的一些组件,在客户端的性能,就是相当的差,必须做很多的选择,然后再减小包的大小,你才能保证相对的性能。在这个角度上来说的话呢,我是希望,从浏览器的角度上也好,或者从框架自身的角度上也好,能够进一步提高它的性能,才能够更好地用在企业开发上。
2. 如果在企业应用中使用开源框架,今后的趋势又是怎样的?
那我可以介绍一下,就是说之前几年我在开发中具体使用的一些情况。刚开始的时候呢就是说,其实最开始的时候我很早,在JSP 0.8或者0.91的时候,那时候开始写Java程序。刚开始的时候呢,是一个相当无序的一个情况,直到后来出现MVC 1和MVC 2上这样的架构,慢慢逐渐(好)起来,但是实在来说,这个市场呢,比单用Delphi或者之前的CS开发呢,存在着很大的一个区别。首先一直以来没有组件这样的一个模型,导致你自己写JSP的时候,(就算有taglib,)就算你用了Webwork,就算你用了一些Spring,你仍然需要写大量的业务代码,这一点没有得到任何根本的改善。那么我觉得,从近两年开始呢,从这一点上来说,开始有了比较大的改善(迹象),比较大的一个特点呢就是像Seam这样的组件的出现,那么你要说我现在对什么感兴趣呢,就是说对Seam这样的一个组件式的开发相当的感兴趣。我们可以看到,像Spring,像那个模型,它对业务建模并没有带来很本质性的一个大帮助,(之前)我举的例子来说,就比如说,我们在写应用程序的时候,经常遇到这样的情况,我需要在界面上放一个客户的一个表示客户情况的一个Box,一个框,或者一个组件,它里面可能包含有四个字段,包括说我的客户,他的简称,他的全称,然后他的应付帐款,然后他的一个信用评价,这么一个程度,那么我在业务中认为这是一个业务的体现,那我可能在十几个不同的页面中,都同时会引用这么一个客户的一个状况的一个界面。但是假如说,当我这十个界面我都要去自己去写四个Field,或者用(类似)什么样的方式来做,那么我觉得,这是一个很不可接受的这么一个事情。
现有的这些MVC框架没有帮我解决的问题,那么我要怎么样才能解决这个问题呢,那唯一的办法就是对页面和后台的组件,我能够衔接起来,第一呢,把页面也组件化,第二,要能够处理好组件化所带来的事件和包括我界面上的数据组装,带来的这种影响。在这个意义上面来说,我从业务上考虑的事情,我要要求的就是说,第一框架本身是要足够健壮足够易用的,我要能够有很快的方式,能够组建出一个业务的雏形出来,那当然了,我不可能指望在BS架构下达到像以前CS下的Delphi或者VB这样的一个开发效率,这样的开发进度,我能够第二天就拿个模型去见我的客户说,结果就是这样这样的。(第二)我至少在里面,要能够重用我以前做的这些成果, Delphi里面,它是允许你把它自己现有的组件很快地就能组装出来,做成新的组件来使用的,或者说我可以通过页面之间的继承关系,我能够把一个Form作为一个BaseForm,然后所有的其他Form都来继承这个Form,达到一些基本的封装。那么在这一点上来说的话呢,我对现有的所有的Web框架都是很不满意的,因为它们还没有达到这么一个抽象,组合的形式,那么我觉得在所有的这些框架里面,可以说JSF是最接近这个目标的,而且Seam这样的一个组件框架是目前为止,最健壮的,最最能够反应出事物的本质的。
3. 那用于企业开发的这些Java开源框架之间各自存在哪些优势和劣势?
我觉得就是说像Spring这样的一个组件,主要的大家会比较拿Spring和JBoss的一套体系来做比较。首先我觉得JBoss来说,现在从标准上面或者说从商业推广的进度上来说,都是领先Spring的,一个就是说,它的确是将很多很有价值的组件整合在一起的,而且特别是,像Hibernate已经上升到JPA标准这样的一个组件,,然后呢包括像Seam这样的组件库里面也让人有新的感觉。像Spring的话,它更加有点像草根的感觉,就是能够真正的解决开发人员平时遇到的一些很大的问题,但是我的感觉是什么呢?它没有一个很大的支撑,没有一个说,让你能知道说,我过三年,我过五年之后Spring到底能不能够成为一个新的主流,我觉得在这上面的话会有所疑问。例如说,我现在用Spring,用他的整个一套体系,用IOC这么一个容器,但是呢,我用容器能带来的一个好处,我是从一个技术人程序员的角度上来说,我能看到说,我后面的Webflow能够使用它这东西。但是我对于他是不是能打通前后关节呢,能够把我用容器管理的Bean,以后我能够直接在Web上面来应用,能够跟后台的JVM或者其他的Workflow的框架能够整合起来,那么在这一点上,我觉得只能取决于Spring各个库的各个Section,它的开发的进度。
但是呢,我们现在可以看到,就是像JBoss这样的另外一种方向的话,你能看到这种保证,至少能看到他们中,那么终于有一天我可以得到像我刚才所想象的这样一个比较好的WEB业务开发的一个框架。 可以说Java的现在的Web表现层比.NET的表现层差距还是比较大的,我觉得如果我现在去开发程序的话呢,我不太愿意说,我用Java建立这么一套框架,自己搭建一套新的系统,当然我现在实际的真实的开发中间,我是这么做的,但是如果让我仔细的从各个方面,业务成本的方面,或者其他的各方面来考虑的话,假如我现在开启一个新项目,我愿用BS结构,但是我可以采用嵌入ActiveX控件的方式,或用其他方式,让我能够避免用现在所谓的HTML和JavaScript组件的RIA应用,所带来的不稳定的一些因素。
4. 那么像纯的这样的HTML的组件库,在企业应用开发中是怎么样的一个应用情况呢?
我觉得企业应用主要有两种情况吧,一种是使用一些比较轻量的一些组件库,比如说Prototype,或者是像jQuery这样的组件库,另外的情况呢,就是应用一些相对来说比较重型的,比如说Dojo这样的方式来做,实际上呢,第一种方式用的人会相对来说少一点,因为它看不到太多的好处,那么第二种方式的话呢,我自己以前曾经用过Qooxdoo,,但是那段时间其实带来的经历比较惨痛,因为主要的后来发现使用Qooxdoo,很多是我们使用的问题或者其他一些问题,带来比较严重的效率问题。比如一个页面,我弄的页面如果展示需要两三秒钟,我的整个应用就是不可接受的,是非常大的一个代价,最后呢,我们换到Ext上面来。其实我的第一个基本的观点就是说,你在这种两难的决择下,做得任何选择都有可能是一种赌博,你不知道你现在用Qooxdoo,或者是Ext到底能不能在两三年之后还仍然获得比较好的一个成长。为什么呢?因为所有的这些组件库之间有一些内在的不一致性,首先他们都分装了DOM里面的事件机制,但是这种分装的事件机制,都是不一样的,就面临着说,你选择的这种事件机制,你可能在一两年之后,发现说由于整个组件库发展不尽如人意,你想切换到另外一种组件库的时候呢,你根本上很难切换过去,你就被粘住了。
本质上来说,这是因为现在HTML的分裂的现状造成的,所以说浏览器大战中间,我到现在为止,FireFox和IE之间的DOM的事件模型,都还存在不一样的地方,产生了很多的封装,本身这种封装就是不规范的,那么我们现在在诸多的不规范的封装里面选择一种来使用,就是很冒风险的事情;第二个就是说,你把这种框架跟后台的你的整个的一个Java的一套体系结合起来的过程中间也会遇到很多的问题,因为所有的这些框架在前端的话,它们对数据绑定都是没有特别多的考虑,但是我们再到后台的时候,我是希望我能够把我EJB3或者说Hibernate里面所产生的ORM的对象图,整个的一套面向对象的一套定义,我能够直接穿透到前方去,能够在我的JSP里面或者说在我的前端的Web浏览器环境里面能够直接使用。
举个例子来说,NOT NULL这种属性,我在业务上面来说,我这个业务,我需要在我的一个标志上面打上一个黄色的星号,提示客户说,这是个必须输入的属性,并且如果他不输入的话呢,我要进行一些校验,告诉他出错了,那这种情况,我不希望我在前面我再重新定义一次,我不希望就是说像类似的这种东西,我都要重新来做。这是个很烦琐的事情,我当然希望我在服务器端,在我的操作界面,在我的pojo里面,我用一个annotation,把这些定义完之后,所有的一切事情都是自动化完成的。那么放大来说,前面我说的业务组件也是一样的,业务组件,我在后台一定是用一个语义模型来把它调试出来的,那么我怎么样在前台的界面里边展现这个模型?我可以用不同的View,但是我希望我定义完View之后,我前面的整体就能够组合起来。那么这件事情,所有的现在前台框架都没有替我做这件事情,所有后台的这些组件库也没有替我做这件事情,那么这个事情是我自己来做的,那么我觉得就是说在企业领域里面,这是以后所有的这些框架所面临的一个主要问题,需要解决的一个问题,但是呢,我不确定,它们是不是以后能替我们解决,所以可能我们还不得不继续做这种工作。
5. 那你觉得就是在企业开发中这个业务组件的重用,今后会不会是一个比较大的一个方向呢?
不光是今后,包括这么多年来,大家写程序的时候,实际上,一直是在做这种重用的工作,比如说,刚开始的时候,大家用JSP的Tag来做这种工作,我以前自己也做过这种工作,当然后来很多时候被证明,这是一个事倍功半的工作。但是不得不承认,最简单的JSP include,虽然能够带来一些便利,但是有可能让你的代码变的很难解读,很难懂,但是我觉得如果组件,业务组件本身能替你完成这些事情,这是一个很漂亮的工作,我当然很期待这种事情。
6. 刚才你就提到这个用组件化来实施项目的这样的一个思想,那么就是说在你现在具体实际项目实施当中,你是怎么去实现这样的一个思想的呢?
是这样的,简要介绍一下我们现在具体的一个做法,我们在前端的话呢,是用Ext,然后后端的话呢,是用Spring做容器,然后用Hibernate来做一个数据存储的一个解决方案,那么在这个过程中间,我用Buffalo,就是陈金洲同学写的Buffalo来做中间的数据转换的一个过程。然后在前端,我们是模仿Delphi,把页面上所有内容,我分类成一个描述办法,然后再把它渲染出来,在客户终端中间就需要用一些Data Source为某个页面提供数据;例如来说,一个典型的CRUD界面,可能是由一个List页面和一个Detail来组成的,Detail呢,可能相对来说比较复杂,比较复杂在于什么呢?它可能自己内部包含一些Grid来表述一些它的一些属性,简要的来说,我们可以举一个例子吧,比如说我们维护一个客户,客户可能他还有他自己的上家,他还有下家,那么在这样的一个页面中间的话呢,我们可以牵扯到三个不同的对象,就是说首先是客户本身,那可能还有客户的上家对象,客户的下家对象,那么在这个页面(开始),可能是一个List页面,点击List页面之后的话,(界面转变)变成一个Detail,Detail页面上方显示客户他的一些详细的一些情况。那么在下面是Grid,两个Grid,分别显示他的上家的一些内容,和他的下家的一些内容。那么具体在Detail的界面里面呢,有可能需要三个Data Source,一个Data Source是客户本身自己的一些数据来源,那么还有他的上家,他的下家,这是两个独立的Data Source,关联到后方去。
实际上,我们知道在服务器里面,我们定义的Hibernate是一个对象图的一个关系,那么客户对象他用一对多,关联到他的一个上家,再用一对多关联到他的一个下家。那么在前端,我们定义完整个的后端对象图之后的话呢,我们在前端不应该在定义上面的这么一个对应的关系,我只需要表明说,我一对多关系在前端我需要用Grid来体现出来,然后我在定义我这个Grid里面,我使用的这个一对多的关联他的这个对象的他哪几个字段,分别去怎么样显示的,那么OK,页面自动的就会知道,我把Grid定义出来,并且Grid里面每一个字段,它应该是什么类型,添加的时候呢,可能有些是预期类型。首先它是一个Lookup的类型,甚至它在Lookup另外的一些体现。那么在这样的一个情况下,我们就认为说,我们可以把它的业务定义,把它的Domain的一些Metadata一些属性就可以穿透到前端来,减少前端编写的时间。
当然了,具体的一些业务的问题仍然是需要在服务器上做的,我们不鼓励业务逻辑放在前端来解决,还是放在服务器端来做业务的一些处理的,在整个过程中间比较复杂的一些就是说,第一我对组件的一个抽象化的处理,那目前我们在客户端呢,把整个组件分成了两种,一种是容器类的,另外一种就是字段本身的一个就是业务表示,你例如说,我们认为Grid和Field Set,这是两种最基本的容器,然后在容器里面的话呢,我会用不同的形式来表达我的业务的一个字段,可能这个业务字段是一个lookup的一个table,或者是abstraction的一个box,甚至可能是我们今天做的是用拼音来做的combobox,输入前两个字母之后,我就把符合声母的客户名称列出来,那么也有可能是一个Grid,但是Grid里面的话呢,我需要另外一个定义,那么比较复杂的一个问题呢,就是一个事件的处理,那么在整个的一个模型中间,对事件已经是做一个包装的,我们目前呢是基本上直接使用Ext的事件,那么事件,特别是在需要跟服务器端交互的时候,如何映射到服务器端,那么这点我们觉得我们做的还不是特别好,那么在这一点上面,JSF它是有一个比较好的解决方案,特别是说Ajax for JSF这样的一个解决方式,它是利用一些Tag,然后在Tag上面直接指定说,我能够访问到后端的JSF具体的一个事件,这点上面呢,我觉得我们也可以向Seam构架学习,这点上,这是我们以后努力的一个主要的方向。
7. 假如今后你有无限的时间和精力的话,你要解决这样的一个项目中出现的问题,你会怎么样去选择呢?
实际上企业开发很多时候都是一个Trade off,就是个妥协的过程,我们在运作的过程中,开始的时候,也设想了很多先进的一些方式来解决问题,但是最终呢,由于时间的问题没有想出很多办法来实现,那假设说我要想列出一些主要想解决的问题,第一个呢就是说,我要给我的form编辑器写一个比较好的一个实用的一个小的编辑方案,能够让form编辑变的简易一些,如果说能够达到像很快的给客户做一个演示出来,那我觉得对整个项目是有很大的帮助。目前为止的话呢,我们在服务器端用编码的方式,是用类似于我们自己做的一套类库来做定义的工作,但是呢可能是需要用更加好的机制,比如说Ruby DSL定义成form,来定义之间的这种交互性的操作。然后这样是一个比较好的一个方式,第二个呢,就是说更综合了,有一个更好的结合,在这一点上的话呢,我觉得像现在Seam的一些处理方法是值得我们借鉴的,比如Seam它是把Pojo跟后端的JBPM,能够完整的连接在一起,这样的话就能够很好的利用服务器端的工作流的基础设施,那我们现在因为没有太深入,所以我们自己呢,就是做了一些小的一些改良,是比较微不足道的,很难具有说服力,这点上面的话,我们是希望的能够有所改善,能够跟后端结合的更加紧密。
那么还有一个就是,主要的一个比较大的问题就是效率的问题,就是客户端的效率的话呢,因为由于时间的关系或者其他原因,我们没有办法做更多的这种效率优化的工作,如果能够有这么多时间的话,你客户端,就是Ext如何在具体界面里面使用的时候做更多的选择,然后呢,做更多的局部优化,能够满足效率的提升。你比如说我刚才说到的,我说我用Ajax从服务器端调出一些数据来,但很多时候呢,事情是可以优化的,你比如说我第一次装载页面的时候,我完全可以说,我把数据我就直接跟Ext页面一起传递到前端,节省掉一些解释的时间,你甚至于可以说,我把能够把缓存的JavaScript,我尽量能够缓存到客户端,甚至于使用NETBox这样的一些其他工具,我把整个JavaScript我都处理了,做一个小的客户端界面出来,这种事情都能够明显的改善客户端的用户体验。