DEVELOPER'S JOURNAL

NOTE 04 · HOW I KNOW

证据流程随录——为什么不信自己的截图

一个人做项目怎么防止骗自己:证据只追加不改写、截图不当证明、指标只是及格线,以及这套流程实际拦下过的几次事故。

这些是我自己写的记录,会提到失败、犹豫和还没做完的事。它描述的是现在,不是最终形态,也不是任何发售承诺。

前言

一个人做项目最容易骗的是自己:没有同事、没有 code review、没有 QA,唯一会说“这个还没做完”的人是自己,而自己恰好是最不想说这句话的那个。提需求、干活、验收三顶帽子戴在一个脑袋上,最后一顶最容易掉。

所以这个项目里“完成”不是一种感觉,是一种必须带着证据出现的状态。这篇记一下这套证据流程长什么样,以及它实际上挡下过什么。

只追加,不改写

第一条规则:被接受的证据不能改。每次正式捕获会生成一个目录——截图、日志、性能采样、文件清单——目录一旦封存,脚本会拒绝往里写;新的工作写到新目录里,失败的尝试不删只披露。

实践里这条规则会带来一些不太舒服的事。7 月 15 日第一次完整走通城镇到城镇的一局,试玩验收原话是「我试玩了觉得没有什么问题」,然后封存的验收清单十六项一项没填,于是它永远停在 0/16。属实汗颜,但规则就是规则:批准是后来追加的另一份记录,不回头把 0/16 改成 16/16,也不替当时编出十六条“观察到的情况”。一开始觉得这条严苛得有点过分,现在觉得它是整套流程里最值钱的一条——它记的是当时摆在面前的东西,不是事后希望自己审阅过的东西。

截图不能当证据

第二天翻了个大车:事后审计发现,一份已经通过审批的画面包里,静态截图的景深刷新是错的——也就是说,拿来做审批判断的那些截图本身就不对。包已经批了,处理方式不是回去改,而是追加一份修正过的新包带自己的清单,旧的一个字节不动。从那天起对截图的态度就变了:截图是给人看的,不是用来证明的。证明要靠校验器打出来的那行 OK、文件哈希清单、可以重新算一遍的东西。

同一天还有两次失败留在记录里。一次是网络劣化条件下的联机测试,跑满十分钟,两个客户端一个事件都没收到,终结器直接拒绝并清除了这次运行,没替它编原因,因为当时确实推断不出来。另一次更离谱:正式测试两个客户端都干净退出,收尾时却因为一个“读不出来的确认文件”整次被拒。高度怀疑是 macOS 给文件延迟附加了一个扩展属性、改动了它的时间戳——但高度怀疑不是证明,所以只针对这两个文件做了最小加固(读两遍、隔开一点时间、逐字段比对),然后把相关测试全部重跑。记录里把“猜是这个原因所以这么修”和“证明了这个原因”分开写。

指标是及格线

第二条规则:机器指标是必要条件不是充分条件。每个新候选都按同一个模式出现——新文件、运行时开关、自己的校验器、自己的证据目录;指标全绿之后,还得过一道有名字的人工门才能改默认值。

于是仓库里长期存在这样的状态:某套光照方案六项指标全达标、性能过关、证据齐全,运行时默认值仍然是老的,新的只是个 opt-in。通过指标和通过审美是两件事,前者不该自动变成后者。这一点在守卫像那次表现得最清楚:几千项检查全过,打开画面像一段神龛。机器只查被教过的东西。

回滚 ≠ 恢复

8 月 10 日尝试把东京服务器恢复到上一个稳定版本,失败,证书链校验没过;自动回滚成功,服务在线。记录里就两句话:“恢复没有成功。回滚成功。”中间不加“所以”。把“回滚成功”说成“旧版本恢复成功”是最省事的自我欺骗——甚至不用撒谎,把两件事写成一句话就行。

网站上的图

顺着这个逻辑说一下这个网站。上面绝大多数图标着「再渲染实机截图」:从开发中的实机画面出发,为了气氛和构图重新渲染过,不是原始截图也不是最终画面。少数几张标着「实机截图 · 开发中版本」,直接从引擎里截出来只缩小没动,比如下面这张。它粗糙得很,但正因为没再渲染,它才能证明一些事:这个场地存在,这几个角色存在,霸主站在门后。

实机截图:白昼的森林战场,霸主站在遗迹之门前,牛头人与哥布林散布在石板上,剑士与占位形象的吸血鬼站在前景的光环里实机截图 · 开发中版本
白昼,首领门前。这张没有再渲染。实机截图,开发中版本。

后记

这套做法很慢:写校验器的时间经常超过写功能的时间,每次“完成”之后还得跑一遍链条才敢说出口。但它确实挡下过东西——朝向错误的候选链在昂贵的正式捕获前就被探针拦下;零事件的联机运行被拒绝而不是被解释;有缺陷的截图包被追加修正而不是改写;东京的恢复被如实记为失败。放在一个只记成功的流程里,这些全会消失。

换来的是一个人做项目最稀缺的东西:五个星期前写下的结论,现在还能信。游戏还在做,这篇记的不是它做到了什么,是怎么知道它到了哪一步。