快速开发 WebApp

前段时间,女朋友的学校里面要求写一个小型的 MIS 系统(课题为客房管理系统),虽然老师是要求使用 .Net 进行开发,不过女友说服老师允许她最终使用 Chrome Apps的形式完成作业。因此开发系统这个艰巨的任务就落在俺的头上了(IT男就是新时代的苦力)。

代码已经到Github,需要自取:Hotel-Manager-for-School-work.

功能需求

在网上找了个需求,原有的一共有四张表,将顾客和账单分开来做。但是针对简单的MIS系统,完全不需要使用单独的表来保存顾客的资料,所以就将顾客表整合到账单里面,使得系统更加精简也容易开发。

简单的需求功能如下:

  • 管理员的添加,修改,登陆。
  • 客房的添加,登陆,查询,排序,checkin,checkout
  • 账单的查询(根据顾客信息,客房信息等)和结算。

技术选型

因为时间紧迫,加上之前并没有代码积累,因此要迅速开发一个简单的单机版应用程序相对还是比较困难的,好在JS的库非常多,组合选择如下:

MVC 框架及设计模式

使用 Backbone.js 来做,这套架构简单明了,配合观察者模式来写非常方便。Template方面使用了handlebars.js来做模板渲染。

UI Framework

当仁不让的首推 jQuery 配合 Twitter Bootstrap 来做,方便快捷。另外为了添加酷炫的效果,使用了isotope.js来做选择排序。

DB 层

在Chrome里面,说到DB,是可以同时使用indexedDB以及WebSQL的,但是根据需求来说,最好选择WebSQL,因为IndexedDB并没有全文检索的功能1

WebSQL 在github上面也有非常多的功能库,这次我还是使用了比较简单容易的Snake.js.

Loader

使用了一直在使用的yepnope.js来做。

其他

一开始选择了Less.js 但是直到最后都没有使用上,因为没有在Twitter Bootstrap上面做太多的更改。

增加了一个dateformat.js 来实现类PHP的日期格式化方法,很纳闷为啥JS不能直接提供这类的方法。

开发要点

观察者模式开发

虽然Backbone使用了hashchange来做route,但是在实际开发的时候我并不喜欢。

  • 由于测试的时候一直需要刷新,如果直接使用hashchange在测试的时候会导致很多的问题。
  • 对于route来说配置起来非常恶心,代码并不简洁。
  • route本身可能产生耦合问题。这种耦合使得代码掺杂在一起并不好看。

因此最后还是用Backbone.Event来做了一个简单的Observer,所有的View都关联到Observer的事件上来就好了。其实现原理其实有点类似route,只是耦合度更加低了,不过需要注意以下问题:

  • 事件名称的约定:目前我的做法是哪个view触发的事件,就以该view的名称作为namespace,后面加上该view的事件。
  • 事件绑定的顺序问题:可能有部分view同时相应一个事件,而两者之间的数据可能会有先后依赖关系,这个时候尽量要将view之间的耦合度降低。如果不能解耦,那就需要注意事件注册的先后顺序。

不过有时候Observer并不是一个,在公司的一个项目开发的时候, 对于几个View同时依赖一个 collection 的时候,可以将这些View的相应功能绑定在全局的collection事件上面,这个collection上面的事件也可以做到类似Observer的功能。

虽然并没有他人提示,只是想着如何利用Backbone的Event来解耦,唉,可惜这个想法Dexter.Yy2早就分享过了(凭什么记忆力要这么好?)。当然作为小型系统,并没有那么复杂的状态转移啦一次完成,以及先后顺序流之类的玩意。不过观察者模式对于这种到处乱串的场景非常有益。

使用ORM (Snake.js)

其实作为配合Backbone使用的WebSQL ORM,最好的不是Snake.js,而是 MarrLiss写的Backbone-websql3,它直接将Backbone的model sync 映射到了 WebSQL 上,简化了Model的编写。 但是出于懒得学习的想法,还是用了Snake.js,但是在其上面封装了一层storage。

(function(exports){
	'use strict';
	var   config = exports.config.websql
		, api = {}
		, db = {}
		; 
	exports.storage = $.extend({}, api);


	if (!config) return false;
	db = new Snake(config.config, config.tables, config.pre_sql);
	if (db){
		Object.keys(db).forEach(function(item){
			exports.storage[item] = db[item];
		})
		exports.storage.db = db;
	}
	exports.storage.clear = function(){
		localStorage.clear();
		exports.storage.db.SQL('DROP table bills');
		exports.storage.db.SQL('DROP table operators');
		exports.storage.db.SQL('DROP table rooms');
		console.log('Drop all tables');
	}
	console.log('initialize db finished');

})(App);

这样就将db对表的访问简化为 app.storage.bills这样来访问了。

使用Twitter Bootstrap进行快速UI搭建。

作为前段方面,觉得最麻烦的不是JS的部分,而是最纠结的HTML部分。要写大量的代码,也要进行大量的调试,幸运的是,我们有了Bootstrap。通过简单的库和CSS的引用,加上直接复制 官网的参考代码。差不多一个小时就写完了整体的UI功能,而且看起来也觉得非常不错,虽然女朋友觉得不好看。

总结

整体来说,开发一个WebApp Demo,如果明确,开发速度是抵得上传统Native应用的,尤其是在如此多开源库支持的情况下,开发难度已经被大大降低了。但是还是手写了大量的代码,开发上不如.Net那么可视化。

数据库

如果只是针对这个应用而言,个人觉得WebSQL被放弃的太早了。这个本应该是DeviceAPI的加强,而不单单是给传统网页前端人员用的。去掉了WebSQL之后,虽然IndexedDB也是能用的,但是缺乏了全文检索和Sort的功能,无形当中增加了程序本身的负担。搜索全文检索过程当中,曾经看到Google Group有人建议先将内容全部读取出来再去正则匹配,虽然这样是可行的(可以使用WebWorker来开多线程做这个事情),但是不如WebSQL本身简单方便。况且IndexedDB在写open的时候也并不比WebSQL简单到哪里去。而且使用WebSQL的话,SQL本身是前后端通用的,如果不讲究太多安全性的话,这样反而极大简化了前后端的开发难度。想到这里,难道是因为安全性的问题所以放弃了WebSQL么?

更快速的开发

开发的时候发现大量可重用的地方,实际上可以基于现有使用的库来构建比较快速的开发方式。但是现在依旧没有比较快的解决方案。因此开发这个程序用了差不多8个小时,其中架构用了4个小时来码代码,2个小时用来解决WebSQL的数据库同步问题(本来这里应该使用backbone.Websql来解决,但是时间不够,因此没再继续深究下去了)。2小时用来解决重复性代码的差异。 基于backbone的开发以及观察者模式的确可以更快的解耦。目前所有的form表单也是以组件的方式来走的,应该可以在html做标识,然后继承统一的backbone.form来做这些简单的事情。

但是还是需要类似VS.Net一样的工具来简化大家的开发流程,使用拖拽和数据绑定的功能迅速做出相应的内容出来。话说这是可以可行的方向,结合maqetta来做类似的事情。

  1. https://developer.mozilla.org/en/IndexedDB/Basic_Concepts_Behind_IndexedDB#Limitations 

  2. http://www.limboy.com/2011/07/10/mvc-behind-alphatown/ 

  3. https://github.com/MarrLiss/backbone-websql 

Q.E.D.