做了 9 年程序开发,以国内的标准算是老程序员了,对技术还是充满热情。虽然这种想法在国内不算流行,依然在执着的坚持。
在这些年的开发过程中,用过很多框架,其中有一两年专门使用 Struts 、Hibernate 和Spring 开发项目。项目初期,有同事使用 XDoclet 写了生成脚本,可以根据数据库定义直接生成页面和框架代码,开发过程还是顺利。但是在项目的维护过程中,苦不堪言,改一个属性的名称要记得改若干配置文件,而且,项目比较紧,经常是刚刚改好,还没有完善的测试就发到现场(国内这样的情况应该不鲜见吧)。结果可想而知了,经常有遗漏的改动被客户发现,然后被经理一顿批判。总是想,如果IDE 的重构和编译检查能帮上忙就好了。“耦合点”是Bug 的一个重要来源,是可维护性的一个重要障碍。
“约定胜于配置”真是一股春风,让开发人员感觉暖意融融,当然在GreenTea 框架里,这个事实标准也是不可或缺的。
其实,Web 开发的问题不是仅限于“配置”一项,还有以下几个方面值得考虑,罗列如下:
页面操作的思维路线较长;
维持页面状态比较困难;
业务逻辑里包含了页面跳转的代码;
涉及的技术比较多,程序员要了解JS 、JSP 、标签库、模板等诸多内容;
重用比较困难,如:业务逻辑和页面的复用等;
“动”“静”未分离。
作为一个程序员,我总是在思考这些问题,怎样才能使得开发工作更简单一些,让人们更“懒惰”一些。前段时间为 GreenTea 框架开发了一个基于 Swing 的客户端,从中得到一些启发,于是将这种思想融入到这个框架中,构建了一个以“JS” 为主的客户端。
这个想法就是在开发的过程中,主要使用 HTML + JS + Java 来进行开发,减少程序员的技术要求,降低学习门槛,让页面逻辑更加直接,让程序员更加关注页面逻辑,让测试和维护更简单。
就上面提出的几个问题,我使用对照的方式,将现有框架存在的问题和GreenTea 框架带来的好处一并罗列出来。
有人说Web 开发挺简单的,是不是你头脑简单才感觉复杂呢?或许是!复杂在哪里呢?我认为最大的问题就是完成一个功能时的思维路线比较长。我简单的画了一张图,如下:
上图描述了一个简单的查询和增加的过程,可以看出来,过程不是很复杂但是非常冗长,不够直接。如果一个环节出了问题,追溯的时间会比较长,这还是最简单的情况。
GreenTea 有哪些变化呢?还是看图说话吧。
注:Business 表示业务逻辑类。
从图中可以直观地看出来,页面的调整和请求过程都是非常直接简单。在这里略作解释:
从一个 URL 直接跳转到 HTML 页面;
在页面初始化的时候,请求加载列表数据;调用的方式是:直接调用服务器端的相应方法,结果以JSON 形式返回,并使用JavaScript 构建一张表格(之前构建表的过程是使用JSP 或者标签库来完成)。
增加的过程也是类似:使用URL 调整到增加页面,填写数据后,直接保存,如果操作成功,可以跳转到列表页面;操作失败的情况下也不刷新页面,用户可继续处理。
下面给出一小段的示例代码,这段代码主要是用来初始化表格之用,如下:
// 从服务器端读取数据
// TableService 是一个普通的Java 类;list 是其中的公共方法
var service = ServiceFactory.getService('com.xy.ab.TableService');
var data = service.list();
// 创建表格
var table = new Gtable('table1');
// RowBean 是一个持久化对象,定义了表格相关的属性
var config = new TableConfig('com.xy.ab.RowBean');
table.decorate(config, data);
做过 Web 开发的程序员都清楚,一旦操作出错,请求已经提交到服务器端,页面已经发生变化,所以返回出错的页面时需要恢复之前状态,这个过程是非常繁琐,易错的。特别是有相关联的数据时,如有两张相关联的主子表,处理起来尤其麻烦。还有一种情况,当多个页面之间需要传递参数时,特别是跨页面传递时,也需要时时记得在中间页面添加“隐藏域”,苦啊!!!
如果使用 AJAX (也是GreenTea 框架中使用的主要技术),这些问题就迎刃而解了。
传统的Web 框架多是将业务逻辑和页面逻辑混杂在一起,理由是业务逻辑的处理结果会影响后续的页面流向。就我本人的经验,页面逻辑和业务逻辑还是分离比较好。其一,由于耦合性降低,业务逻辑复用起来比较容易,因为在哪个界面上的调用都是一致的(之前使用PB 和 Delphi 开发的人员体会应该比较深);其二,页面逻辑都在页面上,处理逻辑会比较简单,容易理解。
下面罗列的技术在项目中不一定都使用,但是程序员一定要在每个层面上都会一两种,技术牛人呢除了精通两三个之外,应该大体都了解。
浏览器脚本层:JavaScript 、JQuery 、prototype 、DOJO 、ExtJS 、...
视图层:JSP 、JSTL 、Struts Taglib 、Tiles 、Velocity 、FreeMarker 、...
服务层:Struts 、Spring 、WebWork 、JEE 、...
持久化层:JPA 、Hibernate 、iBatis
GreenTea 的目标:
浏览器脚本层:JavaScript 、JQuery 、prototype 、DOJO 、ExtJS (用的基础内核是JQuery )
持久化层:JPA 、Hibernate 、iBatis
在我供职的公司内部有这样一个习惯,在程序开发之初,业务分析人员都会使用HTML 编写一个界面原型,便于和客户确认功能。但功能确认之后,这个原型就被丢弃了,因为开发人员会使用生成工具再重新生成一个 JSP 页面。因此,这些页面工作还需要重新复制一遍。如果能重新利用这些页面即可以减少重复工作,也可能会比程序员做的页面漂亮一些。
“动”即业务逻辑,“静”即HTML 页面。应用服务器的强项是数据运算(业务逻辑运算)而非字符串或者文件处理,而相对静态的 HTML 页面可以通过其他的手段提供更好的性能,比如使用反向代理进行缓存。因此,更好的方式是使用文件服务器处理静态页面,而应用服务器只关注业务逻辑的运算。JSP 的最大问题恰恰是其需要同时完成这两个功能。而且,HTML 和 Java 代码混杂在一起也导致了页面的难维护。
还有一方面的问题就是效率的问题了,因为页面逻辑和数据混杂在一起,每次刷新都要下载所有数据,如果只传业务数据,性能无疑会好得多。
当然,这个方式目前还存在一些问题,比如:需要程序员对 JavaScript 有比较深入的了解,具备更强的调试能力;有些复杂的功能还没有实现或者没有在实践中验证。GreenTea 并不排斥 JSP 和标签库,并且也带提供 JSP + Taglib 形式的客户端。在某些复杂的情况,JSP 也是不可或缺的,因此他们之间不是排斥的关系,而是互补的关系。还是那句老话,技术没有对错,只是选择的问题。
这是一个演示程序 ,采用标准的 War 包形式,直接放置到应用服务器的发布路径就可运行。其数据库是一个内置的数据库,业务逻辑部分的源代码在“src” 目录下。
这篇文章里介绍的稍微理论化一些,请参考我在后面补充了一个更为感性的 Hello World 。