QIAOPANG.COM · 陈天(TYR CHEN)2013–2026 精选技术与随笔文集 · 共 260 篇按时间顺序浏览(2013 → 2026)↗
程序人生 · 陈天文集QiaoPang · Systems, Craft & Agentic Era
时间轴 ↗

程序员和拉条子

程序员和拉条子

做拉条子是个苦力活,能把拉条子做好的程序员,写程序也不会差到哪里。

定谱

在做之前,你要么手边有本菜谱,要么心中有谱。你「看得见」,「闻得着」还未成形的美食:色泽如何,汤汁几成 —— 仿佛她们就在嘴边,向你招手;写程序前,你的谱就是你的设计,你清晰地知道 goals / non-goals,知道完工那一刻程序的模样。读菜谱是个苦力活,你要了解谱者的意图,知道所需的工具,材料,谋划行事的顺序,确保执行时一气呵成;设计也是个苦力活,你一遍遍在纸上模拟,在胸中演算,这样到了真正写作的时候才能「手之所触,肩之所倚,足之所履,膝之所踦,砉然向然,奏刀騞然,莫不中音」。

备料

做拉条子的材料很繁琐:面条需要靠面粉和水来配;配菜有:西红柿,青椒,洋葱,胡萝卜;小料有姜,蒜和葡萄干;佐料自然少不了油盐酱醋。这些东西都是别人做好提供给你,即插即用,否则做个拉条子还得自己种麦子磨面粉,这日子便没法过了;写程序也一样,讲究生态圈,一个程序员再牛逼,没有各种库的支持,原材料不够齐备,也无法多快好省地写代码。

在备料的时候,你需要考虑工期。客户在那嗷嗷待哺,你可不能窝在厨房里研究材料研究个三五小时。此时,即便你是个制面大师,也得收敛和面的冲动,去超市买上一把品相不错的手擀面。拉条界的人精明果敢,眼睛紧盯着目标如何完成,所以喜欢现成的材料;而程序界的人一根筋,总觉得自己最牛逼,动不动就傲骨侧漏,跟自己较劲:没有洋葱(库)就自己种,或者手边即使有洋葱,但嫌洋葱卖相不好,也非要自己重新整一个,美其名曰:reinvent the wheels。所以做过拉条子的过来人,写程序时会考虑集成第三方工具,绝对不会什么都自己做。

当然,不是什么时候都有手擀面卖的,这时你不得不自己去做,但做有两种做法:鱼和渔。前者考虑当下,解决具体问题,全手工和面和拉面;后者着眼未来,买个和面机和压面机,按照功能说明使用即可,一劳永逸。写程序也是如此,你要考虑是特殊问题特殊处理呢,还是特殊问题抽象化,制造出(购买)解决这类问题的机器处理呢?to build,or not to build,this is a question。

开工

料备齐了,接下来是开工干活。做拉条子,就是把手擀面化作热腾腾的面条,各种材料制出香喷喷的配菜,然后二者混合的伟大过程。整个过程从材料到成品,需要一系列的转换(transformation);而写程序,是完成一个系统,把输入经过一系列的转换,化作输出。

我们看:切菜是个 map 的过程,一根根胡萝卜,一颗颗青椒,被一个叫「滚刀」,或者「推刀」的工序 map 成一堆堆胡萝卜丁,或者青椒丝,随即它们和 map 成丝的牛肉块洋葱,map 成块的西红柿一起,先后入锅,接受 reduce 的过程。

嗯,炒菜是个 reduce 的过程。一份份材料或单独,或组合,被一个叫「翻炒」或者「爆炒」或者「焖炖」的工序 reduce 成一个个半成品,最后这些半成品们,再被 transduce 成配菜,和煮好的面条一起,被 flatMap 成一盘盘大家喜闻乐见的拉条子。

写程序更是如此。map / filter / reduce,基本上,你 90% 的代码都在干和这相关的事。

干活不能蛮干,讲究流水线作业(pipeline),才能事半功倍:何时切菜,何时切肉,何时下油,炸花椒,入姜末洋葱,何时炒肉,何时炒青椒,何时烧水下面等等。你必不会在菜完全炒熟之后才烧水做饭:你会在灶台上,开启两个进程,一个处理炒锅,一个处理煮锅,它们有各自的流水线,但在某一点交汇(thread.join)。每个进程虽有固定的优先级(烧水的时候,炒菜是优先级最高的),但一些突发的事件(比如水开了,或者水要溢出来了)可以抢占你的处理能力。

写程序也是如此,一个程序基本上就是一个大的 pipeline 化作一系列小的 pipeline 然后不断 pipe 下去,直到 CPU 拿到一条条指令,放入自己的 pipeline 中执行。pipeline之间需要同步,你可以通过 lock,callback,CSP,actor 等等方法进行同步。

异常

干活的时候,和写程序的时候,总需要面对异常处理。萌蠢的大厨总是会把自己的手砍伤,被开水烫伤,被火烧伤,当这些异常发生时,如果不能淡定地挂起当前的进程(比如说关火),而手忙脚乱地处理,那么会产生更大的后果。写程序的时候,如果没有 let it crash(erlang)的勇气,最好乖乖地,滴水不漏地处理异常,否则异常一层层 bubble,最后给你一个毫无理由的错误,你都没法解决。

需求变更

做拉条子的时候很少会遇见烦人的需求变更。如果顾客在你菜炒了 2/3 时说:欧巴,伦家不喜欢青椒,换尖椒好不?就算对方是九五之尊的娘娘,也可顶上一句:不早说,就这么着了,爱吃不吃!

不过偶尔熊孩子会冲进厨房让你给她转陀螺。这种小的范围蔓延(scope creeping)式的需求变更会吞噬项目的进度,让拉条子出锅的时间延后。

天赋和努力

最后讲讲天赋。做拉条子不需要太多天赋,正如写程序不需要太多天赋一样。相比天赋,它们更需要努力练习,再辅以足够的思考,摸着其中的门路,也就是所谓的「道」,就可以随心所欲。就像庖丁跟文慧君所述那样:

臣之所好者,道也,进乎技矣。始臣之解牛之时,所见无非全牛者;三年之后,未尝见全牛也。方今之时,臣以神遇而不以目视,官知止而神欲行。依乎天理,批大郤,导大窾,因其固然。

MORE IN 编程语言与工程

同专栏延伸阅读

查看「编程语言与工程」全部文章 →

是时候认识 jj 了:Git 的下一个进化方向

Git 统治了版本控制二十年,但它的暂存区、脆弱的 rebase、动辄阻断的合并冲突,正在成为 AI 时代的绊脚石。jj 从底层重构了版本控制的心智模型,而且完全兼容 Git。这篇文章带你看清它为什么值得关注。

New Hope (2025–2026)5,588 字 · 12 分钟