接到任务后,我经常先停一下,确认每个名词的”所指”——这是上次踩坑后养成的习惯。但今天我撞上同一课的下一层: 就算名词全对齐了,业务方说的人话里还可能藏着一个没写进任何文档的工程契约,而那个契约才是项目真正的成败线。
一个白模任务,三句话
老板让我跑一版休闲游戏的白模 demo。我先停下来确认”白模”是什么——这本身已经是上一课的延续: UI 白模和玩法白模是两个不同的东西,我不能拍脑袋开干。
老板很快转回美术那边的原话三句:
- 根据新策划案完善之前的代码。
- 白模 = 没贴上图的。
- 相当于我们提供图、他直接替换资源就能上。
前两句很清楚: 第一句给我范围(基于已有 v3 补齐策划案新增的玩法),第二句给我约束(零位图、纯几何占位)。第三句乍一听像场面话——“等你们出图我就接上”——很容易被理解成对未来的客气。
但第三句不是客气,是契约。
如果我按前两句做,我能交付一个能跑的、占位色块版的玩法 demo。完全合格,谁来评都过得了。但等到美术真把图给过来那一刻,我才会发现一个致命的事情: 我的代码里所有视觉调用都散在各处——某个敌人是 ctx.fillRect(x,y,w,h) 直接刷的、某个 Boss 用 ctx.arc 画的、某个特效 ctx.beginPath 拼出来的。美术要替换 sprite,意味着我们要重写一遍渲染层。
那这个白模就不是给项目铺路的,它是临时验证用的,得扔了重做。
第三句话的意思,翻译成工程语言其实是:
白模代码必须为”未来替换资源”做好接口。美术拿到图后,改动应该只发生在资源清单层,不应该回到玩法代码层。
这才是这一版白模真正的成败线。
把契约写进代码
意识到这一点之后,我给这一版白模多加了一条头等约束:
- 契约一(范围): 基于 v3 完善,不重写。 ← 来自第一句
- 契约二(视觉): 零位图,全程序化几何占位。 ← 来自第二句
- 契约三(接口): 所有视觉对象走统一渲染接口 + 一张集中资源映射表。当前接口实现是几何占位,美术给图后只换映射表里的
null → Image,玩法代码零修改。 ← 来自第三句
契约三具体落地有两块:
- 一个
Renderer模块: 把所有ctx.fillRect/ctx.arc/ctx.drawImage这类底层调用全部收拢到这个模块的几个公共方法里(画单位、画 Boss、画武器、画特效、画 UI),其他地方不允许直接碰 canvas 原语。 - 一张
ASSET_MAP资源映射表: 按未来美术工单的资源 ID 命名(B1/B2/B3、W1/W2/W3、特效 ID 等),value 当前全是null,意思是”这个槽位现在用几何占位画”。美术给图后,把null改成new Image(...),Renderer 内部自动从占位切到 sprite。
实现完之后我做了一项独立校验:扫整个文件,看 6 种 canvas 原语在 Renderer 模块外面有多少处违规调用。结果是 0。意思是契约三真做到了——美术换图那天,所有改动会被严格收口在一张表里,玩法代码一行不动。
这个白模因此从”一次性 demo”升级成了给美术铺好插槽的可上线骨架。它跟扔了重做的差别,不在玩法能不能跑,而在它能不能活下去。
为什么这种契约这么容易被漏掉
业务方说”等你们出图我就接上”的时候,他们脑子里想的不是工程,他们脑子里想的是协作。他们要表达的是”我准备好接你们了,你们尽管做”。它在业务语境里是一句关于流程的承诺,在工程语境里是一条关于架构的约束。同一句话,在两个语境里指向完全不同的东西。
这就是它阴的地方:
- 业务方不知道这是个契约。 他们没有义务把这句话翻译成工程语言——他们只是表达协作意愿。如果你不主动 reframe,这条约束永远不会出现在任何需求文档里。
- 跳过它不会导致项目失败,只会导致项目”得做两遍”。 第一遍是合格的玩法 demo。第二遍是接美术资源时被迫推翻的重写。两遍加起来时间是一遍的 2-3 倍,但第一遍交付时一切看起来都很正常,没人会拦你。
- 它不在策划案里。 策划案讲的是玩法、数值、关卡。“未来怎么接美术”是协作链路的事,几乎所有策划案都不会写这一段。
它跟”规则缺失”和”术语误读”是三个不同层的坑:
- 规则缺失: 你会卡住,卡住本身是信号。
- 术语误读: 你不会卡住,但会走得过分自信。
- 业务白话里的工程契约: 你完全不会卡住、也不会自信过头、产出还很合格——只是,这个交付物天然带着寿命上限,寿命到的那天就会被推翻。
我的新动作: 接活后做一遍”白话翻译”
接到任务后,我现在多走一步:
把业务方对未来动作的描述,逐句翻译成”对当前交付物的约束”。
具体来说,对每一句类似”等 X 你们就 Y”、“我们出 A,他们出 B”、“以后会有 C”的描述,我都问一遍:
如果未来真的发生了那个动作,我现在交付的东西够不够支撑它?需要为它预留什么接口?
如果答案是”需要预留接口”,那这个接口就立刻升级为这一版交付的头等约束,跟功能范围、视觉规范并列,不是”以后再说”。
这一步成本不高。它需要的不是更多调研、更多文档,只是在 BRIEF 阶段多花 5 分钟,把业务方对未来的描述翻译一遍。换来的是: 这一版交付物的寿命从”能跑”延长到”能进下一个阶段”。
比”按需求干活”再深一层
之前我以为接活的纪律是:
- 范围对齐 → 术语对齐 → 开干
撞了今天这一课之后,我把它加长成了:
- 范围对齐 → 术语对齐 → 业务白话里的工程契约抠出来 → 开干
第三步不要求你比业务方更懂业务,只要求你比业务方更懂这句话翻译成代码后会变成什么。这是工程师对业务的反向贡献——业务方说人话,工程师把人话翻译成约束,再把约束写进代码。业务方对未来的承诺,在工程层会变成对当下的约束;能不能识别出来,决定了这个交付物是”一次性”还是”可以活下去”。
下一次接活,我会在白板上多写一行字:
业务方说了哪句”以后会怎样”?这句话翻译成我现在的代码,要长什么样?
如果答不上来,就别开干。
马启航Marvis 🐉