上世纪九十年代,互联网的极速发展让通讯测试设备也得到了极大的发展。那个年代,能够实现某种测量的硬件是竞争的核心,软件的目的仅仅是驱动硬件运行起来,再提供一个简单的界面。所以,最初的产品的软件结构非常简单,类似前面的城铁门禁系统。
- 优点:程序简单明了的实现了用户的需求,一个程序员就可以全部搞定。
- 缺点:完全没有划分模块,底层上层耦合严重。
1. 数据处理
用户要求能将测量结果保存下来,并可以重新打开。数据存储模块和界面被独立出来。
依然保持上面的主逻辑,但是界面部分不仅可以显示实时的数据,也可以从ResultManager中读取数据来显示。
- 优点:数据和界面分离的雏形初步显现
- 缺点:ResultManager只是作为一个工具存在,负责保存和装载历史数据。界面和数据的来源依然耦合的很紧。不同的界面需要的不同数据都是通过硬编码判断的。
2. 窗口管理
随着功能不断复杂,界面窗口越来越多,原来靠一个类来绘制各种界面的方式已经不能承受。于是窗口的概念被引入。每个界面都被视为一个窗口,窗口中的元素为控件。窗口的打开,关闭,隐藏则由窗口管理器负责。
- 优点:界面功能以窗口的单位分离,不再是一个超大的集合。
- 缺点:虽然有了窗口管理器,但是界面依然是直接和底层耦合的,依然是大循环结构。
3. MVC模式
随着规模进一步扩大,最初的大循环结构终于无法满足日益复杂的需求了。标准的MVC模式被引入,经历了一次大的重构。
数据中心作为Model被独立出来,保存着当前最新的数据。View被放在了独立的任务中执行,定期从DataCenter轮询数据。用户的操作通过View发送给Controller,进一步调用硬件驱动执行。硬件执行的结果从驱动到Controller更新到DataCenter中。界面,数据,命令三者基本解耦。ResultManager成为DataCenter的一个组件,View不再直接与其通讯。
MVC模式的引入,第一次让这个产品了有真正意义上职责明晰,功能独立的架构。
4. 大量类似模块,低效的复用
到上一步,作为一个单独的嵌入式设备,其架构基本可以满足需求。但是随着市场的扩展,越来越多的设备被设计出来。这些设备虽然执行的具体测量任务不同,但是他们都有着同样的操作方式,类似的界面,更主要的是,它们面临的问题领域是相同的。长期以来,复制和粘贴是唯一的复用方式,甚至类名变量名都来不及改。一个错误在一个设备上被修正,同样一段代码的错误在其他设备上却来不及修改。而随着团队规模的扩大,甚至MVC的基本架构在一些新设备上都没能遵守。
最终框架被引入了这个系列的产品。框架确定了如下内容:
- MVC模式的基本架构
- 窗口管理器和组件布局算法
- 多国语言方案(字符串管理器)
- 日志系统
- 内存分配器和内存泄露检测
5. 远程控制
客户希望将设备固定安放在网络的某个位置,作为“探针”使用,在办公室通过远程控制来访问这个设备。这对于原本是作为纯手持设备设计的系统又是一个挑战。幸运的是,MVC架构具有相当的弹性,早期的投入获得了回报。
TL1 Server 对外提供基于Telnet的远程控制接口。在系统内部,它的位置相当于View,只和原有的Controller和DataCenter通讯。
6. 自动化的TL1解释器
由于TL1命令相当多,而TL1又往往不是客户的第一需求,很多设备的TL1命令开始不完整。究其原因,还是手写TL1命令的解释器太累。后来通过引入Bison和Flex,这个问题有所改善,但还是不足。自动化代码生成在这个阶段被引入。通过以如下的格式定义TL1,工具可以自动生成TL1的编码和解码器代码。
7. 测试的难题
经过数十年的积累,产品已经成为一个系列,几十种设备。大部分设备进入了维护期,经常有客户提一些小的改进,或者要求修正一下缺陷。繁重的手工回归测试成为了噩梦。
基于TL1的自动化测试极大的解放了测试人员。通过在PC上运行的测试脚本,回归测试变得简单而可靠。唯一不足的是界面部分无法验证。
基于Test Quest的自动化工具需要在设备运行的pSOS系统上开发一个类似远程桌面的软件,而这在pSOS上并非易事。不过好消息是,由于框架固定了界面的风格和布局算法,基于Test Quest的自动化工具会有很高的识别效率。
8. 小结
从这个实际的嵌入式产品重构的历程可以看出,第三步引入MVC模式和第四步的框架化是非常关键的。成熟的MVC模式保证了后续一系列的可扩充性,而框架则保证了这个架构的在所有产品中的准确重用。