工欲善其事,必先利其器。器可以来自他人,也可以自造。我进实验室的第一个项目便是开发一款行业软件,相比于真正的商业软件,它的系统本身真的很简单。但真是应了那句话,“大学不适合做软件”,整个系统交互复杂,设计冗余,维护起来很困难。在项目结题之后,整个系统便存在硬盘里再也没有人问津。虽然我只开发了其中一个模块,但依旧心痛。
痛定思痛,我希望能有一个成熟简单的桌面框架,解决多数桌面开发遇到的问题:界面显示,数据库,插件式架构,调试输出,网络连接等。同时尽可能减少多个开发者之间的耦合度,为此我了解了SharpDevelop等开源软件,但它的设计对我而言依旧太复杂了。更强调的是代码复用,为一个项目开发的模块,为何不能为另外一个项目服务,同时尽可能减小集成的工作量?于是,从研一上学期开始,我便投入了第一个插件式桌面框架类库的开发: XFrmWork 。
如今,它作为基础类库为三个项目软件提供服务,分别是XMOVE,实验室的数据挖掘软件和LTE软基站仿真演示程序。
下面是以XFrmWork为基础实现的软件之一——XMOVE Studio:
下面,本文集将简要介绍其功能和实现。
XFrmWork基于WPF界面技术和.NET Framework 4.0。 插件式结构设计。主框架包含五个类库,其名称和功能如下图所示:
绝大多数的UI控件采用了MVVM结构,利用数据绑定实现界面与逻辑分离。所有使用外部开源控件的都对其做了接口抽象,因此可以在任何时候使用其他同功能控件,上层代码不需做更改。
同时,框架正在增加其他类库,其中包括专门实现多媒体功能的XFrmWork.MultiMedia库,由于其并未开发完成,因此此处没有介绍。
为了尽可能的减少组件集成的工作量,系统采用了类似插件树的设计方案。所有的功能都通过可组装的插件接入系统。使用非常方便,只需在对应的类上添加attribute标识。
插件的结构类似于键值对:键(Key)是插件要求实现的接口,值是对应的插件名称字典。管理器可以随时插入,删除(有安全隐患)插件字典中的数据。至于插件系统的具体实现,可参考我的系列博文。
以下是插件系统搜索相关目录下的插件后形成的插件列表:
您可以详细了解到当前系统所有的插件字典的键(上图的“插件接口列表”)和 值,同时给出插件的加载策略和详细信息。
在科研计算领域,通常面临的问题是复杂多样的,因此很难通过图形界面完成配置和操作。但我借鉴了Labview的理念,任何复杂算法总可以分解为不同的模块的组装。因此,我们只需设计不同的算法模块,并定义它们的接口。用户可以根据问题的不同,对模块实现组装和配置,解决实际中的复杂问题。
模块可以理解是拥有输入输出接口的“盒子”,一个盒子可能包含多个输入或多个输出。只有输入全部满足,才能执行,但可以不输出给其他盒子。多个盒子可以以复杂的形式组装为算法网络,实现自动化处理。同时,不同的算法之间可能存在耦合和分层。算法管理系统将对模块实现分层和分组。不同组之间模块无交互,因此可以并行执行。同组算法由第一层依次执行到下层,类似流水线。我在这篇博文中,详细介绍了它的实现:
如上图,数据统计输出模块和时间序列分析是分在一组,但不同层的模块,处理时先执行数据统计输出,并将其结果传输到时间序列分析。 另外一组, 计算方法A和B都是C的输入,运行时先完成A,B的处理(并行完成),当两个任务都完成时,传递给计算方法C,继续执行。 值得注意的是,不同组之间是并行的,他们的执行互不干扰。
良好的调试可以方便开发者和使用者,通常我们采用VS自带的调试工具,但在软件Release之后,需要有界面输出工具。
调试输出组件我采用了log4.net组件,网上相关资料较多,此处不赘述。以下是实现效果:
值得一提的是,该组件可以按照信息等级的不同(Debug,Info或是Error等)显示不同的颜色,以提示用户。这些数据可以方便的保存为文件,或传输给指定的电子邮箱地址。
数据作为软件系统的核心,作者开发了多项数据相关模块
数据查看器:为方便数据开发,采用数据绑定和反射技术实现数据查看。其界面会随数据类型的不同而动态改变。
from data in 基本数据1 where 性别 is f select data
点击查找,系统就会自动解析LINQ语句,并执行查找功能。
复杂软件一般需要可自定义的布局系统,本框架使用了AvalonDock开源软件的WPF版本,可以随时修改布局,拖放任意组件,支持不同分辨率,甚至显示在不同的显示器上。同时,系统可以保存或加载已经保存的布局。
WPF的动态资源使得原本在winform时代几乎不可能实现的“动态换肤”成为可能。您可以选择软件右上角的主题管理选单,选择不同风格的界面效果。
在数据挖掘子项目中,需要动态显示和分析数据间的联系,因此我设计了专门显示关系数据的可视化控件,具备如下功能:
下图展示了微博用户网络(采用星状布点)
为了方便显示统计数据,我使用了开源图表控件WPFWisifire。同时,采用了接口隔离方式简化了控件实现,使用时仅需要传递一组KeyValuePair序列,即可实现绘图。支持柱状,线状,雷达等类型图表。下图展示了中国登记在案的科研项目每年数量的变化图:
地理图形可以更直观的帮助用户分析数据,因此我使用了开源控件GMap.Net实现地图功能。同样使用接口隔离具体实现,可自动定位,绘制路径,增删修改地标等。
为实现更好的扩展性,作者在程序中大量使用反射,为提速,作者使用了一些技术提升反射性能,从而优化了用户体验。
系统上方的菜单也是根据插件接口自动组装完成的,如下图所示:
作者通过重新封装socket等基础功能,提供了方便上层调用的通信功能。
作者使用了多项技术,使得上层不需要考虑数据存储的序列化细节,只需调用一个函数即可完成。而对于跨进程调用时,系统使用了.NET Remoting等技术。在此不一一赘述。
XFrmWork是我在.NET开发中实现的第一个完整类库集。坦白的说,博客园里的诸位大神,早已使用或已经开发了比XFrmWork强得多的架构系统。但是它却是适合我自身的系统。在不同项目的需求驱动下,我的团队推动了它的不断升级。这也让我学到了更多的知识。我会为其插件搜索速度绞尽脑汁,也会吸收各类开源软件的架构精华。其实,有这样的平台,对我来说已经足够。如果它能被我带入到工作中,那一定是最幸福的事情。
开放全部的源代码没有价值,我会在“插件系统加载”和“自组装模块"的基础上继续与大家分享它的开发经验。欢迎大家关注。