STDF-Viewer 状态管理不崩的 4 个关键点:单一数据源怎么落地
【免费下载链接】STDF-ViewerA free GUI tool to visualize STDF (semiconductor Standard Test Data Format) data files.项目地址: https://gitcode.com/gh_mirrors/st/STDF-Viewer
先聊一个真实踩过的坑:数据可视化应用里,文件 A 的图还挂在图表页上,DUT 表却已经翻到文件 B 的数据;点一下 tab,进度条卡在 99%,表格却刷新了——消息列表和"发送中"那种不同步,在桌面应用里一样会发生。STDF-Viewer 是一个用 PyQt5 写的 STDF 半导体测试数据可视化工具,它靠一条固定管线把"单一数据源、状态只读、变更可追踪"这三件事落了地,下面是完整的做法拆解。
故障现场:界面比数据跑得快
想象你维护一个聊天窗口:消息列表已经渲染出第 10 条,"发送中"却还指着第 9 条。用户点重试,两条消息就重发了。桌面端同样会犯这个错——两个组件各自持有一份"当前文件",谁先刷新谁说了算,界面开始说谎。STDF-Viewer 的做法是把这类事故直接堵死:所有查询只认一个数据出口,所有刷新只走一个槽函数。
为什么状态必须"可预测":一家只有一个出餐口的餐厅
测试汇总页的数据状态示例
别急着上框架名词,先想一家小餐馆。后厨只有一口出餐口(单一数据源):服务员(UI 组件)想吃什么都得喊这一口,后厨现做现端;点单小票上菜只读,谁也不许改单(状态只读);每铃一响,必然对应一道菜端出来,铃响了几次端了几道,账本上一目了然(变更可追踪)。
反例是那种每家服务员手里都备一份菜、还顺手改小票的店:上错菜没人说得清,哪来的错。可预测不是玄学,就是三条:数据只有一个源头,界面只读不写,每次变更都有明确入口。前端状态管理技巧里反复出现的单一数据源、状态只读、变更可追踪,说的就是这家餐厅。
数据怎么流动:一条管线走到底
① 后台线程只干一件事:造数据库。STDF 文件由 Rust 解析器在独立 QThread 里逐条记录解析,生成 SQLite 库;解析完,线程把数据库路径交给主线程。源码里有一句关键注释:sqlite 连接不能跨线程用,所以子线程只负责"造库",主线程负责"连库"。
② 主线程只认一个对象。DataInterface(在deps/DataInterface.py)连上库后,一次性读出文件清单、测试项列表、可用 site/head、BIN 映射、fail 计数等元数据。UI 里所有取值都走它,没有任何组件直接摸库:
di = DataInterface() di.DatabaseFetcher = DatabaseFetcher() self.dbConnected = False self.availableSites = [] self.availableHeads = [] self.completeTestList = []构造函数把每个状态字段都给了明确初始值;之后 UI 调它的都是只读方法,比如getTestStatistics()、getWaferMapData()——它只回答"数据是什么",从不替你改数据。
③ 刷新只有一个入口。后台线程完成后发出dataInterfaceSignal,主窗口槽函数updateData()一次接管:清空旧图表 → 换掉 DataInterface 实例 → 重建 site/head 复选框 → 重挂 DUT 表、datalog 表 → 触发一次onSelect()。全应用没有第二个刷新入口,界面任何变化都能沿这条信号链反查。
④ 选中状态做对比去重。每次选 test、勾 site 或切 tab,onSelect()都会把当前的 (heads, sites, tests) 和selectionTracker里存的上次快照对比:没变就跳过查库,tab 变了则强制重算统计表。Vue 状态流转讲究"状态变了才重渲染",这里是同一个思想——状态没变,查询就别发。
⑤ 配置也是一个数据源。全部设置集中在SettingParams(deps/SharedSrc.py),pydantic 模型带默认值和字段校验:启动读一次,改完写回同一对象,退出自动落盘。改 Cpk 阈值、换语言、调 BIN 配色,走的都是同一条路,不存在"改一处、界面另一半不认"。
状态自查清单:5 个问题对着你的项目过一遍
- 每份数据只有一个"主人"吗?所有查询是否都从
DataInterface这一个对象出去?如果某个 UI 组件直接连库,先把那根线拔掉。 - UI 能不能改数据?过一遍接口:只读方法只该返回数据。任何"顺手改一下"的写法,都是未来对不上账的源头。
- 变更入口是不是唯一的?刷新界面只该走
dataInterfaceSignal这一条信号链;出现第二处直接改模型的代码,就是事故的起点。 - 有没有记录"上次已应用的状态"?照
selectionTracker的做法:状态和上次快照相同就跳过查库,不同才干活。 - 每个状态字段都有初始值吗?打开
DataInterface.__init__对一遍:没给初始值的字段,迟早渲染出个None。
做完这 5 问,再列一张小清单:字段 → 初始值 → 谁写入 → 哪个槽触发。状态对不上时,按清单找,而不是从头调试。
收尾:照搬就能用的 3 句话
把数据收敛到一个只读对象,把刷新收敛到一个信号槽,把"上次状态"存下来做对比——ChatGPT_JCM 状态管理那套"单一数据源、状态只读、变更可追踪",在 STDF-Viewer 状态管理里就是这么落地的。任何数据可视化应用都适用,照着上面的自查清单过一遍,状态就再也不会各说各话。
【免费下载链接】STDF-ViewerA free GUI tool to visualize STDF (semiconductor Standard Test Data Format) data files.项目地址: https://gitcode.com/gh_mirrors/st/STDF-Viewer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考