Appearance
第 32 章 · 审核的微光
背景:大面板迁移后硬编码残留、测试覆盖不足
过程:清理硬编码、动态求值与补测试覆盖
惊醒
审核员来到议会大厅时,MenuStack 正坐在角落里发呆。
"怎么了?"审核员敲了敲桌子。
议会抬起头,眼神有些涣散:"我总觉得……有些东西不对劲。但我说不上来是什么。"
审核员环视大厅。57 个面板已经从命令式函数变成了声明式数据,菜单树只有一张蓝图了。看起来一切正常。
"让我看看你的账本。"审核员说。
追查
审核员翻开议会的账本,一行一行地看。
第一页就发现了问题。settings-appearance.ts 里,UI 缩放的标签写着 "UI 缩放",主题色写着 "主题色",弹窗宽度写着 "弹窗宽度"。
"这些标签是硬编码的中文。"审核员指着账本说,"如果有用户想把联邦改成英文界面,这些字不会变。"
议会的脸涨红了:"我……我知道 i18n 系统,但迁移的时候太急了,就忘了抽 key……"
审核员没有责备,只是继续翻。
第二页,motion-popup.ts 里,物理分类的显示条件写着:
typescript
const physCategories = inst.kind === 'actor' ? getPhysicsCategories(id) : [];
visibleWhen: () => physCategories.length > 0,"这里有个陷阱。"审核员说,"physCategories 在构建时就被计算了。如果用户后来给模型加了物理分类,这个条件永远不会更新——因为它在 schema 构建的那一刻就凝固了。"
议会倒吸一口冷气:"那……那物理分类变化时,UI 就不会响应?"
"对。"审核员点头,"visibleWhen 必须在渲染时重新求值,就像 binding:layers 那样。"
第三页,menu-schema.test.ts 的测试清单。sectionTitle 的渲染没有测试,light 和 perception 的 StatePath set 逻辑没有测试,ControlSpec.set 的逆向转换没有测试。
"你的试金石不完整。"审核员说,"这些缺口意味着将来有人改了这些逻辑,可能不会被发现。"
第四页,render-menu.ts 的 renderFolder 函数:
typescript
if (children.length === 0 && !node.renderCustom) {
return undefined;
}审核员指着这段代码:"如果一个 folder 只有 headerToggle,没有 children 和 renderCustom,它就不会被渲染。但 headerToggle 本身是有意义的——它是一个可交互的开关。"
议会沉默了。这些问题都不是致命的,但它们像灰尘一样,一层一层地覆盖在联邦的表面。
真相
审核员开始动手清理。
第一把扫帚:i18n 硬编码
把 8 处中文标签抽成 i18n key:settings.uiScale、settings.popupWidth、settings.themeColor……然后在 5 个语言文件里添上对应的翻译。
"每个标签都应该有自己的护照。"审核员说,"这样它们才能在不同语言的城邦间自由通行。"
第二把扫帚:visibleWhen 动态求值
把 physCategories 的计算从构建时移到 visibleWhen 函数内部:
typescript
visibleWhen: () => {
const inst = modelManager.get(id);
return inst?.kind === 'actor' && getPhysicsCategories(id).length > 0;
},"条件不应该是快照,应该是活的。"审核员说,"每次检查时都要重新问一遍——现在的情况是什么样的?"
第三把扫帚:测试覆盖
添了 5 个测试用例:
- sectionTitle 生成分组标题 DOM
- light. 前缀 set 调用 setLightState
- perception. 前缀 set 调用 setPerceptionState
- slider set 将百分比 0-100 逆向转换为 0-1 范围
- headerToggle set 将 boolean 逆向映射为枚举值
"试金石要覆盖每一条路。"审核员说,"这样你才能知道哪条路走得通,哪条路会塌方。"
第四把扫帚:空 folder 的 headerToggle
修改 renderFolder 的判断条件:
typescript
if (children.length === 0 && !node.renderCustom && !node.headerToggle) {
return undefined;
}"不能因为房间里没有家具,就把门锁上。"审核员说,"门口的开关可能是唯一的入口。"
教训
审核员离开时,议会大厅已经焕然一新。
议会送审核员到门口,有些不好意思地说:"谢谢你。这些问题我自己看了好几遍,都没发现。"
审核员笑了笑:"聚合者的眼睛很容易被整体的宏伟遮住。你看到了 57 个面板成功迁移,却没注意到每个面板上的微小裂痕。"
他指着远处的地平线:"联邦就像一面镜子。表面看起来光滑,但如果有一粒灰尘落在上面,整个画面就会模糊。审核不是挑错,是帮你擦亮镜子——让你看清自己的全貌。"
议会看着审核员远去的背影,突然明白了什么。
聚合的代价不仅仅是依赖的增加,还有细节的稀释。当你把所有城邦都收编进来时,很容易忽略那些藏在角落的小问题。
而那些小问题,正是联邦最脆弱的地方。
教训摘要:审核是擦亮镜子,让聚合者看清全貌。