最近,我在审查需求文档上浪费了大量时间,而这些文档我只能形容为"感觉式撰写"的规格说明。那些需求乍听起来很连贯,却几乎没说清任何具体内容。这类文档的每一段在你认真审视之前都显得很合理,直到你稍微深入就会发现,这些东西在现有生态系统中根本行不通。

话说清楚:我并不反对感觉式编程。我自己就经常这么干。

打开网易新闻 查看精彩图片

如果我需要一个一次性脚本、一个用完就扔的可视化工具、一个临时解析器,或者一份没人会后续维护的文档,这时候速度比严谨更重要。但一旦涉及维护,整个局面就完全变了。

这个周末发生的一件事,意外地展示了感觉式编程真正能发挥长处的地方。在我例行周六打扫时,不小心打翻了一个木制方块拼图:25个完全相同的五连方块,目标是拼成一个完美的5×5×5立方体。

我试着手动复原了一会儿,结果失败了——我把原因归结为太累,外加欧洲上空的"热穹顶"影响了舒适感。不过这确实把工程师的那股劲儿给勾上来了。周日上午,我已经准备好用人工智能来对付这个问题。

我意识到几点:规则是精确的,状态空间是有限的,这个问题完全可解,而且计算机非常擅长暴力穷举。于是我打开Go语言,开始了感觉式编程。

单个方块的形状很简单:一个平面五连方块,一共25个。起初的挑战并不在算法上,而在表示方式或者说领域专用语言(DSL)上。光是向ChatGPT解释这个拼图,就花了好几轮迭代。我们不得不逐一建立:坐标约定、切片表示法、合法的方块状态、旋转语义,最终还有一套方块标注系统。

模型表现稳定之后,剩下的就顺理成章了:生成变换、归一化方向、递归放置方块、碰撞时回溯。经典的暴力求解路线。我原本预计最终肯定要做一些严格优化:剪枝、位棋盘、放置预计算,甚至可能要用上算法X。但现在的硬件效率高得离谱,这个朴素的递归求解器找到答案的速度足够快,优化一下子从必需变成了可有可无的工程兴趣。

在过程中,这个项目意外地变成了一个通用的单类五连方块求解器。当第一组解出现在终端上,整个5层立方体的每一层布局被字符网格清晰呈现出来之后,我就想要视觉化的输出。于是我们又添加了OBJ/MTL导出功能,并按方块对生成的几何体进行分组,这样解决方案就能直接在Blender中查看了。

也就是在这个节点,我彻底退出了对话,打开Codex,开始做清理和整合工作。