CAE 案例生产化检查清单
1. 数据与文档
- 领域对象使用 stable ID,UI index/pointer 不作为持久身份;
- Document 有 revision/dirty/schema version;
- 保存使用临时文件 + commit,失败保留旧文件;
- 自动恢复与正式项目文件分开;
- 大数组所有权和峰值内存可观测;
- 导入器限制实体数、深度、字符串和文件大小;
- 单位、坐标系、材料/载荷引用在提交前验证。
2. 命令与撤销
- 所有用户领域修改走 command/service;
- redo/undo 维护完整不变量;
- 大操作使用增量或共享 snapshot,undo memory 有上限;
- 不可逆外部副作用使用明确补偿/新版本;
- 异步结果提交前重验 document revision;
- selection/view state 与领域 state 边界明确。
3. 求解器
Queued -> Starting -> Running -> Cancelling -> Finished/Failed/Cancelled- 每个状态只有合法转换;
- QProcess stdout/stderr 增量排空并限额;
- 输入 deck 在独立工作目录,路径/参数不经 shell 拼接;
- 取消先协议/terminate,deadline 后 kill;
- 退出码、崩溃、解析错误分开;
- 日志、环境、solver version 可追溯;
- 结果只在完整校验后原子导入文档。
4. 线程与关闭
- GUI 只在 GUI 线程;
- worker 不保存易失 UI 指针;
- progress 限频/合并;
- 队列有界,过载有拒绝策略;
- 文档关闭先取消关联 job 并等待;
- 应用退出停止接收、取消/排空、join,再销毁服务;
- 关闭有 deadline 和用户可见进度。
5. Model/View
- begin/end 范围与实际变化一致;
- persistent index/selection 在 reset/move 后正确;
- proxy 映射不假定 row 相同;
- data() 无阻塞 I/O;
- 百万级数据按需加载/虚拟化;
- 使用 model tester 和随机变化测试。
6. 渲染
- GL/VTK 资源只在正确 context/thread 创建销毁;
- context 重建可恢复;
- CPU 计算和 GPU upload 分离;
- staging/upload 有界并丢弃旧 generation;
- 大模型有 LOD/culling/分块;
- picking 使用 stable domain ID;
- 显存不足/驱动错误有降级与诊断。
7. 插件
- IID/metadata/ABI/能力校验;
- Qt/compiler/CRT/third-party 支持矩阵;
- Host service 接口窄且版本化;
- 插件注册资源可统一撤销;
- 运行 job/queued callback 存在时不卸载;
- 不可信扩展进程外隔离;
- 完整细节链接插件工程区,不在 Qt 文档复制两套规范。
8. 安全与健壮
- 所有外部长度/计数/递归深度有上限;
- 临时目录/文件权限与清理;
- 路径遍历、符号链接和覆盖保护;
- 依赖/SBOM/签名/许可证;
- 敏感 token/模型数据不进普通日志;
- 崩溃包可脱敏;
- 模糊测试导入器、项目文件和求解输出 parser。
9. 性能与可观测
- 启动、导入、网格、求解提交、首帧、交互 p95/p99 指标;
- CPU/峰值内存/显存/队列深度;
- profile 后优化,不凭容器 Big-O;
- 大模型基准固定数据集和机器;
- 性能回归有阈值和趋势,而非单次波动;
- 用户操作有 request/job/document correlation ID。
10. 交付验收
- Qt/VTK/solver 动态库随包正确部署;
- clean machine 安装/启动测试;
- 项目文件向前/向后兼容矩阵;
- 自动保存恢复演练;
- 崩溃/断电/磁盘满/solver hang/显存不足故障注入;
- 升级、回滚、卸载保留用户数据策略;
- 文档区分教学示例和生产承诺。
11. 面试/复盘速答
为什么 job 要绑定 document revision? 防旧计算结果覆盖用户之后的修改。
为什么生产化不只是加 try/catch? 还需上限、状态机、取消、持久化、隔离、可观测和恢复。
为什么插件加载成功仍可能不兼容? loader 只解析库,接口 ABI、依赖、数据格式和行为能力仍可能不匹配。
12. 最小发布门禁
format/schema tests
model invariant tests
thread shutdown tests
import/parser fuzz + sanitizers
large-model performance baseline
clean-machine packaging test
crash/recovery drill生产 CAE 先画完整数据流
File/Importer
-> validated domain document (units/schema/revision)
-> compute pipeline (mesh/solve/postprocess)
-> immutable result chunks
-> Qt Model/View adapters + render extraction
-> GPU resources/views每个箭头定义所有权、线程、版本、错误和取消;避免 UI 控件成为隐藏数据库。
Document 不变量
- 单位系统明确且边界转换;
- entity ID 稳定,不用 vector row 当永久身份;
- revision 单调并进入任务结果;
- undo/redo 与 dirty 状态一致;
- 保存只清除成功持久化 revision;
- 关闭后禁止新命令与结果提交。
大数据预算
file mapping/cache budget
domain mesh budget
solver working set
result cache
GPU memory
undo history总预算而非每模块各自“尽量缓存”。缓存可淘汰数据必须能从权威源重建;内存压力触发 LOD、分块和 backpressure。
长任务状态机
Queued -> Running -> StopRequested -> Cancelled
-> Succeeded(revision/input hash)
-> Failed(structured error)进度单调、节流;取消有检查点和最大响应时间;结果提交验证 Document identity/revision;失败保留可诊断阶段与输入摘要。
Model/View 验收
- begin/end 信号包围不可失败提交;
- proxy/source index 映射正确;
- persistent index/reset 策略明确;
- worker 不直接修改 GUI model;
- 大表只获取可见/分页数据;
- delegate 不做阻塞 I/O/求解。
渲染验收
- device/context/thread 责任;
- in-flight fence 与延迟销毁;
- scene revision 与 picking/readback;
- device loss/窗口重建可恢复;
- shader 错误与 GPU memory 可观测;
- 停止提交后才销毁资源。
文件与恢复
autosave snapshot/delta -> temp + checksum -> rotate
normal save -> validated temp -> atomic commit
startup -> detect incomplete/recovery candidates -> user chooses自动保存不能阻塞 GUI,也不能与手工保存竞争同一 revision。崩溃恢复格式也要版本化、限长并 fuzz。
插件与脚本安全
插件声明 ABI/API/version/capabilities;来源签名与权限策略;导入器处理不可信文件时资源限额/隔离。插件卸载先停止任务、断开回调、销毁对象。脚本只获得窄 capability,不默认任意文件/进程访问。
可观测性
记录 document/task/connection ID、revision、阶段时间、队列、内存/GPU 字节、取消延迟、模型 reset 次数和帧时间。错误日志与用户消息分层,敏感路径/数据可脱敏。
测试矩阵
domain unit + schema migration corpus
model contract tests + proxy/edit scenarios
thread cancellation/shutdown stress + TSan where supported
import fuzz + ASan/UBSan
headless/offscreen render tests + device variants
old plugin/old document compatibility
large dataset performance/peak memory发布与关闭演练
发布候选用真实安装包打开历史工程、运行取消/保存/插件/渲染场景;模拟磁盘满、GPU device loss、worker 崩溃与强制退出。关闭必须有 timeout 与诊断,不能让后台线程静默拖住进程。
面试式架构回答
问:CAE Qt 应用如何避免 UI 卡顿? 答:GUI 线程只处理状态提交和显示;计算/I/O 分块到 worker,结果以 revision 标记 queued 回来,并提供背压/取消。
问:大模型为何不能直接塞进 QStandardItemModel? 答:会复制大量对象与角色数据、失去领域权威和按需加载,应实现领域模型适配的 QAbstractItemModel。
自测与答案
- 旧求解结果为何不能只看 Document 指针? 答:同一对象 revision 已变化,需验证输入版本。
- 关闭最先做什么? 答:停止接受新命令/任务,使系统可收敛。
- GPU cache OOM 时为何不能删除任意资源? 答:资源可能仍被在途命令使用,需 fence 安全回收。
- 保存成功的判据? 答:目标 revision 的数据通过持久化协议 commit,而非后台任务刚启动。
工程深化:把本篇知识落到项目里
这一节不是为了凑篇幅,而是把《CAE 案例生产化检查清单》从“知道概念”推进到“能在项目里稳定使用”。 阅读时可以把每个知识点都追问成四件事:它保护什么边界,失败时有什么现象,怎样最小复现,怎样写进团队流程。
concept -> boundary -> failure signal -> minimal proof -> project rule工程切片 1:最小可复现样例
**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。把问题压缩到一个可以提交给同事的目录,保留源码、构建命令、版本输出和预期现象。
**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 事件循环 -> QObject -> 模型数据 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 2:接口边界
**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。写清调用方能依赖什么、不能依赖什么,并把隐式假设转换成命名函数、配置项或测试。
**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> QObject -> 模型数据 -> 线程边界 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 3:失败注入
**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。故意制造一个常见错误,让日志、断言或测试先失败,再用修复后的证据说明规则生效。
**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 4:跨平台差异
**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。至少比较 Windows、Linux 或不同编译器下的一个差异,记录差异属于标准、实现还是平台约定。
**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 5:性能观察
**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用小规模和压力规模各跑一次,区分算法成本、同步成本、I/O 成本和工具链配置成本。
**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 6:生命周期
**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。标出资源创建、转移、共享、停止和销毁的顺序,特别关注错误返回和提前退出路径。
**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 诊断工具 -> 事件循环 -> QObject -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 7:诊断证据
**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。保留命令、日志、符号、栈、测试输出或截图,让结论可以被另一个环境重新验证。
**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 事件循环 -> QObject -> 模型数据 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 8:维护策略
**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。把一次性经验沉淀到 README、CI、脚本、示例工程或检查表里,避免只存在个人记忆中。
**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> QObject -> 模型数据 -> 线程边界 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 9:版本演进
**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。为未来变更预留兼容策略:版本号、特性位、弃用窗口、迁移脚本和回滚入口。
**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 10:最小消费者
**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。从使用者角度写一个小程序或小工程,只依赖公开接口,验证安装包、头文件和运行时行为。
**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 11:边界复盘
**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用一张表说明问题发生在源码、编译、链接、加载、运行、关闭或发布中的哪一层。
**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 12:反例训练
**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。写出一个看似能工作但不可维护的方案,再说明它在规模、团队协作或发布时会怎样失败。
**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 诊断工具 -> 事件循环 -> QObject -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 13:最小可复现样例
**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。把问题压缩到一个可以提交给同事的目录,保留源码、构建命令、版本输出和预期现象。
**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 事件循环 -> QObject -> 模型数据 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 14:接口边界
**场景。**围绕 QObject 建一个很小的案例,不要一开始就放进完整业务系统。写清调用方能依赖什么、不能依赖什么,并把隐式假设转换成命名函数、配置项或测试。
**边界。**先判断这里讨论的是 QObject、模型数据 还是 线程边界 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> QObject -> 模型数据 -> 线程边界 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 15:失败注入
**场景。**围绕 模型数据 建一个很小的案例,不要一开始就放进完整业务系统。故意制造一个常见错误,让日志、断言或测试先失败,再用修复后的证据说明规则生效。
**边界。**先判断这里讨论的是 模型数据、线程边界 还是 资源生命周期 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 模型数据 -> 线程边界 -> 资源生命周期 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 16:跨平台差异
**场景。**围绕 线程边界 建一个很小的案例,不要一开始就放进完整业务系统。至少比较 Windows、Linux 或不同编译器下的一个差异,记录差异属于标准、实现还是平台约定。
**边界。**先判断这里讨论的是 线程边界、资源生命周期 还是 诊断工具 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 线程边界 -> 资源生命周期 -> 诊断工具 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 17:性能观察
**场景。**围绕 资源生命周期 建一个很小的案例,不要一开始就放进完整业务系统。用小规模和压力规模各跑一次,区分算法成本、同步成本、I/O 成本和工具链配置成本。
**边界。**先判断这里讨论的是 资源生命周期、诊断工具 还是 事件循环 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 资源生命周期 -> 诊断工具 -> 事件循环 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 18:生命周期
**场景。**围绕 诊断工具 建一个很小的案例,不要一开始就放进完整业务系统。标出资源创建、转移、共享、停止和销毁的顺序,特别关注错误返回和提前退出路径。
**边界。**先判断这里讨论的是 诊断工具、事件循环 还是 QObject 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 诊断工具 -> 事件循环 -> QObject -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
工程切片 19:诊断证据
**场景。**围绕 事件循环 建一个很小的案例,不要一开始就放进完整业务系统。保留命令、日志、符号、栈、测试输出或截图,让结论可以被另一个环境重新验证。
**边界。**先判断这里讨论的是 事件循环、QObject 还是 模型数据 的责任;如果三者混在一起,先把输入、输出和所有权拆开。
input -> 事件循环 -> QObject -> 模型数据 -> observable result**验证。**记录一条能重复运行的命令或测试,并写明成功输出和失败输出。只说“本机能跑”不够,至少要记录工具版本、构建类型和关键参数。
**常见错误。**把偶然通过当成规则、把私有实现当成公开契约、或者让错误路径绕开清理逻辑,都会让本篇主题在真实项目里变得不可维护。
**复盘问题。**如果明天换一个编译器、Qt 版本、插件版本、输入规模或发布目录,这个结论是否仍成立?不成立时,应该由文档、测试还是 CI 给出提示?
本篇收束
掌握《CAE 案例生产化检查清单》的标志,不是记住所有名词,而是能把 事件循环、QObject、模型数据、线程边界、资源生命周期、诊断工具 放进一条可验证的工程链路。 先用最小样例建立判断,再用测试和脚本固定判断,最后把失败证据留给未来的自己和团队。