最近我们Team和一个运营商合作在紧张忙碌的构建基于我们OSGi.NET框架的软件超市平台。该平台体系结构如图1所示,它由应用商店平台、应用运行时和开发者工具包构成,为软件提供商、运营商和消费者构建了一个统一的平台。在平台设计过程中,我根据客户需求制定了一个技术方案,但是由于中间需求产生变化,导致我们需要临时调整并构建新的技术方案。我觉得这两个技术方案的选型都非常的有意思,这两方案都是先从用户角度出发,对开发者和消费者都具有很强的易用性,因此,就写下来和大家分享一下。
图1 AppStore体系结构图
在图1中,App Runtime是应用运行时,即类似提供商开发的应用的运行容器,Dev SDK则是针对App Runtime特定应用的开发者工具包。
第一个方案:面向企业用户构建单机应用
该方案意味着App Runtime是传统WinForm应用的运行容器,在该容器运行的所有应用都是WinForm应用(事实上,这并不是客户的真正需求,客户真正需求是B/S模式的App Runtime)。这也就意味着Dev SDK也是针对WinForm运行容器的App Runtime设计的。
我们设计的App Runtime运行界面大致如下:
图2 App Runtime运行效果图
这个设计Idea如下:
(1)App Runtime由OSGi.NET内核、WinForm界面插件、Sqlite Data Access Service插件、Rbac Service插件组成;
(2)OSGi.NET作为App Runtime底层框架,提供了模块化、插件化、动态性、面向服务、模块扩展等功能;
(3)WinForm界面插件定义统一的界面框架,向所有的应用提供了导航栏与内容区域扩展点,允许基于Dev SDK开发的应用动态的向左边导航区域添加菜单,同时允许将用户定义的业务逻辑界面显示到右边的内容区域;
(4)Sqlite Data Access Service插件是单机应用数据访问服务,它封装了对Sqlite的数据访问;
(5)Rbac Service插件提供了统一的用户权限管理,用户自定义的插件只需要在插件添加扩展,这个扩展的格式为<Permission Id=”<PID>” DisplayName=”<DName>”>的集合,然后调用其提供的PermissionService.CheckById方法执行权限检测。这种方法提供了对Rbac任意级别的扩展。此外,它还提供了几个基础管理界面包括用户与权限的管理;
(6)Dev SDK是针对开发者提供的应用开发工具包,它由应用模板、VS插件、OSGi.NET内核、远程管理控制台、文档、Video和示例组成。默认的应用模板是一个VS2005SP1/VS2008/VS2010项目模板,基于模板创建的项目由Sqlite空数据库、包含获取DataAccessService和PermissionService的激活器、自带对权限和界面模块扩展的模块配置文件组成,如图3所示。这个Dev SDK创建的默认项目一旦运行起来便会自动向WinForm界面框架注入导航条,并可以把Form1和UserControl1控件显示在内容区域,如图4所示。
图3 使用Dev SDK新建一个应用的项目模板结构图
图4 默认项目运行的结果
这种方案的优点有:(1)对于软件提供商,开发应用非常简单,和传统开发方法几乎没有什么差别,而且还赠送了还不错的界面、通用数据访问、通用权限管理模块;(2)对于软件消费者,可以随时安装、添加和卸载应用,整体风格非常一致。整个方案的设计,我从三个用户的角色出发,分别设计了他们的使用场景,在我认为一切都很完美的情况下写了一个功能规范。
本来,我已经把这个项目的功能规范文档(如图5)已经提交给我的合作伙伴,哪怕他看一眼规范,他也能看出来WinForm这种快要过时的技术是不符合要求(我原来曾经质疑过这一点,但由于客户的态度非常肯定,我就以为我掌握了客户的需求)的。但是,合作伙伴没有看一下这个文档,或许是他们对我们过于相信了。这次的错误可能在于我们双方都过于相信已经理解了双方的想法,而实际上,并不是真的如此完美。直到原型已经做出来给他们演示了,他们才提出了一个很严重的问题。他们说这个设计无法满足要求,至少是C/S或者B/S应用,不能是单机版的(单机版的也没有白设计,我们还有其它应用)。于是,接下来我和团队便开始进行下一轮方案设计和选择。
图5 AppStore功能规范关于App Runtime的设计
第二个方案:面向企业用户构建C/S应用还是B/S应用
对于C/S应用,有一个非常大的好处就是实时性和交互性非常强。不过,如果使用C/S模式的话,消费者将碰到2个非常棘手的问题:(1)如何安装Server是第一个问题,者需要把Server先安装在服务器,然后安装客户端,每一个客户端都需要配置数据库连接,这种方式对消费者来讲过于复杂;(2)如果要添加一个新的应用或者删除一个应用,则意味着所有客户端都需要进行变更,这更致命了。如果非得使用C/S模式,我们必须解决这两个问题,可以凑合来解决问题的方法只有一个即智能客户端技术。每个用户通过Server来安装且订阅Server对应用的更新从而实时更新,这种方式从技术实现上来讲没有问题,但使问题变得非常复杂且易用性不好。因此,我们只能使用B/S模式来实现。
对于B/S模式,它又重新带来了2个问题,即开发者如何开发、消费者如何使用。如果这两个问题的答案非常的费劲,意味着这个方案将无法满足用户的需求。对于一个软件产品而言,易用性毕竟是第一位!
首先,对于消费者如何使用的问题,稍微简单一些:(1)前提:用户安装了IIS;(2)下载的App Runtime + Apps的安装包自动将应用发布到IIS上,新增的应用能够自动拷贝到Plugins目录且会引起IIS重启。
对于开发者,我们引入了一个新的讨论。即基于单机版设计的开发模式无法满足B/S模式。这里面有一个致命问题,Sqlite本地数据库是不支持多线程的,而B/S应用又是多线程的,这意味着如果使用Sqlite的话,Data Access必须类似WinForm一样封装了一个唯一的线程来访问数据库,并基于线程同步技术使不同应用浏览器串行的访问数据库,且不能支持Linq和ADO.NET Entity Framework。这对于开发者限制太死了。我们不希望如此。
参考了所有的可以商用的文件数据库,另一个可选的方案是SQL CE。只不错,SQL CE版本太多,无法统一,因此,我们在单机版的App Runtime便放弃了。不过,它具有Sqlite没有的好处,便是提供并发性支持。我和Team对这个问题,从易用性角度出发,进行了一个讨论,得出一个折中的方案为:(1)将单机版的模式移植到B/S模式;(2)第一个是现阶段:限制开发者使用VS2008 SP1 + SQL CE3.5 SP1开发;(3)第二阶段:OSGi.NET包装了多个版本的SQL CE运行时,这样用户可以使用任意VS版本和CE版本来开发应用。
这样,我们总算提出一个可行的解决方案。
声明:WinFormShellPlugin的设计用了一些开源的组件,包括John Underhill (Steppenwolfe) 的vTab、Muhammed ŞAHİN的NavigationPanel、Starts_2000的SkinForm,当然,还包括Sqlite的做主了,在此,感谢他们的分享!!最近特忙,我的个性签名已经变成“写代码和看电影一样,已经是一种放松的方式了”,能编写代码真是一件简单、轻松、单纯的事情了~~,好久没有更新Blog了。