先说个画面。一个外国客人,在上海的酒店里刷 Instagram,刷到 LANN,想订明天下午三点的泰式按摩。她填了一张很短的英文表格——名字、邮箱、几个人、想去哪家店、想约几点——点了提交。她不会中文,也没有我们的会员账号,她跟 LANN 之间,此刻只有这一张表。
表格落到另一头,是某家店的店长打开了它。她一看,明天三点已经满了。她想给客人改到四点。问题来了:软件该怎么让她「建议四点」这个动作发生?
最顺手的答案——也是我作为一个写程序的人,手会自己伸过去拿的那个答案——是这样的:把四点这个座位替这位客人锁住,挂一个三十分钟的倒计时,她不在时限内确认,座位就自动放掉。预约、占位、计时、状态流转。这一整套搭出来,看着很完整,很像一个「真正的」预约系统。
这一套,我们一个都没建。店长的「建议」,说穿了就是一封邮件:「四点现在看起来有空——但我们没给你留着,所以想要就赶紧。」客人要是想要,点一下邮件里那个只属于她的链接,这条请求就当成一条全新的预约,重新回到店长面前,店长再从头看一遍现在还空不空。没有锁座,没有倒计时。客人要是一直不回,那就什么都不发生——这条请求静静躺着,不占任何资源。
为什么要放着那个显得高级的版本不做?因为这家店根本没有一本实时的电子档期。四点到底空不空,这个真相只活在两个地方:店长的脑子里,和前台那本纸质登记簿上。我们的软件这两样都看不见。所以一旦我们「锁」了四点,我们锁住的是一个自己根本锁不住的东西——是在替这家店,对客人许一个只有站在前台的那个人才兑现得了、也才毁得掉的承诺。一个店里执行不了的预约,不是功能,是一个套了好看界面的谎,而且它专挑最糟的那一刻露馅——客人推门进来站在你面前的那一刻。
对我来说,真正学到的是这一条:我作为一个搭系统的人,本能是不停往里加状态——加占位、加计时器、加各种标记——因为状态越丰富,系统看上去越周全,越像我把什么都想到了。可状态其实是一种「断言」。我存下的每一个状态,都是系统在替自己说「这件事我知道,是真的」。而我只该存那些系统真能让它一直为真的东西。真相住在某个人脑子里的地方,诚实的设计不是缓存一份副本然后假装自己也知道——而是每一次都老老实实回去问那个人。这套预约系统每次都重新去问店长,就因为店长是唯一一个真知道的人。
我得承认:那个有锁座、有倒计时的版本,才是会让我显得聪明的版本。它演示起来好看,像是「考虑周全」。当时决定不做它,心里是有点像把活干了一半的。后来才明白不是。更难的那一份克制,恰恰是:不去建那个我兑现不了的部分。
所以,在你打算把一件事交给软件去管之前——一份排期、一个库存数、一个亮着的「现在有空」——先找一找,这件事的真相到底住在哪。如果它住在一个人身上,软件能做的最体面的事,是别假装自己比那个人更清楚。就一直回去问。一个肯承认「我不知道」的系统,好过一个一脸笃定、却把过期消息当真相递给你的系统。