上周我说,我还在找一个答案。现在有了一个,只是比我希望的小,比我怕的大。
先把问题再摆一遍,给跳过上一篇的人。当工具几秒钟就干完我花了十年才学会的事,哪一部分才算我?
我从列清单开始。工程师焦虑的时候就会列清单。
第一栏:那些被秒杀的十年
第一栏是我花了很多年学会、如今模型做得和我一样好甚至更好的东西。这一栏比我想要的长。
十几种语言的语法,大多已经小众(汇编、Fortran、Prolog)。让链接器闭嘴的那句精确咒语。我像背电话号码一样背下来的 API 接口。样板代码,多到离谱的样板代码。
我为这些骄傲过。其中一部分还付了一套房子的钱。
但很多最后被证明只是查找。非常快的查找,加上挑得准的品味,但仍然是查找。这就是"比我希望的小"的那部分。它扎人,比我想的更疼。
第二栏:说不出口的那部分
第二栏花的时间更长,因为里面的东西更难命名。
在任何人写下一行代码之前,知道哪个问题值得解。看着一张干净、自信的架构图,感觉哪里不对,却说不出哪里不对。问出会上没人问的那个问题。知道正确答案是"别做"。这些都没法写成一条规则。
这就是"比我怕的大"的那部分。
大学时我读维特根斯坦,他花了大量时间在一个听起来很蠢、但越想越不蠢的问题上:你怎么知道如何遵循一条规则?不是规则本身,是它的应用。没有哪条规则告诉你它什么时候适用。你需要另一条规则来说明,然后那条又需要一条,最后你会落到某个根本不是规则的东西上。是实践,是判断,是当查找免费之后剩下的东西。
我觉得那就是我的部分。它同时也很不方便——它没法放进一页幻灯片。
凌晨两点的那只虫子
那我是怎么分这两栏的?主要靠回忆一个老 bug。
多年前我在摩托罗拉做视频点播。我们有个系统会跑得好好的,然后倒下。不是一台服务器,是整个系统,连锁式地倒。重启,恢复正常,然后又不行了。我们按时间、负载、内容、月相找规律,什么都没有。
后来我注意到一件小事。故障总是从一次突发流量里的第九个请求开始。不是第八个,不是第十个,是第九个。
我不知道这为什么重要,盯着它看了久到我不想承认。然后我想起来,我们的服务器有八个核。第九个请求是第一个必须等待的请求,第一个被阻塞的请求。
这把我们引向了锁,具体说是 Java 里的公平锁与非公平锁。公平锁按到达顺序服务等待的线程,非公平锁允许新来的插队。这意味着第九个请求会一直阻塞到那波流量清空,而到那时它已经超时了。
关键在于:今天的模型能把公平锁和非公平锁解释得比我好。把锁指给它,它大概午饭前就能修好。我不太确定的是,它能不能注意到那个"九"。这个数字不在任何一条日志里,它是横跨几十次崩溃的模式,而它的含义藏在一份从未被写下来的硬件规格里。也许未来的模型能发现它。即便如此,也得有人决定,第九个请求值得盯一盯。
那个"盯",就是第二栏。它也是我低估了四十五年的部分,因为它从来不出现在代码行数里。
一个不太舒服的测试
我最后落到一个可用的区分标准:如果我能把它写成一条规则,它属于第一栏,或者很快会属于。如果我只能用例子展示它,它属于第二栏。
这个测试不让人舒服。它意味着两栏不是固定的,东西会迁移。每当有人把一块判断写得足够清楚,它就往左移。代码评审的启发式、架构模式、安全清单,都是这样。这就是我上次写的那种失落感,它不会消失。
但迁移有个地板。你写下的每条规则,都需要有人决定它什么时候适用。维特根斯坦的回归不会终结于一条更好的规则,它终结于实践,而不是又一条规则。
如果第二栏才是我的部分,那我大概应该刻意去投资它。目前做了四件事。
- 我把智能体的输出当教学案例来审,而不是当苦差事。它错的时候,我问自己是怎么知道的。一半时候答案是我有它没有的上下文,另一半时候答案很有意思。
- 我记下那些"差点出事"。不是记规则,是记故事。故事承载判断的方式是清单做不到的。我当年学东西也大多是这样,通常是某个年长的人讲 1987 年出了什么岔子。
- 我让新人和失败配对,而不是和教程配对。教程教的是第一栏,而模型午饭前就能赢过他们。
- 我不再为"盯着看"道歉。盯着一个东西直到你知道它哪里不对,这不是慢,这就是现在的工作。可能一直都是。
回到那个浮标
上次我说,没人能抓住一个漂走的浮标,划船的人的任务是保持稳定的桨频(我给一场赛艇比赛写过计时程序,终点浮标被割断,开始往下游漂)。我要补一句:还得有人注意到浮标动了。岸上得有人说,"等等,终点不在那儿。"
那就是第二栏。模型划得很好,但它仍然不知道浮标被割断了。
所以哪一部分才算我?比我以为的少。剩下的那部分,是一直在干真正的工作、只是藏在一堆语法后面的那部分。一台机器让我看清这一点,我有点不好意思。它还在那儿,我也松了口气。
就这样吧。我要去揉面团了。第二栏的东西,往往就是在那儿冒出来的。
热门跟贴