Modular Application Development


桌面应用程序的典型特征

相比十几年前的桌面程序,当今的App最明显的特征是“复合”。以前的桌面App对功能的完整性与多样性并没有太高的要求(这一点你可以对比很多当下的软件,比如即时通讯类:QQ)。 随着互联网行业对传统行业的冲击,人们更愿意接受来自互联网的产品和行为模式,进而无形之中对App的功能需求是越来越多(用户就是希望你最好这个功能有,那个功能也存在)。 拥有最大操作系统用户量的Microsoft Windows OS的换代既是对当下需求的一次变革模范,Microsoft 为了降低Web、Mobile、Desktop三端的应用程序的开发难度与移植难度,顺应 了市场需求,给开发者和用户都带来了一个很好的新的开端。换个角度也可以看出,微软的架构必然对之前的各平台“各自为政”做出了融合,所以也是一个典型的“复合”架构。

抛开技术构架,用户对UI的要求也就颇多了。我相信每个人都至少吐槽过几款App。类似“毫无用户体验可言、界面太丑、操作出错,bug多,没反应, 经常crash... ...”。说实在的,用户 是最难伺候的,但这不能成为身为开发者的我们去回避的借口。如果拿一款连自己都不能说服的App上线让用户使用,结果可想而知。但是要相信,要做好前端工作并非朝夕。随着用户体验被 偷偷挪上头条时,前端这个概念的比重直线上升,已经与后端占有相同的比重,毕竟UI是程序的“面子”,用户不关心你怎么实现的。

综合以上可以看出,当代应用程序正迈向三个标准: “高度的架构复合”、“良好的用户体验”、“完备的功能服务”。对于各位来说,是机遇或是挑战?

开发者面临的挑战

我们都知道软件开发设计的基本原则“低耦合、高内聚、模块化”,如果我们将这三者作为前面所说的应用程序的三个标准的强力后盾,那么你的App不会差! 如果一款App最初没有打算从1M的源代码量做到1G或是10G,那么必然会从架构上作出巨大的牺牲。所以,我建议所有的开发人员:请把你正在开发的每一款App,都视为用户量 已经突破1亿。

巨大的挑战摆在面前,如何利用开发技术或框架来解决好应用程序的三个标准。相信Google会告诉你很多,最好不要让你眼花缭乱。

如何构建良好的应用程序架构

如果想要自己动手创建属于自己的架构(当然,在这之前你最好了解相关的技术框架和业界的标准做法),最好的方式莫过于时刻的反问自己,比如: 1. 每个App都需要的组件是什么? 2. 每个App是不是至少都包含1个或以上的Module? 3. 每个Module之间的交互,这么做? 4. Module UI与Logic有没有真正分离,如果我换一套UI? 5. 当用户量是1000时,100000时,10000..时,在哪些地方有瓶颈? ... ...

Microsoft Prism for WPF框架源码分析

当然,我也是处于好奇和自己的兴趣原因,尽管自己还没有做的足够的好,但我还是得继续坚持先看懂别人的,再写点自己的这样一个原则,相信水滴石穿,日积月累。 所以,我就以Microsoft.Prism框架源码为例,做一个梳理。

Microsoft.Practices.Prism.Bootstrapper

Bootstrapper是一个类似引导器的组件,负责统筹管理整个App启动阶段所需要的一切资源和执行动作。例如与本文直接相关的,它可以用来管理App各个Module的加载管理。可以看先下Bootstrapper的定义:

可以看出,Bootstrapper是一个抽象类无法直接使用(Prism提供了MefBootstrapper用于实现该抽象类,其用于管理服务(Service)的容器是CompositionContainer),且可以自由Override其虚方法以多态的形式进行高级定制。 可以看下Run方法的源码,这些过程的执行顺序就一目了然了:

在这里特别说明下与本文相关的InitializeModules方法: 其中AggregateCatalog是用来管理需要App自动发现外部组件的引用目录,简单来说CompositionContainer将会在改对象下所有的目录中去加载可用组件(插件思想).比如上边的MainForm类型所在的程序集,还有App允许目录下的“Modules”文件夹就是外部组件目录。 同时在这里,可以通过订阅ModuleManager的模块加载事件,来进行精确控制,比如程序启动的进度和当前步骤等等,可发散的空间很大。 注:在以后的框架设计中,可以借鉴这种统筹管理的方式,提供默认的执行方案,并提供使用方的个性化定制。

CompositionContainer

Microsoft.Practices.Prism.Modularity

负责模块的定义、模块加载时初始化的职责。若采用MEF Container作为容器,则需要在对应module class中用 [ModuleExport] Attribute标示,还可以通过枚举参数InitializationMode指定加载策略,且该Module Class必须实现IModule接口,IModule接口只拥有一个初始化的方法, App会在初始化各个Module完成之前调用该方法: PIC : IModule的定义 Module之间的加载依赖可以用[ModuleDependency]来指定所要依赖的Module,可以多次指定。 App是如何发现这些Module的呢? App是在Bootstrapper启动过程中,从AggregateCatalog指定的目录下加载所有带有[ModuleExport]并实现了IModule接口的实现类,将其注册为Module,并根据InitializationMode决定是否立即加载,立即加载就意味着会调用对应Module的Initialize方法进行初始化。 那么在Module初始化时,我们需要做些什么呢? 1. 将该Module提供的Service注册到容器中 2. 从容器中获取需要的Service使用 3. 订阅或发布该Module需要的事件 可见Module之间的解耦都交给了容器管理,各个Module实际上不知道从容器中取得的Service是来自哪一个Module。 这就好像负载均衡策略一样,终端用户不清楚当前请求命中了哪一台服务器。

Microsoft.Practices.ServiceLocation

ServiceLocation,服务位置坐标,通常我们称之为服务定位器(Service Locator),其内部实现采用了Adapter Pattern,将Container进行了包装,以更加便捷的使用。 其理念是:无论你想要什么样的服务,请告诉我! 当然我们也可以自定义Service Locator,只需要实现IServiceLocator接口,并将其注册到Container中即可。 IServiceLocator定义: 其使用方式也是非常简单: 可以看出,我们用统一的服务定位器来管理服务,至少有2点值得借鉴:1.降低了模块之间的服务引用依赖;2.服务对调用方来说,易用、不透明的。 介于篇幅,这里仅对Prism与Modular Application相关的源码做了简要分析。只是提供了一个引子,更多请Google Prism。

对Desktop App、Mobile App的一些思考

一直以来,开发出一款经典的App是许多程序员闲暇时更多想做的事。桌面应用相对于移动应用在这几年处于颓势,在这之前,我从未想过移动应用会如此之多,就像是雨后春笋,一发不可收拾。仔细一想,移动物联是大势所趋,在今后,还不知道有多少“神奇”的App出现呢!想提醒哪些有想法的同学们,同时也鼓励自己:你总该为这个世界增添点来自于你所创造的东西。

(打赏)

If you want to pay for this
I will list your account name here.
HA HA!