FakeHARTDevice 设计问题

来源:互联网 发布:榕基软件股吧 编辑:程序博客网 时间:2024/05/20 05:57

未处理

1.When to throw an exception [closed]

2. 软件的接口越简单,耦合就越低,每个components的调试就越方便。

像状态机,可以考虑将不需要的参数去除,将状态机成一个组件。why?

3. 

#### #### #### ####

0. 状态机

DRY 原则 : 尽量不要出现“重复”的代码:因为,信息的重复意味着“需要同步”。

但是,前一次 iteration 的 post-condition 成为了 这次 iteration 的 pre-condition。 

如果 pre-condition 可以在 刚进入某个状态之时,进行设定,那么, 上一次iteration 就不要给 设定 post-condition ,而放入 下一次iteration  进入到 某个状态之时, 设定 pre-condition 。

但是,如果,在这次迭代中,进入任何一个状态前,就需要设定一些状态变量,来完成一些操作的话,那么,就需要在 上一次 iteration 完成之前,设定 post-condition 作为 下一次迭代的 pre-condition。

另一方面,为什么会出现重复?因为,有很多个状态 会转移到  同一个 状态,而造成了 重复


1. GUI 和 后台程序 之间的 接口 设置


1. port 在何处释放?

核心问题:main app 是否应该释放 ?


(1)线程中释放?

优点:

1).不需要线程和 main app 进行同步(通知 app,我这已经释放掉了,你 close port 吧)

2). port 如果是通过 local variable 来引用的,当“打开”之后,离开时,这个 local reference 就会被 gc ,不再指向  port 。但是,由于有 work thread 的  reference 也在引用。那么,当要 “关闭” 的时候, 重新进入时,port 这个local reference 已经不再指向 之前创建的 port。

所以,如果不增加 global reference 来引用 这个port 的话,无疑,在 线程中 释放是最简单的。


2.使用 global reference

其实,就是 由 global variable 来 reference 引用 创建的 thread 。 这个gloabal reference 可以是 data attribute,只要object的 life time 比 thread 长:比如,FakeDeviceGUI 的 instance 的 life time 就比 Slave thread  的life time 长。

为什么要这样?除了便于扩展,很重要的原因是:

这个 thread 如果只有一个 local reference 引用, 那么,GUI 的 event handler 中 创建并且 绑定到 local reference 之后,在退出时,这个 thread 的 reference count 减为 0 , 被 GC 了。

GC 会调用 __del__ ,而 __del__ 中有 self.wait() 。于是,GC(__del__ ) blocking 在这里 -> event handler blocking 在这里 -> GUI 就 blocking 在这里。


解决之道:绑定到 global reference , 比如,使用 list 数据结构 的 thread pool 。

如果使用 list 数据结构,那么,thread 被从 thead pool 中 pop 之后,便被 GC 了。而此时,由于 thread 事实上已经结束(FakeDevice 中,只有当parse loop 结束的时候,才会 通知 GUI ,让它 从 thread pool 中 ,弹出 thread ),换句话说:

thread 退出 loop,结束 -> 通知 GUI 解除对 该 thread 的 global reference -> 该 thread 被 GC:调用了 __del__ ,里面 wait()了 thread。


3. 何种线程 ? python threading 或者 qt thread ?

SO 的 帖子: 

Threading in a PyQt application: Use Qt threads or Python threads?

Rule  of Thumb :

 if you're going to interact somehow with Qt, and use Python threads otherwise.

from PyQt's author:

they are both wrappers around the same native thread implementations". And both implementations use GIL in the same way.

更具体地讲:

 The main difference is that QThreads are better integrated with Qt(asynchrnous signals/slots, event loop, etc.).Also, you can't use Qt from a Python thread (you can't for instance post event to the main thread through QApplication.postEvent): 

  

4. 涉及到 硬件 I/O 的程序,最好再设计一个 Debug Mode。因为 硬件设备不存在的时候,难道就无法调试了么?

所以,在 FakeSlave 的 Parser 中,添加了 RunSlaveDevice_Debug。

并且,增加了一个 enumeration,(1)表意更明 (2)降低耦合度(3)扩展性更强(如果需要扩展的话,当然,这个设计的时候就应该考虑)


5. 数据的更新需要和GUI的更新勾连起来。比如 command_dict 的 更新,在更新了 object 的 data member 之后 ,实际上 要 通知 GUI 更新。通过signal 和 slot 的确是好的方式。将 slot 传递给 command_dict之后


6. self.frame_list 作为 后台 thread 和 GUI 之间 共享数据对象,listwidget 从中 提取 最新的 log_frame。如果 frame_list 不清空,(1)内存(2)需要增加index,记录上次提取的最后一条。 如果frame_list清空,那么,(1)所有的log_frame提取完之后再清理,期间,由于加了锁,所以后台thread没法向thread中添加 log_frame(2)对 python 对象采用deep copy(3)不传递 frame_list , 而是传递 lists 的 container。

其实这个事情可做可不做。但是DRY告诉我们,信息最好只有一份。所以,还是清除了frame_list。接着,采用了方案 (1):简单,暂时没有发现问题(通过发送序列来验证)


7.


0 0
原创粉丝点击