可伸缩性是一种对软件系统处理能力的设计指标,高可伸缩性代表一种弹性,在系统扩展过程中,能够保证旺盛的生命力,通过很少的改动,就能实现整个系统处理能力的增长。
在系统设计的时候,充分地考虑系统的可伸缩性,一方面能够极大地减少日后的维护开销,并帮助决策者对于投资所能获得的回报进行更加精准的估计;另一方面,高可伸缩性的系统往往会具有更好的容灾能力,从而提供更好的用户体验。
WEB交互式系统的可伸缩性主要体现在两个方面:
WEB交互式系统的主要应用包括:
本系列文章主要分为两个主要部分对可伸缩性进行阐述,分别是平台的可伸缩性和模块的可伸缩性。本文是系列文章的第一篇,讨论平台的可伸缩性。
平台的可伸缩性
WEB交互式系统对平台的可伸缩性主要表现为:
我们先介绍一下WEB交互式系统的目标平台的情况。
平台分类
根据系统所在容器的差异,我们将平台分为浏览器平台和混合应用平台两大类。各分类的详细说明见下文所述。
浏览器平台
按引擎划分
浏览器平台,按照主流引擎可以划分为以下几类:
混合应用平台
根据混合应用的宿主平台的差异,我们将混合应用的目标平台分为以下几类:
宿主 |
说明 |
Android | Android系统的混合应用,浏览器引擎会自动适配至Webkit |
iOS | iOS系统的混合应用,浏览器引擎会自动适配至Webkit |
WinPhone | Windows Phone系统的混合应用,浏览器引擎会自动适配至Trident |
PC | 桌面应用,采用CEF做为容器,浏览器引擎会自动适配至Webkit |
平台适配
AOP(Aspect-Oriented Programming):面向切面的编程范式,其核心思想是将横切关注点从主关注点中分离出来,因此特定领域的问题代码可以从标准业务逻辑中分离出来,从而使得主业务逻辑和领域性业务逻辑之间不会存在任何耦合性。
这里我们可以借鉴AOP思想来实现平台的适配策略,结合不同的平台实现逻辑,我们可以认为对于使用规范、标准来实现业务逻辑的部分为我们的主关注点,而不同平台可以做为若干的切面关注点进行封装,各平台只需关注自己平台下对标准的修正逻辑即可,因此可以通过增加、删除平台修正的切面逻辑来实现对不同平台的适配。
实现时我们首先提取标准业务逻辑,然后各平台根据实际情况实现对业务逻辑的修正:
根据此思路我们对比以下两段代码:
代码一:目前常用的平台适配方式
function doSomething(){ if(isTrident){ // TODO trident implement }else if(isWebkit){ // TODO webkit implement }else if(isGecko){ // TODO gecko implement }else if(isPresto){ // TODO presto implement }else{ // TODO w3c implement } } // 上层应用使用 doSomething(1,2,3);
此方式对所有平台的修正逻辑均在主逻辑中实现,存在以下弊端:
代码二:借鉴AOP思想的平台适配方式
function doSomething(){ // TODO w3c/es implement } // 上层应用使用 doSomething(1,2,3);
针对Trident平台适配的逻辑,比如 trident.js中
// trident implement doSomething = doSomething._$aop( function(_event){ // TODO trident implement }, function(_event){ // TODO trident implement } );
对比代码一,我们可以发现借鉴AOP思想的接口适配方式分离了标准业务逻辑和平台特有业务逻辑,是否增加平台特有业务逻辑并不会影响主业务逻辑的执行,而对于平台修正逻辑的切入则可以直接通过配置的方式灵活的进行增删,因此我们可以从中得到以下好处:
实现举例
NEJ框架借鉴AOP思想提供了配置式的平台适配系统,对于这部分的详细信息可参阅NEJ的《依赖管理系统》和《平台适配系统》了解更为详细的信息,以下仅举例说明NEJ中适配的使用方式。
一个典型的适配控件结构如下图所示:
这里的widget.js是控件业务逻辑实现文件,在此控件的实现中会依赖到存在平台差异的API,其依赖代码如下所示
NEJ.define([ 'util/event', '{platform}api.js' ],function(t,h,p){ // TODO });
这里对 {platform}api.js 的处理方式如下图所示,这里的./相对于当前的代码文件即widget.js文件所在的目录
这里的api.js文件为需平他适配API的标准实现逻辑,而api.patch.js文件则利用NEJ.patch接口对各平台做按需适配逻辑,同时打包时也根据NEJ.patch接口中对平台的条件识别做按需输出,由于api.patch.js文件最终会按需输出,因此在此文件中除了使用NEJ.patch做平台适配逻辑外,不允许包含其它业务逻辑。
// 此文件只能定义NEJ.patch不可执行其他业务逻辑 // 打包输出时仅根据平台配置输出所需处理逻辑 // 实际情况看需求,可将平台相关部分逻辑独立到单独的模块中 NEJ.define([ './hack.js' ],function(h){ // 针对trident平台的处理逻辑 NEJ.patch('TR',function(){ // TODO }); // 针对gecko平台的处理逻辑 NEJ.patch('GR',[ './hack.firefox.js' ],function(fh){ // TODO }); // 针对IE6平台的处理逻辑 NEJ.patch('TR==2.0',['./hack.ie6.js']); // 针对IE7-IE9的处理逻辑 NEJ.patch('3.0<=TR<=5.0',function(){ // TODO }); // 这里必须同hack.js文件的返回值一致 return h; });
最后我们只需要配置产品的目标平台即可输出平台对应的适配,而不会存在其他平台的额外影响:
<script src="/path/to/nej/define.js?p=wkgktd"></script> <script src="/path/to/nej/define.js?p=cef"></script>
平台变更
通过以上实现举例我们可以看到当平台发生变更时我们可以快速进行扩展或缩减
平台扩展
当有新平台需要作为系统目标平台时,我们只需要做以下工作:
系统对平台配置部分增加新添的识别符,如
原平台适配:<script src="http://www.wfuyu.com/uploadfile/cj/20140920//path/to/nej/define.js?p=wkgktd"></script>
新增平台适配:<script src="http://www.wfuyu.com/uploadfile/cj/20140920//path/to/nej/define.js?p=wkgktdnxw"></script>
即可完成对平台的扩展,而不会影响到原有的业务逻辑。
平台缩减
当系统适配的目标平台由于某种原因退出历史舞台时,系统也需要将该平台的冗余代码从系统中剔除,我们只需要做以下工作:
系统对平台配置部分删除要剔除的平台标识,如:
原平台适配:<script src="http://www.wfuyu.com/uploadfile/cj/20140920//path/to/nej/define.js?p=wkgktd"></script>
缩减后平台适配:<script src="http://www.wfuyu.com/uploadfile/cj/20140920//path/to/nej/define.js?p=wk"></script>
即可完成对平台的缩减,而无需修改任何业务逻辑。
以上即是有关平台可扩展性的介绍。下一篇将阐述模块的可扩展性,敬请期待!
本作品采用知识共享署名 4.0 国际许可协议进行许可。
上一篇 深入浅出交换类排序算法
下一篇 数字证书及CA的扫盲介绍