王潘章
【摘要】目的:目前JavaScript在前端架构中得到越来越多的应用,该文主要论述了同形JavaScript架构在医院信息系统设计中的优点。方法:以医院OA中风险防控子系统为例,对比了其他基于MVC的设计模式。结果:与传统架构相比,同形JavaScript架构更加解耦,更加适合大型富前端应用的核心框架。结论:同形JavaScript架构应该是未来Web前端设计架构的趋势,在医院信息系统的应用设计将带来更好的设计质量与开发效率的提高。
【关键词】同形;JavaScript;架构;风险防控
【中图分类号】R722.12 【文献标识码】B【文章编号】1004-4949(2015)03-0094-01
1 引言
随着Web技术的深入应用,医院信息系统也更多地采用B/S[1]架构的方式来实现。近年来,Web前端技术得到了高速发展,更多的技术与框架完全建立在JavaScript/Ajax[2]之上,例如:Backbone,AngularJS等。而随着Node.js技术的发展,JavaScript在服务器端也得到了很好的应用。这样带来的好处是,无论在客户端还是服务器端,都可以使用一种语言来实现。但是,由于客户端与服务器端是完全不同的运行环境,无法实现真正意义上的应用解耦。
本文以本医院风险防控平台的建设为例,阐述了同形JavaScript技术在信息系统中是如何实现前后端可复用的架构设计。
2 风险防控平台的功能模块
卫生部于2012年8月出台了《关于加强公立医院廉洁风险防控的指导意见,文件要求医院通过“制度+科技”的形式[3],建立医院廉洁风险防控平台[4],实现风险预警、风险分析、风险处置等功能,对权力运行廉洁风险实施动态防控。风险防控平台作为一个新的信息系统,使用了全新的JavaScript框架,并实现了与现有OA系统的对接。主要包括以下几个功能模块:
2.1 职务权力防控
通过定义权力目录、权力运行流程,协助医院做好清权确权工作。系统采用权力路径模式,利用外部监督、纪检监督实现对医院职务权力行使的全程防控,把决策、基建、采购、人事、财务等职务权力纳入重点监控范围,通过设置“内控点”实施过程动态监控,确保医院各项权利的正确行使,及时发现廉洁风险,及时警示或纠正,避免问题扩大。核心内容是“三重一大”事项民主决策制度落实情况,主要是:重大事项决策权、干部人事聘任权、项目设备采购权、先进推荐评选权、科研申报管理权和财务资金运行权。
2.2 职业权力防控
从HIS等系统中抽取数据,通过数据转换、数据装载技术,创建数据仓库,实现对医护人员执业行为的监管和分析:
临床用药:采购药品使用监控、基本药物使用监控、抗菌药、超限处方;
临床路径:临床路径入径、出径及变异情况;
大型检查:大型检查阳性率;
耗材试剂:强化对来源、采购、资质、出入库、使用的监控;
医疗收费:药品、耗材加成率,超标准和超范围收费,退费、欠费;
2.3 患者满意度管理
通过医院终端采集、患者随访等多种渠道,实现患者满意度数据的大样本、背对背采集,依据多种数据分析模型,实现医院的满意度情况分析,及时掌握公众对医疗机构的服务满意和不满意的地方,以便相關领导及医护人员了解情况,及时发现问题,提升管理服务水平。
2.4 供应商诚信度管理
建立供应商数据库,通过资质准入、诚信教育、诚信档案、诚信评估管理手段,全面采集供应商交易信息、用户满意度、表扬投诉、不良行为、禁止行为数据,建立健全供应商诚信档案,加强供应商风险预警、分析、处置管理,结合职务权力中采购权流程管理和职业权力中供应商产品异动信息,遏制供应商和医院在采购过程中的不规范行为。
3 同形JavaScript项目架构设计
3.1 Gulp 构建工具
为了系统的开发过程更加专注于编码与实现逻辑,大大提高前端开发人员的工作效率,我们采用了基于Gulp来实现自动化构建管理。Gulp.js 是一种基于流的,代码优于配置的新一代构建工具,提供了高质量的构建插件,使用方便且易于学习。主要包括以下几个命令:
gulp.task(name, fn) 运行单个任务。
gulp.run(tasks...) 尽可能多的并行运行多个任务。
gulp.watch(glob, fn) 当glob内容发生改变时,执行fn
gulp.src(glob) 返回一个可读的流
gulp.dest(glob) 返回一个可写的流
Gulp 对基于JavaScript的项目构建提供了自动化的管理方案,大大节省了开发人员每天花在项目构建上的工作量,从而提供了开发效率。
3.2 CommonJS
设计中遵循了CommonJS;CommonJS是服务器端模块的规范,Node.js采用了这个规范,而且Browserify支持CommonJS。根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性。CommonJS采用require()方法加载模块;采用exports.report输出模块变量。以下为使用CommonJS的代码样例:
var risk = require('./risk.js');
exports.report = function () {
console.log("评测报告");}
CommonJS让我们可以更好地按模块化的方式组织代码,并且通过Browserify和Node.js使客户端和服务器端都更好地支持这一规范,增加了代码的易读性和可维护性。
3.3 React.js
React.js是一个来自Facebook的开源JS库,用来创建“独立的视图组件”。其根本思想与AngularJS的指令或者Polymer的web组件很相似。一个React组件本质上来说就是一个拥有自己作用域的DOM元素。它不能够直接和你的应用中的其他部分进行交互,无论是JavaScript代码还是DOM。众所周知JavaScript的性能取决于操作DOM的性能,针对这点,React.js 实现了虚拟DOM以及DOM diff算法,使得对DOM的操作性能得到大幅地提高,因而其性能是其他框架(AngularJS, JQuery)的数十倍以上。
React.js中另外的一个独特部分是采用了JSX,它能够将同代码一起编写的HTML转化成可解析的JavaScript代码。也有人称为:“JavaScript XML”,简称为JSX。下面就是一个关于React组件中使用JSX的一个例子,下面的代码将会渲染成一个链接。
var component = React.createClass({
render: function() {
returnMore}
});
它将会被转化成为下面的代码:
var component = React.createClass({
render: function() {
return React.DOM.a( {href:"/more"}, "More") }
});
3.4 Express.js
Express.js 是一个简洁流行的 node.js[5] Web应用框架。我们采用Express.js实现了Web请求路由的功能,并且利用React.js技术在服务器端对Web页面(DOM)进行了预先实现,与单页面JavaScript应用相对比,就大大提高了初始页面加载的速度。
app.get('/page/:page/', function(req, res, next) {
var page = req.params.page || '0';
if (!validator.isInt(page)) {
return next();
}
makeCall(req, res, next, {
action:ContentActions.list,
params:{
page: page
}
});
});
Express.js支持多种模板引擎,常见的有:Jade、Mustache、Swig等。让Express.js支持React.JS的视图,只需要以下代码来实现:
function(res, markup, state) {
state = state || res.locals.state;
var html = React.renderToStaticMarkup(HtmlComponent({
state: state,
markup: markup,
context: res.locals.context.getComponentContext()
}));
res.set({
'content-type': 'text/html; charset=utf-8'
});
res.write('<!doctype>' + html);
res.end();
}
3.5 Browserify
Browserify 可以让你使用类似于 node 的 require() 的方式来组织浏览器端的 Javascript 代码,通过预编译让前端 Javascript 可以直接使用 Node NPM 安装的一些库。
Browserify具有一系列灵活的转换工具,可以在调用require()之前对各种格式的源代码进行相应的转换,最终都转换成JavaScript的形式。例如:
转换coffee Script文件:
% browserify -t coffeeify main.coffee > bundle.js
本文中用来转换React JSX文件:
% browserify -t reactify main.jsx > bundle.js
同时,Gulp实现了JSX文件转换的自动化。这样,我们可以利用React.js来实现丰富的页面逻辑,并且按照业务逻辑对文件进行模块化管理。Browserify和Gulp会自动将其转换成前端JavaScript,从而实现了一处构建,多处运行的同形模式。大大提高了代码可复用性与解耦性,因为我们不在关注于是客户端还是服务器端,而是注意力转移到了真正的业务逻辑实现上来,而这一切还都是同种语言(JavaScript)来实现的。
3.6 Flux
Flux为React.js提供了一组类似于MVC的设计模式。Flux包含三个基本概念:转发器、存储和组件。它的流程是: 轉发(Dispatcher) -> 存储(Store)-> 组件(View). 如果一个组件想要改变它的状态,它需要发送一个请求到转发器中。在MVC设计模式中,你经常会用到 MODEL <-> CONTROLLER <-> VIEW这个流程, 状态可以双向改变。
Store包含了应用的所有数据,Dispatcher替换了原来的Controller,当Action触发时,决定了Store如何更新。当Store变化后,View同时被更新,还可以生成一个由Dispatcher处理的Action。这确保了数据在系统组件间单向流动。当系统有多个Store和View时,仍可视为只有一个Store和一个View,因为数据只朝一个方向流动,并且不同的Store和View之间不会直接影响彼此。Flux与MVC[6]相比较,更加适合复杂大规模应用,因为MVC的模型与视图间的双向数据流动会使程序非常难以理解和调试。
3.7 REST API
风险防控子系统作为医院OA系统的一个子系统,其数据的存储和工作流的集成要求和OA的其他子系统达到高度的集成。这里的集成通过流行的Web Service的方式来实现,具体地说,Web 服务之间通过JSON+Ajax的方式来实现。这样的集成方式,也很好了解决了业务层和表现层的分离。本文论述的重点不是如何集成,只是通过公认的集成方式快速高效地实现了OA子系统。达到了各个子系统之间的松耦合,又实现了数据和流程的集中存储和管理。
4 结论
通过医院OA系统风险防控子系统中采用同形JavaScript的架构方式,阐述了该架构方式的优点和特点。通过对比,可以看出同形JavaScript更好地解决了前端开发过程中的耦合性问题以及优雅的设计思路给代码质量和提高开发效率带来的益处。同形JavaScript架构是未来Web开发的趋势,该文中涉及到的实践尚处于初步阶段,有待于进一步完善成适合医院Web前端开发的一个开源框架。
参考文献
[1] 刘岚. 我院药品不良反应监测网络系统的建设与应用[J]. 中国执业药师, 2013, 12(14): 44-47
[2] 杨艳丽, 王华民, 曾鹏云, 等. 基于B/S结构医院药库信息系统的实现[J].价值工程, 2012, 31(16): 179-180
[3] 俞海燕, 陈蓓, 张琛, 等. 基于医院OA系统权力风险“制度加科技"防控研究术[J].中国医院管理, 2013, 33(6): 16-17.
[4] 颜洁环, 赵婉文, 吕金花, 等. 医院廉洁风险防控机制的探索与实践[J].现代医院, 2014, 14(7): 122-124
[5] 钟强. Node.JS平台下Web前端架构的研究[J]. 无线互联科技, 2013, 12(96): 124/196
[6] 謝晶晶. 基于HTML5的移动办公应用研究[J].中国数字医学, 2013, 8(12): 90-92