11年的文章,当时在做系统集成,实际上当时的思路到现在我还在琢磨,只不过后来就不做系统集成了,也一直没机会深入下去解决这个问题。
==== 正文 ====
一直以来做的项目中有很大一部分工作量都是有关集成设备的工作。为了方便扩展以支持更多厂家的设备,但在这个过程中遇到了非常头疼的问题,在这里我把问题描述一下,欢迎大家来探讨。
问题描述:
所谓设备集成,多数情况下可以简化为SDK的集成(这个比较方便,有时候我们宁愿直接集成协议,但是厂家有厂家的考虑)。针对这种情况,我们的系统采用了比较典型的插件式设计思路,把功能大体一致的设备封装为统一接口的动态共享库,运行时根据数据库配置动态加载调用,同时宿主软件本身也提供了一套接口以便下层动态库来回调获得必要的信息。
我把问题描述到这个程度,估计很多人已经在窃笑了——是的,就是动态库版本问题……
应该说在多数情况下这种插件机制可以很好的应付设备集成需求,并且可以很容易的跨平台实现(这很重要),但是有一种情况,就是在一个进程中使用同一个共享库,却妄图加载两个版本。这时候情况就变得非常混乱。看图:(工具简陋,箭头我没画,大概意思应该都明白)
图中的问题很明了:现在的嵌入式设备厂家众多,但是跟手机行业一样,有很多厂家生产的是“山寨机”,也就是基于嵌入式解决方案做二次开发做出来的产品(比如国内的周立功和华为海思的方案)。针对一些复杂的功能比如解码器,解决方案提供商会以动态库的形式提供上位机开发包,也就是图中的厂家底层库那个模块,然后设备厂家封装SDK要调用这些动态库。如果要在一个软件内集成两个厂家的设备A和B,俩厂家用的是一个品牌的硬件解决方案,但是版本不一样,问题就出现了。这时候底层库的文件名是一样的,但是版本不一样,一个进程做不到同时加载两个版本的底层库。如果解决方案提供商做不到完全的版本兼容,一定会有一种设备用不了。
针对这个问题我曾经尝试用两个方法解决过:
方法一:
很猥琐的方法。当时客户的平台为win32,设备都是遗留设备,厂家的人根本找不到,为了快速解决问题我直接用UltraEdit打开一种设备的SDK文件把里面调用文件名字符串改了一个名字,然后把底层库也改了一个名字,问题就解决了……后来我一直不太放心,怕出问题,还好一直没出问题。后来问同事他们说也这么干过……囧。
方法二:
在设计新版软件的时候,一方面行业的规范性增强了,地区性行业标准相继出现,另一方面新系统主打整体解决方案,不针对老项目改造,这个问题不被重视。但是我预感到基于商业的考量肯定还会出现这种问题。我实验了一种方法,就是把设备这一块封装到另一个进程中,和主程序做数据交互,或者另一个进程也实现一部分界面,直接嵌入到主程序界面中(就像是Smplayer)。我在windows上做了一个原型程序,功能没有问题,但是最终新版软件没有考虑这个方案。原因主要是一方面这个机制和主程序的机制差别很大,封装到一起很不容易,另一方面要考虑跨平台,在linux平台上这样做性能不好,也没有办法优化,甚至某些功能实现不了(经过研究这些确实是有结论的)。
目前这个问题我还没有太好的解决方案,只能就事论事针对项目的特点逐个解决。
应该说造成这个问题的原因和技术是没有关系的,主要还是因为规范不到位,各厂家各行其是,盲目追求”大集成“,对可用性的关注不足。这种问题本事不足为道,但是往往是这种“非智力问题”最困扰人。在这里说这个问题可能不合时宜,就算是带来一点不一样的空气吧。