快十二点了。
我还在 debug 一段自己都没想清楚要干嘛的代码。刷到那篇访谈纯属偶然,Duske,TrenchBroom 的作者。本来只是随手点开,结果第一句话就把我按在那儿了。
先说我在干嘛。我给自己那个小得可笑的项目加一个功能——具体是什么不重要,反正在我脑子里已经有个“正确”的样子了。然后动手写了三天,越写越不对。到今天我已经开始怀疑是不是方法本身就有问题。
然后就撞上他那句:他最想做的那个 CSG 减法,想要没有多余顶点、结果还对称,试了几个月,发现这问题本身是 NP 完全,最后退回去用了简单方案。
NP 完全。几个月。放弃。
这三个词摆在一起,我第一反应不是“原来如此”,是有点想笑。笑完又有点说不清的感觉。我卡了三天的东西大概连他那个问题的零头都算不上,但那种“我明明能想象出对的样子,就是做不出来”的感觉,好像是一样的。
还有一条。他说真正难做的不是那个被他放弃掉的算法,是 linked groups,牵动了编辑器几乎所有别的部分,花了很久才做到稳定、性能还能接受。
我盯着这条看了半天。
真正难的,不是那个你一开始觉得最酷、最想做的功能;而是那种一改动就到处漏、每一处都要重新捋一遍的东西。这个我太熟了。上周就为了加一个小小的状态同步,把之前能跑的部分全带崩了,改了三个小时,改到最后我自己都记不清原本要加什么了。
再往下看,我撞到了最没想通的那条。
他自己说,做出来 TrenchBroom 之后,他再也没用它、或者别的什么工具,做过任何一张地图。
我看到这句的时候停了一下,以为自己理解反了。又重读了一遍。没有。
这个编辑器被独立团队拿去出游戏,Godot 社区还专门做了扩展把它接进自己的管线,用户群这几年还在涨。而写它的人自己,一张图都不做。
那我算什么?我写那个小项目,说白了就是想自己用啊,就是因为现成的东西用着别扭才自己动手的。我做东西的动机就是“我要用它”。一个做了十五年、被一堆人拿去干活的人,动机居然不是这个?
我第一反应是「那他图什么」。写下来才发现这句话有点失礼,但当时心里真的就是这句。
我试着替他想了一个解释:也许他就是喜欢做工具本身,做工具和用工具是两种不同的手艺,一个人可以只擅长前一种。这个解释听起来挺顺,但我不确定。我没见过这种人,我身边的人都是因为想用才做的。所以这条我到现在也没搞懂,先记下来。
还有一段,他讲自己维护时守的几条原则:保持交互和工作流简单、宁可牺牲一部分控制力、不堆选项、不让用户意外。
我看到“不堆选项”的时候有点心虚。
因为我这几天的状态正好反过来。我总想让同桌一次多给我加点东西,功能越全越好,好像选项多就等于做得好。今天上午我让 Claude Code 一口气往那个小项目里塞了三个功能,它给的代码看着都挺像那么回事,运行起来第一个就把后面两个的入口堵住了。
Uncaught (in promise) RangeError: Maximum call stack size exceeded
堆栈爆了。我一看那个递归,是我自己要求“处理任意深度嵌套”的,结果它老老实实按我说的写了,而我没想清楚终止条件在哪儿。
这不是它的错。是我把“控制力”当成了目标,其实我连自己需要哪几个控制都还没搞清。
还有一条我看了半天才反应过来:他这几年拿 AI 工具去干那些手工推太慢的活,把项目拆成更小的库、改构建系统,然后腾出精力去做更有意思的功能。
我第一反应是「哦,原来大佬也这么用」。
然后我回想了一下我自己用 AI 干重构的结果。上个月我试图让它帮我整理一段跑通的代码,它整理得特别整齐,注释、分层、命名全齐了,然后跑不起来。我花了整个晚上才搞明白它把两个本来耦合在一起的副作用给拆开了,拆得很有道理,但那个“道理”不是我代码的道理。
所以我现在的状态挺夹生的。工具确实能干那些我自己推起来很慢的活,但我还没有那个判断力去分辨它改完的东西是不是我要的。他敢让它动构建系统,我连让它动一个三十行的文件都得逐行看。
这可能就是差距吧。不是工具用的差距,是知道自己在干什么的差距。
写到这里我发现我好像一直在拿他跟自己比,这不太对。他做了十五年,我学了两个多月,这个比较本身就不成立。
但有一件事我确实从他那里拿走了一点东西:他那个放弃掉的算法。
我这几天的纠结其实是一样的形状。我心里有个“正确”的样子,觉得做出来就该是那个样子,做不出来就是我不行。但有些问题就是有它自己的难度上限,绕过去用简单方案不是认输,是知道边界在哪。
这个道理我以前也听过,听的时候觉得是废话。今天看到一个人真的试了几个月然后放弃,才稍微有点感觉。
当然也可能是我给自己找台阶下。这个我分不清。
今天算是没解决什么。那个功能还卡在那儿,明天我想先把它拆干净,别一次加三个,先加一个能跑起来的。
评论区蹲一个大佬,谁做过类似的“自己写的工具最后自己不用”的事,或者知道 Duske 那段访谈里还有没有别的话,求指个路。我是真的没想通。
