返回文章
NO.
015
DATE
READ
~4 min
STATUS
原文

TAGS: 案例研究 博客

一张真机截图引发的连锁修复

一张 iPhone 截图,一个下午,十几个提交:桌面目录的三处缺陷、移动端胶囊的状态机、五个被误记'环境问题'的真 bug,到页脚重构。以及一条贯穿始终的纪律——修复的验收标准是驱动真实行为,不是代码看起来对。

一张 iPhone 截图,一个下午。截图里只有两处不对劲:文章底部的目录胶囊压住了页脚,页脚本身的信息层级乱成一团。但顺着这两个症状查下去,最后动了十几个提交——桌面目录、移动交互、测试套件、页脚,一路连锁。

这篇不是教程,是一次真实的排查记录。它想说的其实是一条纪律:修复的验收标准,是它有没有驱动真实行为改变,而不是代码看起来对不对。

截图里没有的三处桌面缺陷

先说反常的地方。截图是手机拍的,我却先去修了桌面。因为同一次"根治"提交号称修好了桌面目录的三个问题,我顺手在宽屏下复核,发现两处根本没生效。

桌面目录是一条 sticky 的侧栏(rail)。它该随滚动停在头部下方、超长时内部滚动。但它的滚动链断在了一个包装层上——flex 容器的 min-height: auto 让子项无法收缩,内部滚动永远不触发。号称修好的提交改了目录组件本身,却没碰这个包装层,所以"修复"在代码里存在、在页面上不存在。

教训第一次出现:声称修复 ≠ 验证修复。 一个 commit 说"三处根治",不等于三处真的生效。

那颗移动端胶囊:从边沿触发到状态机

回到截图里的正主。移动端阅读时,屏幕底部有一颗目录胶囊,滚到文章末尾(评论区/页脚)时它该让位。原实现用的是 IntersectionObserver 的"边沿触发"——元素进入视口的那一瞬间隐藏胶囊。问题是边沿触发是一次性的:一旦你在末尾区域内继续上下微调,那个"进入"事件不会再来,胶囊状态就卡住了,于是它压住了页脚。

修法是把一次性的边沿事件换成持续的状态:维护一个 inEndZone 布尔,胶囊的显示条件挂在 !inEndZone 上,观察器根据元素相对视口的位置持续更新这个状态(进入末尾 = true;从上方离开 = 仍在末尾之后;从下方离开 = 重新武装)。行为从"某一刻做一次动作"变成"任何时刻状态都自洽"。

五个"环境问题"其实是真 bug

改完这两处,Playwright 套件里有五个测试是红的。它们此前被一份审计记成了"环境问题"——理由是"在主分支上也同样失败,与基线一致"。

这句"与基线一致"很危险。它让一个失实的定性存活了两天。真机截图翻了它的案:这五个失败是双层病因。一层是测试断言停在了旧行为——那次"根治"提交改了交互行为却没改对应的断言,于是断言还在验证一个已经不存在的旧行为;另一层是应用真有个末尾区域的 bug(就是上面那颗胶囊)。两层叠加,看起来像"环境不稳定",其实是两个真问题。

修完两层,套件从 4/9 诚实地转回 12/12 全绿。这里的纪律是:"和基线一样红"不是"没问题"的证据,它可能只是"基线本来就带病"。 绿,才重新是闸门。

页脚重构

最后才轮到截图最初的症状:页脚信息层级。原页脚把导航、版权、许可证、统计堆在一起,没有语义分组。重构成三块语义结构——来源优先的导航、版权/许可/隐私一行、colophon 一行——移动端按来源优先纵向堆叠,并在窄屏给固定的返顶按钮预留一条底部让位带,让它停靠时不再压住任何文字。

真正想说的

十几个提交,起点只是一张截图。但把它们串起来的不是某个具体的 CSS 或 observer,而是两条纪律:

  1. 验证驱动的修复。 桌面目录那两处"改了但没生效",和测试那五个"红了但被记成环境问题",是同一个病的两种表现——都把"代码看起来对"当成了"问题解决了"。修复的验收标准必须是驱动真实行为:目录真的在滚、胶囊真的让位、测试真的因为行为正确而变绿。

  2. 诚实记录,包括翻案。 那句"与基线一致、判为环境问题"如果一直留着,后续每一个接手的人都会在错误的基线上工作。翻案时我没有删掉原记录,而是加了一条带日期的更正——因为"我们曾经判断错、后来纠正了"这件事本身,就是这个博客最该留下的东西。

一张截图能引发多大的连锁,取决于你愿不愿意顺着第一个症状一直查到底,以及查到"其实之前判断错了"的时候,肯不肯把它写下来。

评论 →

CC BY-NC-SA 4.0

本文采用 CC BY-NC-SA 4.0 进行许可。

评论

评论由 GitHub Discussions 提供。登录 GitHub 后即可评论。 前往对应 Discussion