2013年初作为开发工程师加入阳光书屋,正好一年总结下。
我们这产品可以说是比较简单的,就是一个可以让学生在pad上做题的Web App,叫阳光提高班,做单选多选什么的。所以主要是支持离线能力时,上下行数据通路的问题。啊还有,实际的使用场景中,一个班级可能有一半的平板不能连上网络(都是泪)。
第一阶段,sqlite传球
Android端有关的APP有俩,一个这个提高班的APP,一个叫daemon,负责server与提高班之间的数据管道。
当时呢,下行数据是这样的。
- 服务器提供一个API:根据传入的timestamp,给出这个时间点后面所有的数据库修改,daemon拿到这数据来更新自己的sqlite。
- daemon暴露一个provider给提高班那个APP, 由提高班主动拉去数据
- 提高班呢,把数据从daemon拿过来,存在自己的sqlite里。
- 再说提高班本身就是个webview。html js什么的都存在apk的asset里。inject一个object到js里,把数据从java扔给js。

上行呢,就是把熊孩子们做题的记录传回给服务器。因为有离线这需求,所以自然要做一个队列来存放所有要回传的数据。流程是这样。
- js把数据通过上面的方式把数据传回java,java把它存到db里,再扔给daemon。
- daemon把数据queue下来,碰到晴朗的日子就把数据发回给服务器。
好了,我的任务是用backbonejs做一个完整的学习逻辑在asset里。
具体的开发流程就不说了,由于没有产品设计,各种混乱。
第二阶段,好啦,终于可以说重构了!大概7月份开始吧。
嗯,为啥要重构呢
- 一片儿数据从服务器到js手里要转三道手,daemon,提高班,injected object。
- 这几道手中,数据的形态变了又变。有sql语句,有table,有java object,有json。
- 以上任何一个环节出错就挂了。 恰好这三个环节还是三个人分别负责的。
- 前端的一个小需求变更,就需要环节中每个人对代码的修改。
好,开始重构。基本就是我甩开膀子干的时候了~
基本的思路就是,打掉至少一个中间环节,让js和服务器贴的越近越好。
第一个决定:把daemon干掉。这个很好理解,sqlite,provider,增量更新,太累了。
第二个最重要的决定:在android上搭一个web server来host这个app。这个花了巨多的时间调研各种技术,nano-httpd,iJetty,android build-in http server,最后锁定在restlet上。1. 它有客服,2. 跨平台, 3. 文档还算ok。
第三个决定:设计一套API,让js可以指挥web server把一部分内容离线下来。这部分可以写血泪史了…
最后一个决定:compile一个自己的chrome来支持HTML5。

离线API的设计,主要源自如下需求:孩子们会不定期的收到新的课程,这课程体现为一张张卡片,每次新出现卡片,孩子们就需要点一下下载按钮,然后就是等啊等啊(你知道在一个贫瘠的网络环境中,httpclient有多辛苦么!),只要下载完成就可以打开卡片离线使用啦。
这里就有个离线过程的设计:需要有进度,需要找个劳力来干下载这活儿,下载的内容可能挺大的,几十兆上百兆。
这API大概有3个版本的设计。前两个已经记不清了,包括创造了一种Method:离线GET,一种离线下载清单API等等。有兴趣的可以看那UML。
xServer UML
Turtle。最后呢,在国庆(是的,delay了一个月的时候),终于在无限的纠结和惆怅中想出了目前的方案:把那些要下载的东西都打包做成app,跟提高班本身一样,类似数据包的形式。把下载行为变为web server与服务器之间的同步app行为。所有文件都在android的web server上静态serve在不同url下。

那,web server的代码也变得异常简单了,只要把某个folder host到url就好啦。下载的行为也变成了pad上得server与服务器的server同步他们的app列表的工作(当然,app会被打包传输,android的webserver收到以后再解压)。
为了描述每个app的内容,还设计了一种描述文件manifest.json(后来发现跟大大们的方案完全重叠=.=)。
啊,还有个问题,提高班怎么知道有哪些课程已经完成了?通过一个类似/apps?query的API,可以通过各种不同的域query当前有哪些app,query可以对manifest.json中任何域所过滤,所以web server基本不需要改变也可以实现很多种功能啦。比如前面说的,到底有哪些app装上了呢?/apps?package_name=org.sunshinelibrary.exercise 就好啦。
对啦,这架构名字叫Turtle~
后来发现,这种设计和chrome的packaged application很相似,只是我们没有browser,就只能用chrome+webserver这种方案了。
呃,为啥不用html5 offline?哎,那玩意儿,谁用谁知道…
好啦,花了快半年的重构告一段落,基本形成了turtle+webapp的架构。可跑可用~
更大的重构
书屋原来的后端结构是:aliyun上有个cloud服务器,每个当地学校有个局域网内的local服务器。之间通过各种方法进行同步。
学校多了人就懒了,不想再每个学校都部个服务器啦~理想中我们当然是想统一的aliyun服务器来管理所有的平板,所有的在线学习学生。但那些农村学校整个学校的对外带宽也就几兆,怎么能让他们直接从aliyun下载几百兆的东西呢。
答案就是localcache服务器,把localserver改造成一个只会缓存数据的文件服务器,这样基本就没有维护成本啦,挂了其实也可以从外网下=.=
差不多就这些啦,胡乱的总结了下去年的成果,希望今年能做出更牛逼的东西来!
00