面向对象设计的一个有缺陷的缓存机制
来源:互联网 发布:客多宝宠物店软件下载 编辑:程序博客网 时间:2024/05/02 00:56
虽然这个标题有点拗口,但是它是我最近在项目中碰到的一次由最初的错误设计导致的重大bug。这类架构层面的设计失误,从一开始就埋下了隐患,后续随着开发小组的变动和软件模块的增加,非常难以跟踪,此外,一当软件编码完成,再有架构层面的变动,是非常耗时耗力的。故此,我将它复原出来,以免再犯同类错误。
一、最初的设计
1,总体架构
最开始我们小组要开发一款“频谱仪”的控制软件,它的架构图如下:
如上图所示,它的大致架构是:
1)BL层以类的形式被GUI层调用;
2)BL层包含多个DLL模块,其中,Hardware(硬件)的接口以pure-c API的形式在BL层调用,其他模块以类的形式包含在BL层。
2,工作流程
工作流程主要在BL层实现,它大致分为4个步骤,反复循环。
如上图所示,BL层反复进行步骤“1 -> 4”的操作。其中步骤1中所谓的“设置硬件参数”,就是调用“Hardware API”中的1、2、3...等接口。
3,缓存机制
对硬件的操作往往都是比较耗时的,假定步骤1中需要设置10个参数,每个参数对应一个API,每个API的调用响应时间为10ms,那么步骤1总耗时为100ms。
经过观察,我们发现:
1)在前一次循环和后一次循环中,步骤1中的10个参数,大部分都是相同的;
2)硬件的10个参数是独立,并且会记住上一次的状态。
基于以上事实,我们想到了用缓存参数的方法来减少对硬件接口的调用,从而提高控制软件的效率。
这个缓存机制的大体思想是:
1)在BL层(它是一个类),设计10个类的成员变量,对应那10个硬件参数。
2)在步骤1中,BL层从GUI获得待设置的硬件参数的值时,先与对应的成员变量比较,如果相等,则不再调用对应的硬件接口。
这个缓存机制的实现交给了B同事。他实现之后,测试OK。
二、新的需求
最近项目提出了新的需求,需要BL层能够并发执行多个任务。架构变动如下:
如上图所示,在程序中同时运行了4个BL层的对象。
三、问题分析
原本以为这个需求的对程序BL层无需改动,仅仅是在GUI层由原来new一个对象,变成new四个对象。窃以为,从一开始使用这种面向对象的设计,能够完美的解决多线程编程时遇到的“不可重入”问题。但是,在实际测试中发现:一当有两个及以上的BL对象同时运行,则获取的结果就出错。
经过几天的试验和分析,终于找出了问题之所在:缓存机制。
当把缓存机制去掉,问题解决。但是细细一想,问题是这么引入的:
1)对象化不完全!在整个程序设计中,其他模块都是对象化的,但是“Hardware API”不是。
2)同时运行两个个BL对象时,假定为A和B,A在前次循环和后次循环,看到它某个的成员变量并未改变,所以不重新设置硬件;而与此同时,B改变了那个硬件参数,但A并不知道。A和B是独立对象,但它们共用一个“Hardware API”。
四,解决方案
找到问题点后,解决的办法有多种:
1)将所有待缓存的参数对应的成员变量设计为static;
2)判断是否某个参数是否改变时,实时从“Hardware API”中获取值,而不是用类的成员变量作为参考值。
- 面向对象设计的一个有缺陷的缓存机制
- 面向对象的缺陷
- 什么是面向对象的软件架构,以下是一个实现UndoRedo机制的面向对象架构设计
- 设计模式是用来弥补面向对象编程缺陷的方法总结
- DDD -- 领域驱动设计 -- 面向对象(OOA/OOD)的缺陷
- C语言的设计模式-面向对象机制的实现
- 面向对象的设计
- 面向对象的设计
- 面向对象的设计
- 面向对象的设计
- 面向对象的设计
- 面向对象的设计
- 面向对象的设计
- Dynamo一个缺陷的架构设计(译)
- Dynamo一个缺陷的架构设计(译)
- Dynamo一个缺陷的架构设计(译)
- Dynamo一个缺陷的架构设计(译)
- 滑块控件的一个设计缺陷
- 一个简单的类似通讯录的封装代码
- Android4.x 如何处理Power按键
- 深入理解Activity启动流程
- nginx负载均衡单点解决方案
- c#学习摘录:类\继承\接口\字段、方法、属性\浅深复制(1)
- 面向对象设计的一个有缺陷的缓存机制
- CentOS无法联网
- Thinkphp3.2图片上传服务器端接收
- TotoiseSVN的基本使用方法
- JQuery获取当前屏幕的高度宽度的实现代码
- 如何使用strace+pstack利器分析程序性能
- 1049 后序遍历
- 使用TypeHandler实现数据入库前的过滤
- C语言变量存储类型auto,static,extern,static extern,register