Files
Just-DataInspector/Documents/Code_Review_Plan.md
T
DeepSeek-V4.1-Flash 86ff0291ba docs(review): 新增代码审查计划与进度文档(Code_Review 分支)
- 删除已完成使命的 UI_Refactor_Plan/Progress/Report(已在 dev 提交 764e5be)。
- 新增 Documents/Code_Review_Plan.md:结构 + 性能 + 体积的节点化计划,
  含已确认的问题事实(dynamic_cast 在最小复现里 +75,264 B、
  cp-demangle.o 56,320 B、每个 EdgePanelKind 出现 21-26 次等)。
- 新增 Documents/Code_Review_Progress.md:基线数字与节点记录。
2026-11-04 02:44:23 +08:00

177 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Code Review 计划(分支 `Code_Review`)
> 目标:在不引入性能回归、不改变用户可见行为的前提下,对全项目做一次**结构 + 性能 + 体积**
> 的查漏补缺,并把「改一个功能要动 40 处」的屎山点收敛成表驱动/单一实现。
>
> 基线(本计划开始时):
> - 分支 `Code_Review`,起点 `764e5be`(dev 已删除过时的 `UI_Refactor_*` 三份文档)。
> - `make release` 产物 **890,880 B**(`.text` 753,136 B、`.rdata` 36,936 B、`.rsrc` 20,656 B、
> `.pdata` 30,420 B、`.xdata` 29,496 B、`.idata` 12,856 B)。
> - 源码约 **5.6 万行**;最大单文件 `PlotViewPaint.cpp` 6,561 行、`PlotView.hpp` 4,654 行。
>
> 约束:
> - 每完成一个节点**编译验证(release + debug 零警告)**并**提交**,同时更新
> `Documents/Code_Review_Progress.md`。
> - 性能相关节点必须给出**同一次运行内的相对量**(历史教训:绝对毫秒阈值不可靠)。
> - 不占用用户的鼠标/键盘/屏幕(只用纯控制台探针或源码级核对)。
---
## 一、已确认的问题(本计划的事实基础)
### A. 体积
| 项 | 实测 | 说明 |
| --- | --- | --- |
| `dynamic_cast`(`Toolbar.cpp:370`) | **+75,264 B** | 最小复现程序:39,936 B → 115,200 B。它会链入 RTTI 元数据 + `cp-demangle.o`(map 里 **56,320 B**)。而该处 `Button::widget` **本来就是 `UiButtonWidget*`** ⇒ 转换完全多余。 |
| `-fno-rtti` | 未启用 | 移除上一条后即可开启,进一步去掉 `type_info` 表。 |
| `.pdata` + `.xdata` | 60 KB | `-fno-exceptions` 已开;SEH 展开表仍存在。可尝试 `-fno-asynchronous-unwind-tables`(历史上链接失败,需复核)。 |
| `libmingwex` 的 `strtodg/gdtoa/mingw_wpformat` | 27.8 KB | 来自 `wcstod` / `wprintf` 类调用;可评估用自写解析替代 `wcstod` 的收益(公式/输入框解析)。 |
| `.rsrc` | 20.7 KB | 图标(PNG 帧)+ manifest + 版本信息,已优化过。 |
| 重复常量/重复实现 | 多处 | `kFormulaEnvelopeBuckets` 已清理;仍有 `ClampDouble` 两份实现等。 |
### B. 性能(结构性热点)
1. **面板开关/参数处理是 6 个 `EdgePanelKind` × ~20–26 处 switch 分支**(实测每个 kind 出现
21–26 次,全部由手写 `if/switch` 维护)。这是**新增功能必然漏改 2–3 处**的根本原因
(历史已发生 4 次:`MARK` 漏拖动、`RESAMPLE` 漏拖动+关闭、`CLIP` 漏滚轮+缓存键)。
2. **`SceneContentHash` 里 6 段几乎相同的逐面板混入循环**(`PlotViewCacheKey.cpp`)。
3. **`EdgePanelLayoutFor` 是巨型分支**,`EdgePanelLayout` 结构体带 20+ 个按面板类型区分的
矩形数组;高度算式与几何算式分开写(历史上多减一个 pad 造成空白空白 BUG)。
4. **`PlotView` 有 30+ 个缓存**,每个都手写「键 + DC + 位图 + 贴图 + 失效」五件套;
失效路径散落在 8 个文件里,`m_sceneValid=false` 出现 6 处。
5. `ApplicationCommands.cpp` **2,165 行**混杂:标签页、数据派生、菜单、工具栏、键盘、鼠标。
6. `PlotView.hpp` 4,654 行(声明 + 内联实现),单文件认知负担极大。
### C. 过时/错误注释与命名(抽样已确认)
- `agent_mem.md` §3「目录结构」仍写着已不存在的 `Utilities/CsvTable/`、`Utilities/DataModel/`
等目录;§2 写 `-Os` 而实际是 `-Oz`。
- 源码中留有历史轮次的「本轮」「上一轮」叙述(对当前读者无意义),以及被推翻方案的注释。
- `PlotViewInternal.hpp` 里 `kFormulaEnvelope*` 注释已随实现迁移,需同步。
---
## 二、节点计划
> 优先级:**S**(安全、收益明确、风险低)→ **A**(结构调整,中风险,需逐步验证)→
> **B**(深度重构,必须有可验证的前后一致性)。
### 阶段 0:建立基线(节点 P0)
- P0.1 记录基线:release/debug 体积、`.text/.rdata` 等节表、关键路径的可复跑测量程序
(纯控制台,链接 `Build/Release/*.o`,不入库)。**已完成基线的部分见下表**。
- P0.2 建立 `Documents/Code_Review_Progress.md`,每节点完成后追加一行结论 + 数字。
### 阶段 1:体积(节点 P1–P5,安全优先)
- **P1 移除 `dynamic_cast` + 开启 `-fno-rtti`**
- 把 `Toolbar::BuildBoxes` 的 `dynamic_cast<const UiButtonWidget*>` 改为直接用
`Button::widget`(已是该类型)或给 `UiWidget` 加虚函数 `ContentBounds()`。
- Makefile `CXXFLAGS += -fno-rtti`;全仓确认无 `typeid`/`dynamic_cast`/`type_info`。
- 预期 **−70~80 KB**。验收:产物下降 ≥60 KB;功能逐项核对(工具栏按钮、布局边界调试)。
- **P2 体积审计第二轮**
- 复核 `-fno-asynchronous-unwind-tables`(历史上链接失败,试 `-fno-unwind-tables` 组合)。
- 评估 `wcstod` 替身(自写定点/浮点解析,仅在公式与输入框使用)去掉
`strtodg/gdtoa/gethex/hexnan`(约 20 KB)。
- 评估 `--gc-sections` 在 LTO 下是否已生效(读 map 确认无死节)。
- 验收:逐项给出「测得的字节数 + 是否采纳」的结论,**不接受「感觉变小」**。
- **P3 重复实现归并**
- `ClampDouble` 两份(`PlotViewInternal.hpp` / `UiLayout.cpp`)→ 统一到 `Shared`。
- 扫描全部 `static`/匿名命名空间重复工具函数,合并为单一实现。
- 重复字符串/常量字面量、重复的三元式开关表。
- **P4 死代码与未使用成员清理**
- 用非 LTO 对象 + `nm` 反查「定义但从未被引用」的函数;删除确认无引用的实现。
- 清理 `PlotView.hpp` 中已无人读取的成员/字段。
- **P5 资源与启动数据**
- `.rsrc` 复核(图标帧数、manifest、版本字符串);`.idata` 导入表复核。
### 阶段 2:性能(节点 P6–P10)
- **P6 建立可复跑的渲染性能探针(纯控制台)**
- 目标:能在**不弹窗口**的情况下测量 `BuildLaneVisuals` / `SceneContentHash` /
`EdgePanelLayoutFor` / 面板绘制 / 信号面板绘制的耗时。
- 方式:链接 `Build/Release/*.o` + 手工构造 `DataSet`/`TabConfig`,只调用纯函数与
`PlotView` 的非窗口方法(避免 `Application::Initialize` 触发模态框,见历史教训)。
- 所有断言用**同一进程内的相对量**。
- **P7 面板元数据表驱动(核心)**
- 新增 `EdgePanelSpec`(每 kind 一行:命令 id、默认尺寸、是否列表型、footer 类型、
滚动字段偏移、面板状态字段偏移、绘制函数指针、命中函数指针)。
- 把 6×~20 处 `switch (kind)` 收敛为「查表 + 3 个通用实现(列表型 / 表格型 / 固定行型)」。
- 验收:**逐像素**对比改造前后面板(离屏渲染哈希);新增一个假 kind 只需加一行表项即可
被绘制/命中/拖动/关闭/滚动全覆盖(用编译期断言或探针验证)。
- **P8 `SceneContentHash` 混入收敛**
- 把 6 段重复循环改为「按面板表遍历 + 每面板一个 `MixContent()`」。
- 验收:改造前后哈希值**逐位相同**(同一状态)。
- **P9 `EdgePanelLayoutFor` 表驱动 + 高度/几何同源**
- 高度算式与内容几何共用同一份 `PanelMetrics` 计算(消除重复减 pad 类 BUG)。
- 验收:探针打印「内容区下边界 vs 按钮上边界」的像素差,与改造前一致。
- **P10 缓存五件套抽象(低风险版)**
- 抽出 `OffscreenCache`(DC/位图/键/贴图/失效),**只替换三处结构完全相同的**
(derived / decor / panel),保留 scene 与 lane layer 不动(热路径最复杂)。
- 验收:逐像素一致 + 帧时间不回退。
### 阶段 3:架构(节点 P11–P14)
- **P11 `ApplicationCommands.cpp` 拆分**
- → `ApplicationTabs.cpp`(标签页)/ `ApplicationDerive.cpp`(派生/重采样/截取/克隆)/
`ApplicationCommands.cpp`(命令分发)/ `ApplicationMenus.cpp`(上下文菜单与设置菜单)。
- 纯搬移,零行为变更;Makefile 无需改动(按目录通配收集)。
- **P12 `PlotView.hpp` 拆分**
- 把 `EdgePanelLayout`、派生曲线缓存条目、图层结构体等**纯数据结构**搬到
`PlotViewTypes.hpp`;把 `PlotView` 的内联小函数按关注点分块放到 `PlotViewInline.hpp`。
- 目标:`PlotView.hpp` ≤ 2,500 行。
- **P13 UI 基础层职责核对**
- 核对 `UiWidget` / `UiComponent` / `UiLayout` / `UiBox` / `UiSurface` / `UiButtonWidget` /
`UiControls` 的边界是否重叠;合并确认冗余的(只保留一套矩形/命中/布局原语)。
- 明确依赖方向:`Components/*` → `Components/Shared` → `Utilities`(校验无反向)。
- **P14 绘制/功能组件边界**
- `PlotViewPaint` / `Raster` / `Panels` / `Features` / `Interaction` 的职责再核对;
把「面板几何」与「面板绘制」的交叉依赖理顺(几何 → 共享 `PanelMetrics`)。
- 把散落在 `PlotView` 里的「颜色/线宽/胶囊样式」常量收敛到 `Theme`/`PaintUtil`。
### 阶段 4:注释与命名清理(节点 P15)
- **P15 注释/命名审计**
- 删除「本轮/上一轮」叙述、被推翻方案的描述、与实现不符的注释。
- 统一命名:`*Dc`/`*DC`、`Lane*` vs `Grid*`、`Edge*` vs `Panel*` 等不一致处。
- 确保所有注释与当前实现一致(重点:`PlotViewInternal.hpp`、`PlotViewCacheKey.cpp`)。
- 同步更新 `agent_mem.md` 的 §2/§3(已经不准确的目录结构与 `-Os`)。
### 阶段 5:验证与报告(节点 P16)
- **P16 最终验证与报告**
- release + debug 零警告;产物体积对比;关键路径探针全部通过。
- 生成 `Documents/Code_Review_Report.md`:逐节点写「改了什么 / 为什么 / 效果 /
未做的事与原因」,并给出体积与性能的前后对照表。
---
## 三、验收标准(硬性)
1. `make release` 与 `make debug` **零 error、零 warning**。
2. 产物体积**必须下降**(目标:从 890,880 B 降到 ≤ 780 KB;若某项无法达成,在报告里
说明实测字节数与原因)。
3. 不改变任何用户可见行为(面板几何、绘制像素、交互语义一致)。
4. 每条性能结论都必须有**同进程相对量**或**逐像素/逐位一致性**证据。
5. 每个节点单独提交,提交信息用中文、说明改动与验证方式。
---
## 四、风险与对策
| 风险 | 对策 |
| --- | --- |
| 面板表驱动改造引入像素差异 | 改造前后用离屏渲染哈希对比;先改 `CLIP`/`MARK` 两个最简单面板做样板,再推广 |
| `-fno-rtti` 破坏第三方/库代码 | 全仓 grep 确认;先单独提交,失败可独立回退 |
| 缓存抽象拖慢热路径 | 只抽象非热路径(derived/decor/panel),scene/lane 不动;每次改完测帧时间 |
| 大文件拆分时误改逻辑 | 纯搬移(不重写函数体),逐文件 diff 核对;先拆 `ApplicationCommands` |
| 探针触发模态「内存不足」框 | 绝不在探针里调 `Application::Initialize()`(历史教训);只构造数据层/纯函数 |
---
## 五、进度索引
进度与每节点的实测数字见 `Documents/Code_Review_Progress.md`。
最终结论见 `Documents/Code_Review_Report.md`。