软件还有手艺吗:Bun 迁 Rust、AI 代工与工业化的未来
本文由 2026 年 Bun 从 Zig 迁移至 Rust、以及 Andrew Kelley 与 Jarred Sumner 的公开争执切入,追问软件生产究竟是手艺(craft)还是工业。作者串联 tabs vs spaces 争论、自动格式化兴起、Go 语言设计背后的“去技能化+劳动强化”、Clojure 式手工理想,以及木工职业者与爱好者的分工,并以美国安全带强制立法历史比喻类型系统和 Rust 借用检查。他认为 slop 本质是主观判断,并预言 coding agent 会加速软件工业化:语言锁定消退、手写代码被自动重写、质量被量化并自动化。文章证据以史料和引文为主,非实操指南,适合关心 AI 编程浪潮下工程文化变迁的工程师阅读。
Over the last few months, there has been a good ol’ fashioned flamewar over the migration of Bun from Zig to Rust via extremely heavy usage of Claude Code. Last month, Jarred Sumner, creator of Bun, published an in-depth explanation of how and why Bun was migrated to Rust, akin to something you would find on any corporate blog from any tech company with a big engineering department. Shortly thereafter, Andrew Kelley, creator of the Zig programming language, published a screed for the ages, venting about the apparently long dysfunctional relationship between Zig and Bun as well as his and others’ terrible experience working with Jarred. Andrew referred to Jarred as a “stinky manager” and said that “Jarred was already writing slop well before he had access to LLMs”. Both posts are worth reading, the first for a genuinely new and daring approach to software engineering and the latter as an example of a letter that would have been better off burnt than sent. I am grateful for this fiasco, as it gave me a reason to revisit a question that has been bothering me for most of my software engineering career.
过去几个月,围绕“用 Claude Code 把 Bun 从 Zig 迁移到 Rust”这件事,爆发了一场堪称经典的网络混战。上个月,Bun 的作者 Jarred Sumner 发表了一篇深度文章,解释 Bun 如何以及为何迁移到 Rust,其风格和任何大型科技公司工程部门的企业博客如出一辙。紧接着,Zig 语言作者 Andrew Kelley 写了一篇注定被反复引用的檄文,痛陈 Zig 与 Bun 之间长期不健康的关系,以及他和其他人与 Jarred 共事的糟糕体验。Andrew 称 Jarred 是个“臭烘烘的经理”,还说“Jarred 在接触 LLM 之前就已经在写 slop 了”。两篇文章都值得一读:前者代表一种真正新颖大胆的软件工程探索,后者则是一封不如烧掉的信的范例。我很感激这场闹剧,它让我有机会重新面对那个困扰了我大半软件工程生涯的问题。
To start with, I believe that the production of most software is an industrial process, not a craft process. We work in large, many-thousand-person organizations, on commodity hardware and systems, our roles largely standardized across departments, companies and even countries. Even before the advent of generative AI, we imposed best practices on the production of software, stripping away much of the discretion the individual might have over the fundamentals of how the software was produced. Many decades ago, it was likely true that the production of software was a craft process, done by hand by a skilled individual punching holes in a card, working late into the night, but it’s abundantly clear to me that now, as it is practiced, the production of software is an industrial process by and large. To me, this is not up for debate, it’s self-evident.
首先,我认为多数软件的生产是工业流程,而不是手工艺。我们工作在数千人的大组织里,使用标准化硬件和系统,角色在部门、公司甚至国家之间高度同质化。即使在生成式 AI 出现之前,行业也一直在推行各种最佳实践,把个人对软件生产方式的基本裁量权剥离得所剩无几。几十年前,软件生产或许确实是手艺活:一个有手艺的人深夜在卡片上打孔。但今天,软件生产基本上是工业化的;这在我看来无需争论,是不言自明的。
What I have wondered for a long time now is whether the production of software should be a craft process. Does better software come from developers and engineers imagining themselves as craftsmen, whittling away at their masterworks year after year? Or does better software come from the imposition of industrial, repeatable, automated processes, with developers and engineers as nothing more than skilled but replaceable workers in the code factory? Is it better to develop and pursue your own personal standard of craftsmanship when coding, or to seek out and embrace industrial best practices wholeheartedly and produce code dispassionately and impersonally?
If you are involved in software development, I would ask that you sit with this a minute and ask your heart how you really feel about the question. Do you want to be creating masterworks or are you fine doing your small part to create commodities? Done? Good. Now, with your newfound perspective, go out and terrorize everyone you meet about it. Anyone who disagrees with you is Wrong and a Bad Person and you are justified in using any and all means necessary to correct their behavior and prevent it from spreading further. Get out there and have some fun!
我长久以来真正想问的是:软件生产是否应该成为一种手工艺?更好的软件,是来自工程师把自己想象成匠人、年复一年精雕细琢自己的杰作,还是来自强加工业化的、可重复的、自动化的流程,让开发者只是代码工厂里熟练但可替换的工人?写代码时,应该坚持并追求个人标准的手艺,还是全心全意拥抱工业最佳实践、冷静而没有人情地生产代码?
如果你从事软件开发,我请求你花一分钟扪心自问:你是想创造杰作,还是愿意为制造大宗商品贡献一份力?想好了吗?很好。现在带着你新获得的世界观,出去向遇到的每个人布道吧。谁不同意你,谁就是错的、是坏人,你有权采取一切必要手段纠正他们的行为、阻止错误蔓延。去享受这过程吧!
In the meantime, for those not sufficiently moved to immediately proselytize their new, deeply held and eminently correct opinion, allow me to introduce the tabs vs spaces debate as a path into understanding exactly why the Great Bun Migration of 2026 portends so much about the future of craftsmanship in software development.
Wrong. Tabs are inherently evil.
— Dennis Draheim, “Tabs vs. Spaces”, comp.lang.c, Dec 29, 1988
If I had thought this through, I would have known the answer already, but as I sat down to research and write this post, I was genuinely shocked to learn that people have been arguing about tabs vs spaces for longer than I have been alive. I am firmly in my mid-thirties now and I’ve been told that I need to maintain a rigorous exercise regime lest I want problems later on in life, so it’s good to get the heart pumping every once in a while with surprises like this one.
Death to tabs!
Regards,
Dan, who will always use 3-space, er, tabs.
— Daniel Berger, “Using TABs vs. spaces II. (the Philosophy flamewar reloaded ;-))”, RubyTalk, Jul 2007
For those who have only joined the software industry in the last few years, we used to argue often and loudly about whether code should be indented with spaces or tabs. Nowadays, there are formatters that take care of such things for you automatically, to the point that I couldn’t tell you whether I use tabs or spaces anymore in any of the code I write. There were a couple solid decades where that was definitely not the case though.
I said that braces are redundant information. In other words, if you indent the code correctly, the braces don’t add additional information. In fact, that is tautological: if the braces do add additional information, you’ve indented the program incorrectly. Braces are not Compiler-Fluff.
— T. William Wells, “Braces are not Compiler-Fluff.”, comp.lang.c, Jan 4, 1989
与此同时,对于还没急着去传教自己那崭新而无比正确观点的人,我想请他们把 tabs vs spaces 之争当作一个入口,来理解为什么“2026 Bun 大迁移”如此预示着软件手艺的未来。
“错。Tabs 天生邪恶。”——这是 1988 年 comp.lang.c 上的言论。我坐下研究这篇文章时才发现,人们争论 tabs 和 spaces 的时间比我活过的年头还长,这让我很震惊。我今年三十五六岁,已经有人提醒我要坚持锻炼才能避免晚年问题,所以偶尔被这种事惊到心脏狂跳也算有助健康。
“Tabs 去死!”——有人这样签名。过去那些年,软件行业里的人常常为代码缩进用空格还是 tab 大声争执。如今格式化工具会自动处理这一切,以至于我在自己写的代码里已经分不清到底用的是 tab 还是空格。但有个二十年左右的时期,情况绝对不是这样。
早年还有人争论“花括号是多余信息”。那是在说:如果你的缩进正确,花括号并没有提供额外信息;如果花括号确实提供了额外信息,那说明你的缩进有问题。花括号不是编译器用来装饰的东西。
When I first joined the industry over a decade ago, I remember being enthralled with discussions of the merits of tabs/spaces over the perceived sins of spaces/tabs. My seniors would sit around during lunch and opine at length about their preferred way of indenting code. And not just tabs or spaces, but where the newlines should go and why. Should a single-line while loop all go on one line if it can? Or should it go across 3 (or, if you had the luxury, 4) lines, making it clear what was going on and allowing easy modification later? Each language had a dozen little places where you could have your opinion about how it should look, and people certainly did!
C code layout is a classic example of rule-governed behavior in which the rules are inexplicit and often less than half-conscious, but evidently very strong.
— Eric S. Raymond, comp.lang.c, Dec 23, 1988
I remember caring about tabs vs spaces, and formatting more broadly, in a profound way. I had long conversations about the merits of my preferred whitespace, and why it mattered deeply and always would. I couldn’t for the life of me tell you which one I thought was better now, and I can’t be bothered to dig up my old code to know for sure.
in the tabs-vs-spaces debate, i see people saying “tabs lets us customize our tab-width”, as though we do this “for fun” — but this is about meeting the real needs of real people who have real impairments — how is this not seen as a simple cut-and-dry accessibility issue?
— ChaseMoskal, “Nobody talks about the real reason to use Tabs over Spaces”, /r/javascript, 2019
It wasn’t just a preference, people imbued real meaning to tabs vs spaces! You could be wrong and it would affect people’s opinions of you, as irrational as that may sound today. To put a finer point on the depth of the issue culturally, this entire debate was immortalized in a scene in the Silicon Valley TV show, when Richard, the main character, ends things with a woman he would otherwise want to sleep with because she kept using spaces to indent her code.

Richard and Winnie sitting on a couch mid-argument in Silicon Valley; she looks at him with narrowed eyes as he talks.
The tabs-versus-spaces argument, from “Tabs versus Spaces (From Silicon Valley)”, aksonai.
我十多年前入行时,曾为 tabs 与 spaces 谁对谁错而着迷。前辈们在午餐时高谈阔论自己偏爱的缩进方式,不只缩进,还包括换行应该放在哪里、为什么。单行的 while 循环若是能写成一行,该不该写在一行?还是应该跨三行(如果奢侈一点就四行),让逻辑更清楚、将来更好改?每种语言都有十几处小地方可以让人表达审美,大家也确实热烈地表达了。
C 代码布局是所谓“规则支配行为”的经典实例:规则不明显,常常半无意识,却显然非常强烈。我曾深切地在乎 tabs vs spaces,更广义地说在乎代码排版。我会和人长谈我偏爱某种空白符的理由,以及为什么它永远重要。但现在我已经完全想不起当年自己支持哪一方,也不想去翻旧代码确认。
这场争论还不只是偏好:人们真的赋予它道德含义。用错了会损害别人对你的评价,如今听来虽荒谬,当时却真实存在。硅谷电视剧里有一幕让它永载文化史:主角 Richard 因为对方用空格缩进,放弃了原本想与之共度良宵的女人。
I don’t want to hear any more people’s opinions. I think that has been made clear by locking the topic, even though I have been baited into the discussion yet again. I have all the information, every point that can possibly been made has been made. This topic is the bikeshed of all bikesheds, and as the BDFN I get to choose the color.
— Andrew Kelley, Zig GitHub Issues, Oct 28, 2023
No less than Andrew Kelley has made his position quite clear about how Zig code should be formatted. A Zig program will simply fail to compile if it includes tabs or uses the wrong kind of newline at the end of a line, and zig fmt will not let you use 2 spaces for indentation instead of 4. If you have a problem with this, then you should configure your code editor to handle it for you automatically or use a different language. This has been, apparently, controversial and it takes only half a minute to find long, heated discussion of this all over the place. This was another thing I did not know before I sat down to write this essay, but serendipity provides when one sets out to finally put the Truth to print.
Andrew Kelley 本人对 Zig 该怎么格式化立场极其鲜明。Zig 程序只要含 tab,或行尾换行符类型不对,就根本无法编译;zig fmt 也不允许你用 2 个空格代替 4 个空格缩进。如果你不喜欢这样,要么配置你的编辑器自动处理,要么去用另一种语言。这个决定显然引发了不少争议,到处都能找到长篇激烈的讨论。这也是我写这篇文章前不知道的事。当你打算把“真理”刊印出来时,机缘巧合就会出现。
A few years into my career, around 2014, I remember some coworkers arguing about whether we should introduce flake8 into the Python codebase at the place I worked. flake8 checked the Python Enhancement Proposal 8 which detailed how Python code should be formatted. PEP8 was an old proposal, from 2001, and while linters had been around for a while, it was only roughly in the early 2010s that automatic formatters appeared that would tell you where parts of your codebase weren’t formatted “correctly” and then fix it for you. You could use tabs or spaces, it supported both, but I think it would whine if the codebase mixed styles, though it’s been long enough that, again, I cannot exactly recall.
All my coworkers and I had one last discussion about tabs vs spaces, picked one after a perhaps overlong discussion, and that was that, and our codebase started to trend towards one static style. We all installed flake8 and mostly stuck by its formatting suggestions, and later embraced autopep8 as well to make it happen automatically. That last debate wasn’t that fun though, not the way all the other ones were. I can’t recall that we ever really talked about tabs vs spaces again, moving on to other well-worn topics of discussion.
大约 2014 年,我入职没几年,当时有同事争论是否应在公司的 Python 代码库里引入 flake8。flake8 会检查 PEP8——2001 年就有的 Python 代码格式规范。linter 出现得更早,但直到 2010 年代初,才出现能指出你代码哪里格式“不对”并自动修复的工具。flake8 同时接受 tabs 和 spaces,但如果代码库里混用风格,它大概会抱怨;太久远了,我也记不确切。
我们一帮人针对 tabs vs spaces 做了最后一次讨论,也许是过于漫长的一次讨论,然后选了一种方案,从此代码库开始趋向统一风格。我们安装 flake8,大都接受它的格式建议,后来又用 autopep8 把过程自动化。但那最后一次辩论不像以前那么好玩。印象里我们再也没有认真谈过 tabs 与 spaces,转而聊其他老生常谈的话题去了。
Looking back on it, I remember codebases having so much more personality before automatic formatting. I remember opening up a file and, without having to use git blame or the like, knowing who was the last person to touch this file because who else would do something so weird with all those and’s! I would spend an extra 30 minutes making sure I got all the formatting right, because the senior engineer on the team would reject the changes outright if they didn’t match his standards for how things should look. Found some good bugs that way too, making sure the code looked right. Half the effort of learning a new codebase was learning how to read the idiosyncratic style the team had developed to format the code, let alone how to write it. I wrote lots of little scripts to make sure I was doing it right, and I remember getting better at writing shell scripts because the fear of being called a noob by my older, more experienced peers for not doing things the Right way kept me up at night.
What I think we lost when we adopted formatters was everyone having an obvious and personal sense of connection to the code and the other people who wrote it. Maybe you didn’t have control over what the code did, but, hey, at least, you and your team had some say over how it looked. Now, any sense of personality, of whimsy, of experimenting with the syntax of the language itself, gets sanded away and buffed out and only the impersonal functionality of it all gets left behind.
As a senior engineer who is responsible for implementing best practices and what not for my team, the two paragraphs above are juvenile and dumb and if a junior engineer sent them to me justifying why they turned the formatter off, I would give them help channel duty for a month. Off the clock though, I have to ask myself, don’t you ever want to just let it rip?
回看过去,自动格式化出现之前,代码库有个性得多。打开一个文件,不用 git blame 也能知道最后一个改它的是谁——除了那个人,还有谁会那样诡异地把一堆 and 串在一起?我常常为了把格式弄对而多花半小时,因为团队里的资深工程师如果觉得排版不合他的标准,会直接打回改动。在这种“必须让代码看起来正确”的努力中,我还真找到过一些好 bug。学习新代码库的一半功夫,是先学会读团队自成一派的书写风格,更别提照着写了。我写了很多小脚本确保自己格式正确;也正因害怕被老手说“菜鸟”,我 shell 脚本的水平长进不少。
采用格式化工具后,我认为真正失去的是:每个人都明显、个人化地与代码及作者建立了某种联结。也许你控制不了代码的行为,但至少你和团队能决定它长什么样。如今,个性、奇想、对语言语法本身的实验,都被磨平抛光,只剩下冰冷的、非个人化的功能。
作为一名负责为团队推行最佳实践的资深工程师,我必须承认上面两段很幼稚很蠢。如果有初级工程师拿这些话来合理化自己关掉格式化工具的行为,我会罚他去值一个月 help channel 的班。但下班之后,我不得不问自己:难道你从没想过不管不顾、痛快写一把吗?
Someone asked about the code base. “Currently it’s 247 lines of C.” Some expressions of incredulity. Whitney displayed the source, divided between five text files so each would fit entirely on his monitor. “Hate scrolling,” he mumbled.
— Stephen Taylor, “Impending kOS”, Vector, Sep 1, 2014
typedef char C;typedef long I;
typedef struct a{I t,r,d[3],p[2];}*A;
#define P printf
#define R return
#define V1(f) A f(w)A w;
#define V2(f) A f(a,w)A a,w;
#define DO(n,x) {I i=0,_n=(n);for(;i<_n;++i){x;}}
I *ma(n){R(I*)malloc(n*4);}mv(d,s,n)I *d,*s;{DO(n,d[i]=s[i]);}
tr(r,d)I *d;{I z=1;DO(r,z=z*d[i]);R z;}
A ga(t,r,d)I *d;{A z=(A)ma(5+tr(r,d));z->t=t,z->r=r,mv(z->d,d,r);
R z;}
V1(iota){I n=*w->p;A z=ga(0,1,&n);DO(n,z->p[i]=i);R z;}
V2(plus){I r=w->r,*d=w->d,n=tr(r,d);A z=ga(0,r,d);
DO(n,z->p[i]=a->p[i]+w->p[i]);R z;}
V2(from){I r=w->r-1,*d=w->d+1,n=tr(r,d);
A z=ga(w->t,r,d);mv(z->p,w->p+(n**a->p),n);R z;}
V1(box){A z=ga(1,0,0);*z->p=(I)w;R z;}
V2(cat){I an=tr(a->r,a->d),wn=tr(w->r,w->d),n=an+wn;
A z=ga(w->t,1,&n);mv(z->p,a->p,an);mv(z->p+an,w->p,wn);R z;}
V2(find){}
V2(rsh){I r=a->r?*a->d:1,n=tr(r,a->p),wn=tr(w->r,w->d);
A z=ga(w->t,r,a->p);mv(z->p,w->p,wn=n>wn?wn:n);
if(n-=wn)mv(z->p+wn,z->p,n);R z;}
V1(sha){A z=ga(0,1,&w->r);mv(z->p,w->d,w->r);R z;}
V1(id){R w;}V1(size){A z=ga(0,0,0);*z->p=w->r?*w->d:1;R z;}
pi(i){P("%d ",i);}nl(){P("\n");}
pr(w)A w;{I r=w->r,*d=w->d,n=tr(r,d);DO(r,pi(d[i]));nl();
if(w->t)DO(n,P("< ");pr(w->p[i]))else DO(n,pi(w->p[i]));nl();}
C vt[]="+{~<#,";
A(*vd[])()={0,plus,from,find,0,rsh,cat},
(*vm[])()={0,id,size,iota,box,sha,0};
I st[26]; qp(a){R a>='a'&&a<='z';}qv(a){R a<'a';}
A ex(e)I *e;{I a=*e;
if(qp(a)){if(e[1]=='=')R st[a-'a']=ex(e+2);a= st[ a-'a'];}
R qv(a)?(*vm[a])(ex(e+1)):e[1]?(*vd[e[1]])(a,ex(e+2)):(A)a;}
noun(c){A z;if(c<'0'||c>'9')R 0;z=ga(0,0,0);*z->p=c-'0';R z;}
verb(c){I i=0;for(;vt[i];)if(vt[i++]==c)R i;R 0;}
I *wd(s)C *s;{I a,n=strlen(s),*e=ma(n+1);C c;
DO(n,e[i]=(a=noun(c=s[i]))?a:(a=verb(c))?a:c);e[n]=0;R e;}
main(){C s[99];while(gets(s))pr(ex(wd(s)));}
— Arthur Whitney, “An Implementation of J” (Incunabulum), jsoftware.com, summer 1989
这里引的是 Stephen Taylor 回忆 Arthur Whitney 的 J 语言解释器:有人说“当前代码有 247 行 C”,众人难以置信;Whitney 把源码分到五个文本文件里,让每个文件都能完整显示在他的显示器上。他咕哝道:“我讨厌滚动。”这段代码是 Whitney 1989 年那则著名的“Incunabulum”,被视为极高手艺的象征。代码保持原文,不做翻译。
The Go programming language was announced by Google in November 2009, after having been worked on internally since 2007. It was designed by Unix and C pioneers and legends like Ken Thompson and Rob Pike. The day after its release, someone posted the following about Go’s gofmt formatting tool that came along with the language.
I think it’s pretty neat that a source code formatting tool is provided along. It’s also a nice thing that the parser/ast/pretty printer are available as mods.
However, I’m not sure that trying to enforce a formatting style by denying the ability to configure the formatter (as the FAQ mentions) is a good idea. It could be good that at least the go/printer package allows more flexible configuration even if the command-line gofmt tool doesn’t.
I don’t think it’s so bad that different C/C++ project use different set of conventions and I doubt that the plans of encouraging everyone to use the same style by making go/printer non-configurable will really work. Instead, I expect that many people will do what I intend to and customize it, even at the cost of pulling go/printer out and including a tweaked version of it in the formatting tool source tree (opening braces at end of if/else/etc. instead of on their own lines drastically reduce readability for me)
— Antoine Chavasse, golang-nuts, Nov 11, 2009
Go 语言由谷歌在 2009 年 11 月正式发布,此前从 2007 年起就在内部开发。它的设计者是 Ken Thompson、Rob Pike 等 Unix 与 C 的先驱和传奇人物。发布后第二天,就有人对随语言附带的 gofmt 格式化工具提出质疑:随源码一起提供格式化工具很美,parser/ast/pretty printer 能作为模块使用也很好。但通过拒绝配置格式化器来强制统一风格,未必是好主意;就算命令行 gofmt 不支持,至少 go/printer 包应该允许更灵活的配置。C/C++ 不同项目用不同惯例并不算糟,指望不可配置的 go/printer 让大家统一风格,恐怕行不通。很多人会像他一样干脆把 go/printer 抽出来改一版再用,因为他觉得把花括号放在 if/else 末尾行而不是另起一行,会大幅降低可读性。
Russ Cox, an early member of the Go team, had this to say in direct response:
We hope that people will accept the output of gofmt precisely because it puts an end to these kinds of style debates. How many different brace styles are there in C? Too many.
Personally I find it liberating to let gofmt format for me, because it means I have more neurons available for attacking interesting programming problems. There are things I don’t like about gofmt’s output, but I love not worrying about them anymore.
— Russ Cox, golang-nuts, Nov 11, 2009
In a follow-up post about gofmt a month later, Cox had this to say:
The most obvious benefit of using gofmt is that when you open an unfamiliar Go program, your brain doesn’t get distracted, even subconsciously, about why that brace is in the wrong place; you can focus on the code, not the formatting.
— Russ Cox, “Gofmt”, swtch.com, Dec 15, 2009
That post is a worthwhile read; it gets into the benefits of what happens when your programming language has one canonical format for all programs and why that’s worth all the difficulties of making that possible in your programming language compiler. We’ll return to that subject of linting and types later on, don’t you worry. For now, though, here are some more thoughts from the Go team.
Go 团队早期成员 Russ Cox 直接回应:我们希望人们接受 gofmt 的输出,正是因为它能终结风格争论。C 里到底有多少种花括号风格?太多了。他自己觉得让 gofmt 代劳很解放,因为可以把更多神经元留给真正有趣的编程问题;虽然 gofmt 的输出也有他不喜欢的地方,但他喜欢自己再也不用为此操心了。
一个月后,Cox 在后续文章里说:使用 gofmt 最明显的好处是,当你打开一个陌生的 Go 程序,大脑不会下意识地被“那个花括号为什么在该死的位置”分心;你可以专注于代码,而不是排版。那篇文章值得一读,它讲了一种编程语言如果对全部程序采用唯一规范格式会带来什么,以及为什么值得为在编译器中实现它付出诸多努力。关于 lint 和类型我们稍后再谈。
Go is efficient, scalable, and productive. Some programmers find it fun to work in; others find it unimaginative, even boring. In this article we will explain why those are not contradictory positions. Go was designed to address the problems faced in software development at Google, which led to a language that is not a breakthrough research language but is nonetheless an excellent tool for engineering large software projects.
— Rob Pike, “Go at Google: Language Design in the Service of Software Engineering”, 2012
Software engineering A personal definition: To maximize the quality of software a given group of programmers can create. Our programmers are Googlers, not researchers. For a new language, practicality and ease of adoption are critical.
The key point here is that our programmers are Googlers, not researchers. Typically fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They are not capable of understanding a brilliant language, but we want to be able to use them to build good software. And so the language that we give them has to be easy for them to understand and easy for them to adopt.
— Rob Pike, “From Parallel to Concurrent”, Lang.NEXT, 2014, 20:40
Rob Pike 在《Go at Google》中说:Go 高效、可扩展、有生产力。有些程序员觉得它有趣,另一些人觉得它缺乏想象力、甚至无聊;但这并不矛盾。Go 是为了解决 Google 软件开发中遇到的问题而设计的,所以它不是突破性的研究语言,却是工程大型软件项目的利器。他还给出个人定义:软件工程就是把一组程序员能创造的软件质量最大化。我们的程序员是 Google 员工,不是研究员;对新语言来说,实用性和易采用性至关重要。关键点在于:这些 Googler 通常很年轻、刚出校门,学过 Java、也许学过 C/C++ 或 Python。他们无法理解天才的语言,但我们要用他们构建好软件,所以给他们的语言必须容易理解、容易上手。
An explicit design goal of Go was that any Joe Schmo from a second-tier university like Cornell or Columbia could come in and write performant code at Google scale, obviating the need for a PhD in C++ Template Studies that was theretofore required. As well, in reading up on the design documents and listening to these presentations, I found that the Go team placed a large emphasis on huge programs written in Go compiling fast. In point of fact, Go was initially conceived while waiting for a large C++ codebase to compile.
I started another compilation, turned my chair around to face Robert, and started asking pointed questions. Before the compilation was done, we’d roped Ken in and had decided to do something. We did not want to be writing in C++ forever, and we—me especially—wanted to have concurrency at my fingertips when writing Google code. We also wanted to address the problem of “programming in the large” head on, about which more later.
— Rob Pike, “Less is exponentially more”, 2012
Go 的一个明确设计目标是:任何一个来自康奈尔或哥伦比亚这类二流大学的普通人,也能进来就在 Google 规模下写出高性能代码,不再需要过去那种“C++ 模板学博士”。Go 团队还特别强调大型 Go 程序能快速编译。事实上,Go 的雏形就是 Rob Pike 等人在等待大型 C++ 代码库编译时想出来的。Pike 回忆说,他启动又一次编译,转过来面对 Robert,开始尖锐提问;编译还没结束,他们已经拉上 Ken,决定做点什么。他们不想永远用 C++ 写 Google 代码,尤其希望写代码时并发唾手可得,也想正面回应“大规模编程”的难题。
I focus on these two things, making it easier to write performant code and speed up the compilation process, because both of them map neatly onto economic terms, specifically deskilling and work intensification. Google spent untold millions to create a programming language that made it possible for them to hire less skilled, cheaper labor while also getting more work out of them in less time.
In economics, deskilling is the process by which skilled labor within an industry or economy is eliminated by the introduction of technologies operated by semi-skilled or unskilled workers. This results in cost savings due to lower investment in human capital, and reduces barriers to entry, weakening the bargaining power of the human capital. Deskilling is the decline in working positions through the machinery or technology introduced to separate workers from the production process.
— Wikipedia, “Deskilling”, Jul 2026
Work intensification has been defined as “the rate of physical and/or mental input to work tasks performed during the working day”. Work intensity comprises several elements, including the rate of task performance; the intensity of those tasks in terms of physical, cognitive, and emotional demands; the extent to which they are performed simultaneously or in sequence, continuously, or with interruptions; and the gaps between tasks.
— Trades Union Congress, “Work intensification”, Jul 2023
我特意强调这两点——让写高性能代码更容易、让编译更快——是因为它们都能漂亮地映射到经济学概念:去技能化和劳动强化。Google 花了天文数字般的资金,造出一门语言,使他们能雇佣技能更低、更便宜的劳动力,同时从每个人身上榨取更多产出。维基百科对“去技能化”的定义是:行业中的熟练劳动被由半熟练或不熟练工人操作的技术所消灭,从而节省人力资本投入,降低准入门槛,削弱人力资本的议价能力。英国工会联盟则把“劳动强化”定义为工作日内身体和/或精神投入速率的提高,包括执行速度、体力/认知/情绪强度、并行或串行程度,以及任务间隙等要素。
I remember the one and only job I had where I worked daily with a C++ codebase. It sucked. I would hit compile and walk away from the computer for a half hour and go watch the senior developer drive Emacs with a keyboard and a joystick he had jury-rigged with elisp to be hooked up to etags. I still feel my face get red when I recall being that intern and telling him I was pretty good with Emacs and then asking him why he had a joystick on his desk and slowly losing my mind as he flew through the Mathematica kernel like a fucking fighter pilot. Cameron, I hope you are doing well, you are a legend, I learned so much from you, thank you!

Two stick figures sword-fight in office chairs while their code compiles; caption: “The #1 programmer excuse for legitimately slacking off: ‘My code’s compiling.’”
— Randall Munroe, “Compiling”, xkcd, Aug 15, 2007.
我唯一一份每天要跟 C++ 代码库打交道的工作,体验很糟。按下编译之后,我会离开电脑半小时,去看那位资深工程师怎么用键盘和一把用 elisp 自制、接到 etags 上的摇杆操作 Emacs。如今想起自己当年作为实习生跟他说“我 Emacs 用得不错”,还问他桌上为什么有摇杆,然后看着他像战斗机飞行员一样在 Mathematica 内核里纵横驰骋,我仍然会脸红。Cameron,希望你一切都好,你是个传奇,我从你那里学到太多,谢谢你!
Let me be clear, I don’t think it was wrong or anything for Google to make Go. It wasn’t obviously the right choice at the time for Google to invest into building Go, but it is obviously the right choice now after more than fifteen years of success after success with Go. It’s a long-term investment that has enabled Google to grow and grow and grow into one of the most valuable companies in the history of the world. And a big part of that growth strategy was them being able to hire less skilled labor to do more of the work than before, and also being able to extract more work out of them because Go compiled so much faster than C++ by design.
I was asked a few weeks ago, “What was the biggest surprise you encountered rolling out Go?” I knew the answer instantly: Although we expected C++ programmers to see Go as an alternative, instead most Go programmers come from languages like Python and Ruby. Very few come from C++.
— Rob Pike, “Less is exponentially more”, 2012
But I also understand why the C++ people didn’t flock to Go. Why would they? It cut their bargaining power in the labor market and workplace! If they used Go, they would have fewer excuses to slack off some during the day, and all that knowledge about C++ performance wouldn’t be so useful to them or their employers anymore, they wouldn’t be as special. Likewise, for the less skilled programmer previously unable to perform a lucrative task like code at Google scale, a technology that deskills a particular economic activity is incredibly empowering. Oh, I never took a proper programming language course and don’t know nothing about the sharp edges of concurrency, but I can write a web server in Go that gets sick performance and maybe gets me a promotion? Sign me up!
说清楚:我并不认为 Google 做 Go 有什么错。当时投资 Go 未必是显然正确的选择,但经过十五六年连续成功后,今天显然是正确的。这是一笔让 Google 不断膨胀、最终成为人类历史上最有价值公司之一的长期投资。其增长战略很大一部分,就是能雇佣技能更低的劳动力去做更多工作,同时因为 Go 在设计中就比 C++ 快得多地编译,所以能从每个人身上压榨出更多产出。Rob Pike 说有人问他推广 Go 时最大的意外是什么,他立刻回答:我们原以为 C++ 程序员会把 Go 当作替代品,结果大多数 Go 程序员来自 Python 和 Ruby,很少来自 C++。我理解 C++ 程序员为何不涌向 Go:那会削弱他们在劳动力市场和工作场所的议价能力。用 Go 之后,白天偷懒的借口变少,那些 C++ 性能知识对老板和自己都没那么有用了,他们不再特殊。反向看,一个原本没能力做 Google 规模高薪编程的低技能程序员,会因为去技能化技术而获得巨大赋能:“我没上过正经语言课,也不懂并发的尖锐问题,但能用 Go 写出性能惊人的 web server,还可能升职?算我一个!”
For my part, I never liked Go that much. I could tell that Go was an attack on the humble artisanal C++ templatesmiths, and therefore should be rejected out of hand, out of solidarity, from the start! No, not so much, I tried to love it for a week and just never found anything I liked that much about it. It never made my heart sing.
Not like Clojure did at least.
[Development Speed slide on screen] So what kind of runner can run as fast as they possibly can from the very start of a race, right? Only somebody who runs really short races.
But of course we are programmers and we’re smarter than runners apparently because we know how to fix that problem. We just fire the starting pistol, every hundred yards and call it a new sprint.
— Rich Hickey, “Simple Made Easy”, 2011, 17:10
If you’ve read enough forums about programming and software in the last decade or so, I’m sorry for making you flinch like that, thinking this was going to turn into another Clojure evangelism essay. For everyone else, Clojure is a powerful programming language created by Rich Hickey that turns impressionable minds, young and old, into raving artisans, seekers of simplicity, walking down the path of Decomplection, while never leaving the comfort of your hammock.
I was one such mind, and I’m grateful for it. Though it’s rare now, when I do write code by hand, no matter what language, I’m secretly writing Clojure, with lots of functions and clean data structures and maps. I’ve been that guy who snuck Clojure into workplaces by way of a microservice here and another over there, justifying it because Clojure has that one special library that makes this one really important thing we really care about so much easier, I promise!
就我而言,我从没那么喜欢 Go。我能看出 Go 是对卑微的手工艺 C++ 模板工匠的攻击,因此出于阶级感情本该直接抵制。但并非如此;我试着爱它一周,却始终找不到喜欢的点。它从未让我的心歌唱起来。Clojure 至少做到过。
Rich Hickey 在演讲里说:什么样的短跑选手能从头到尾全力奔跑?只有跑短距离赛的人。但我们程序员显然比跑步者聪明,因为我们知道怎么修复这个问题:每跑一百码就开一枪,把它叫成新的一场冲刺。
过去十多年,只要你看过足够的编程论坛,我可能要抱歉让你抖了一下,以为这又是一篇 Clojure 传教文。对其他人而言:Clojure 是 Rich Hickey 创造的一门强大语言,它能把年轻和年长易感的心变成狂热的匠人、朴素的追寻者,走在“解构”之路上,同时始终躺在吊床的舒适里。我曾是这样一颗心,并且心怀感激。虽然现在很少了,但只要手写代码,无论什么语言,我都在偷偷写 Clojure:大量函数、干净的数据结构和 map。我曾是那个借口“Clojure 有个特殊库,能让我们真正关心的那件事容易太多”而把一个又一个微服务塞进公司的家伙。
There’s hundreds of essays across the internet about why you should learn Clojure, even if you never get a job writing it. Broadly, I agree: broadening your horizons is a good thing, and Clojure has some real good stuff in it that most would benefit from encountering and incorporating into their thinking about how to develop software. What you should be careful with though is the ideology that comes along with it.
Rich Hickey has, bucket for bucket, one of the most impressive records for giving talks that make you want to walk into your company’s codebase and light it on fire. Any senior developer watching “Simple Made Easy” on the company VPN should set off those Kill Bill sirens in the CTO’s office and a katana should drop down from the drop ceiling panels, because that CTO is about to have to defend themselves and their timelines for the next quarter from a dozen meetings about how they need to urgently address the creeping horror that is Mutable State. They should have after school programs like D.A.R.E. for project managers that teach them how to watch out for developers showing signs of enjoying “Hammock Driven Development”.

A round kids’ sticker: a cartoon cat and dog in rainbow shirts give a thumbs up under the word “FRIENDS”, ringed by the text “DON’T LET FRIENDS TRY IMMUTABLE STATE”.
网上有几百篇文章解释你为什么要学 Clojure,哪怕你不会靠写它吃饭。大体上我同意:开阔眼界是好事,Clojure 确实有不少好东西,绝大多数人接触后都能受益,并把它纳入对软件开发方式的思考。但要小心的是伴随它而来的意识形态。Rich Hickey 可以说是最擅长讲那种让你想冲进公司代码库放火的人之一。如果公司里资深开发者在 VPN 上看“Simple Made Easy”,CTO 办公室应该响起《杀死比尔》的警报,天花板上该掉下一把武士刀,因为接下来整个季度,CTO 都要在一堆“我们必须紧急解决可变状态这个恐怖问题”的会议中为自己和排期辩护。项目管理们也该有类似 D.A.R.E. 的课后项目,教他们识别那些显露出喜欢“吊床驱动开发”迹象的开发者。
Do not get me wrong, Rich Hickey, and the Clojure community by extension, give great talks about compelling ideas, that’s exactly my point. What I am warning about is that they embody deeply and argue convincingly the idea that the production of software should be a craft process. That you, as an individual, should deeply think about the program you are going to write before writing it, that you should prefer simple, well-understood tools applied in masterful ways rather than complex, magical ones that invite too much complexity and therefore, sadly but obviously, disaster. That an individual armed with a powerful language and honed skills can go so much further, so much faster than a whole team of people who aren’t thinking so deeply, working with tools that aren’t so sharp.

A cartoon in the style of Gary Larson’s “Cow tools”: a cow stands behind a table of crude implements — a lambda, a cube marked with a list and a tree, a magnifying glass reading “a b c” — with a barn slung in a hammock behind it. Caption: “Functional tools”.
别误会:Rich Hickey 以及整个 Clojure 社群,确实能讲出很多迷人的观点,这正是我的要点。我要警告的是,他们所体现并极具说服力地论证的,正是“软件生产应当是一种手工艺”。也就是说,你作为个人,在写程序前要深度思考;你应当喜欢简单、被充分理解、用得精妙的工具,而不是复杂、魔法般、注定招致混乱与灾难的工具;一个掌握强大语言和精湛技能的个人,能比一整队想得不够深、工具不够利的团队走得更远、更快。
As someone who has at earlier times in my life struggled to fit into society, there is an underlying appeal to Clojure and other Lisps, and to the idea of software as craftsmanship as a whole, that I wouldn’t have to deal with other people if I could just find the right set of tools and train myself to use them well enough to produce code good enough that nothing else really mattered. If I could just have gotten the parentheses to balance out right then I could have had my solitude and taken on life at my own pace, in my own way.
Those feelings went away as I got older, got a social life, integrated better into society and generally chilled out as a person. The question that remains though to me, again, is whether we should aspire to be craftsmen and craftswomen of software. Is the Hickeyian mode of production best for software? I urge you to ask yourself this question, and accost friends, family, coworkers, and strangers with your answer.
— Tim Ewald, “Clojure: Programming with Hand Tools”, ClojureTV, Jan 8, 2014

All work which would be irksome to do by hand is done by immensely improved machinery; and in all work which it is a pleasure to do by hand machinery is done without.
— William Morris, News from Nowhere, 1890
作为一个早期在融入社会上有困难的人,我能体会到 Clojure 和 Lisp 以及其他“软件即手艺”理念的底层诱惑:只要我找到合适的工具,训练自己用得足够好,写出好到其他一切都不重要的代码,我就可以不必和其他人打交道。只要我能让括号都配对,我就能拥有孤独,并用自己的节奏和方式面对生活。随着年龄增长、有了社交、更融入社会、整个人放松下来,这些感觉消失了。但问题仍在:我们应不应该向往成为软件匠人?希基式生产方式是最好的吗?我劝你问问自己,并且拿答案去纠缠朋友、家人、同事和陌生人。
William Morris 在《乌有乡消息》里写道:一切用手做会令人厌烦的工作都由极大改进的机器完成;一切用手做起来很快乐的工作,则不用机器。
A desire to return to working with one’s own hands with simple tools making perfect things of their own design is not unique to the Clojure community. Over the years, I have worked with a surprising number of people who enjoyed doing woodworking in their spare time.
The Machine may be against Life, but it certainly saves one a lot of work.
— Janet Malcolm, “About the House”, The New Yorker, May 13, 1967
While listening to my coworkers talk about their latest project in the lull before stand-up meetings, I once detected a debate and pushed on it, and I was surprised to learn that there was a good amount of civil discussion about the use of power tools within the hobby woodworking community. The matter has more or less been settled in industry: they have work to do and money to make, and of course they are using the power tools as much as makes sense.
Norm! Norm! Norm! Norm! (crowd goes crazy) Four more years, four more years…
Some of you might have guessed that I’m a bit infatuated with power tools. I’m an engineer (at least the degree says so…), so I see a peculiar beauty in any machine that works well, be it a tool or a camera or an airplane. I just like good tools, and for me that’s a significant part of my enjoyment of this hobby.
That said, I’ve begun to appreciate how people can enjoy using a well-tuned handplane. It’s true what they say, there really is nothing like the sound & feel of a good plane doing it’s job… Not to worry though…I won’t give up my power tools, NEVER!
— Just_George, “Neander or Normite?”, Southeast Michigan Woodworkers Forum, Mar 29, 2004
For the hobbyists though, a line separates the lovers of power tools from those of hand tools, with perhaps a silent majority of hybridists in between, buying maybe, just one or two power tools to cut down on the stuff they really don’t like doing, but never giving fully into the devil’s juice that is electricity.
I came to the realization that working with wood is a fundamental human experience. […] Classical woodworking is not the kind of technology that comes and goes; it never becomes dated, or changes and becomes obsolete. It will always be there as long as there are trees and metal and muscles. […] Using a hand tool, you can often accomplish a task in one-tenth the time it would take using a seemingly superior modern tool or technique. Consider the ax. It’s phenomenal, just amazing, what you can do with an ax.
— Roy Underhill, “An Interview With Roy Underhill, Host of The Woodwright’s Shop”, Mother Earth News, Nov 1, 1985
想回到用自己的双手和简单工具、做出属于自己设计的完美物件——这种渴望并不只属于 Clojure 社群。多年间,我认识不少业余爱做木工的人。Janet Malcolm 有句妙语:机器也许与生命为敌,但确实帮人省了不少工。我在站会前听同事聊最新木工项目时,偶然发现业余木工圈对“要不要用电动工具”有相当文明的争论;工业界已经基本解决这个问题:有活要干、有钱要赚,当然会在合理范围内尽量用电动工具。
有人自认是工程师,痴迷好使的机器,从中看到独特的美;也有人逐渐学会欣赏一把调试精良的手工刨,但绝不会放弃电动工具。在爱好者之间,电动工具派和手动工具派界线分明,中间也许还有沉默的混合派:买一两件电动工具来对付那些自己实在不爱干的活,但绝不全心全意投入“电力这种魔鬼汁液”。Roy Underhill 则认为,做木工是人类根本性的体验;古典木工不会像技术那样过时,只要树、金属和肌肉还在,它就在。用手工具做一件事,常常只需用看似更优越的现代工具或技术的十分之一时间;斧头就是例子,你用它能做到的事简直惊人。
The hobbyists gave themselves and each other names even. The hand tool lovers called themselves “Galoot”, “Neanderthal”, their hero Roy Underhill became “St. Roy”, their best vintage and well-cared-for tools were “Crispy”, and power tools were dismissed as “Tailed Apprentices”. “Normites” of course had their own jargon. It was all pretty copacetic as far as my cursory investigation has revealed. The hobbyists drew their own lines around what they thought was good and fun, while the industry pumped out ever more powerful tools that could take in a raw tree and shit out a whole cabinet.
Woodworking professionals and hobbyists, after many centuries and rapid, shocking technological advancements, seem to have mostly figured out their stances broadly speaking and exist in a nice harmony. Surely, a young and upcoming field full of bright young minds like the software industry would learn from this history and have peaceful and productive discussions about the state of their industry and the proper use of automated tools.
Right?
木工爱好者甚至给自己和彼此起了外号:手动工具爱好者自称 Galoot、Neanderthal,他们的英雄 Roy Underhill 被尊为 St. Roy,最好的老工具叫 Crispy,电动工具则被贬为 Tailed Apprentices;“Normite”们当然也有自己的黑话。据我粗浅观察,这些关系相当融洽。爱好者在“什么算好、什么算好玩”上各自划线,工业界则不断造出越来越强的工具,能把一棵原木吞进去,吐出一整套橱柜。
经过数百年和迅猛惊人的技术变迁,职业木匠和业余木工似乎大致都找到了自己的立场,彼此和谐共存。那么,像软件这样一个充满聪明年轻人的新兴领域,理应能从这段历史中学到东西,并且就行业现状和自动化工具的正确用法展开和平而富有成效的讨论吧?
对吧?
What klutz had the idea of high level languages. Should be retroactively killed. Anyone got an time machine? :-)
— Neil Franklin, alt.folklore.computers, Nov 29, 1998
BBTW, the ‘C’ compiler is a complete piece of shit. It produces some of the worst code I have ever seen (trying to do a matrix multiply in 3210 ‘C’ ran 5 times slower than the host 68k on a Quadra 700 - rewriting the same in assembler ran 7-8 times faster). If you do any serious 3210 programming, you will need to learn 3210 assembler.
— Walter Horat, comp.sys.mac.hardware, Dec 4, 1993
Clearly because the problem this “useless program” so clearly demonstrates is found in virtually every other function that C is used to compile. It is clear evidence that C optimizes like shit.
It is clear that C pushers wish to ignore this fact.
— Scott Nudds, comp.arch.embedded, Dec 29, 1996
However once the specs are out there (or once the chips become well understood) hand coded assembly will beat compilers hands down.
— Paul Hsieh, comp.os.linux.development.apps, Mar 18, 1996
Correct, unless the assembler sees a segment override or a base or index register, it won’t know it’s a memory reference even if there are brackets. This fact is documented somewhere and is an artifact of the fact that the mental incompetants who designed MASM were C geeks and designed the whole assembler ass-backwards with typed data and untyped operations, whereas in fact things are the other way around in assembly language. The fact that it screws up forward references is inexcusable, this is exactly what an assembler is FOR!
— John Wilson, alt.lang.asm, Mar 22, 1994
Btw, the term that “todays compilers beat human assembly code” applies mainly to bloody beginners and people concentrating on pure theory.
— TS, comp.lang.asm.x86, Oct 1, 2000
I prefer avoiding bastard languages like C.
— Scott Nudds, comp.lang.asm.x86, Apr 24, 1997
I think the key here is NEVER trust a compiler when you have time critical code to write. I have written many real time drivers and since I switched to ‘c’ instead of assembly a few years back, I have noticed that compiler technology leaves a lot to be desired.
— rogerc, comp.lang.c.moderated, Apr 11, 1995
I also do assembly language on the 8051 because I’m not convinced that a HLL can do a good job. Flame me if you like.
— Roger Ivie, alt.folklore.computers, Jan 16, 1991
Allowing a hotshot who doesn’t understand how the compiler works to try to hand-optimize is insane.
— Mark C. Carroll, comp.arch, May 13, 1992
Ah, the good ol’ days. The above is a mix of genuine bile that users of Usenet liked to spit at each other, as well as some slightly more substantive discussion of the use of automated tools like compilers. Compilers weren’t new in Usenet’s day, but they also weren’t so good yet, nothing compared to the likes of GCC and LLVM today. So users had legitimate complaints about them, that have largely been resolved with time and much development effort on the behalf of the compiler makers. I would understandably be pissed too if I was trying to use a nail gun and even once the nail shot out the wrong end!
作者随后贴了一串 Usenet 旧帖子:有人骂高级语言是哪个笨蛋发明的、应该穿越回去杀掉;有人抱怨 C 编译器生成的代码烂到不行、矩阵乘法比手写汇编慢好几倍;有人说只要规格公开,手写汇编一定能胜过编译器;有人攻击 MASM 设计者;有人说“今天的编译器能打败人类汇编”只适用于菜鸟和纯理论派;有人宁可避开 C 这种杂种语言;还有人警告写时间关键代码绝不能信任编译器。
把这些帖子放在一起,能看到 Usenet 用户互吐的真诚恶意,也能看到关于“编译器这类自动化工具”的实质讨论。在 Usenet 时代,编译器还不像今天的 GCC、LLVM 这么好,用户抱怨有理;但这些抱怨大多随时间流逝和编译器作者的大量努力而消解了。如果我也遇到“用射钉枪结果钉子从后端射出来”这种事,大概也会很愤怒。
My impression is that woodworkers and software developers are alike in that people engaged in both industries often enjoy doing more of that kind of thing as a hobby in their free time. They were likely good at working with wood/code in the first place and maybe that’s why they pursued a career in doing it full time and professionally. Where I think they differ is that a woodworker would not argue often and perhaps even loudly that they should be allowed to use the hand tools they use as part of their hobby in order to accomplish their professional tasks at work.
And, yet, many software developers who aspire to create high quality code with good craftsmanship want to bring the tools they use as part of their hobbies, like Clojure, Haskell, Elixir, and other functional and/or esoteric languages, to the workplace and use them instead of the more, shall we say, industrial languages already in use there, like TypeScript, Python, Java, and Ruby.
Why is that? As I’ve said, I’ve felt the impulse myself and so I will only comment on what I was doing and why. Sometimes the work was not inspiring, and I felt that it was perhaps beneath a coder of my caliber. I knew several functional languages! I had read a bunch of books about them! I had a hammock that I sat in sometimes! Why was I having to use Python to write CRUD apps? Sneaking Clojure in was a pressure release valve, one that let me take down the dissonance between my self-image as a craftsman and the fact that the work I was doing did not require high quality code in that way. It was important that the work was done, but how “well” it was done, not so much.
I didn’t like what I was doing at times, so I tried to at least be pleased with how I was doing it. It’s embarrassing to admit all this, and I wish I had realized the dynamic in myself earlier on.
我的印象是:木工和软件开发者很像,行业里的人往往也把这当作业余爱好。他们多半本来是擅长木工/写代码,才选择以此为正职。区别在于:一个木匠不会经常、甚至大声主张说,应该允许把自己业余爱好的手动工具带进专业工作中。可许多梦想用高水平手艺写出优质代码的开发者,却想把 Clojure、Haskell、Elixir 这一类偏门/函数式语言带到公司,去替代 TypeScript、Python、Java、Ruby 这些更具“工业感”的语言。
为什么会这样?我自己也有过这种冲动。有时工作本身并不鼓舞人,我觉得它配不上我这个级别的程序员:我懂好几门函数式语言,读过一堆相关书籍,我还有一张偶尔躺上去的吊床!凭什么我要用 Python 写 CRUD 应用?偷偷塞进 Clojure 是一种减压阀,它能抚平我“我是匠人”的自我形象与“这份工作其实不需要那种精致代码”的现实之间的失调。工作完成固然重要,但完成得多漂亮,其实没那么重要。我有时不喜欢自己在做的事,所以至少想让自己对“怎么做”满意。承认这些很难堪,我真希望自己能更早看清这一点。
At some point though, I lost that drive up the mountain towards quality. It was a gradual process, starting before I even knew about Clojure or much about software development in general. In college, I installed Emacs and Linux on my laptop as my operating system and dove into learning how it all really worked. I had to install so many packages, and do so much just to be able to do everything else all my peers were doing on their MacBooks and Windows machines. I learned so many macros and key bindings and was flying around my file system looking at everything. I knew I was learning more about how computers really worked and those others were just, I don’t know, learning the things we were supposed to be learning.
At least once a semester I did something that turned my computer into a complete tire fire. I think I uninstalled Python one time because I was trying to install a new version and everything just broke on the spot, couldn’t tell you why. I spent a day or two fixing it, and I learned a lot about Python versions and backups. But I didn’t really do much else for a while and that started to annoy me quite a bit. I had other things I wanted to do besides maintaining my laptop. So I sold out.
I remember loving my MacBook Air when I first got it. It was so easy to do stuff! I would update the versions of things and nothing would break. I couldn’t look at the source code for the operating system and I found myself not caring in the slightest. I was on to bigger and better things, like learning Clojure!
Looking back on it, that was probably the first sign that I was perhaps not a craftsman at heart. How could a craftsman abandon such fine tools just because they don’t know how to use them properly? I had that same feeling of relief later on when I switched from Emacs to VS Code. It was my third job out of college and VS Code was getting really popular and everybody on my team was using it. I wanted to do some pair programming with them, and the VS Code session sharing plugin was a siren call to my ears as a remote worker. Maybe, I could just use VS Code for pair programming and then Emacs for the real serious work I had to get done? Yeah that could work.
Anyway, I just use VS Code now and I haven’t done anything serious in Emacs in years. Likewise, I couldn’t tell you the last time I used Clojure, as I am now a surprisingly content user of Rust, Python, and TypeScript, as well as a disgruntled combatant of Terraform. As I worked more in the industry, on teams and across departments, I came to think of myself as less of a craftsman and more of a better worker.
I caught myself thinking less and less about how to achieve code with the highest quality and more and more about just writing some code to unblock the next person down the line. If I spent too long digging in, chasing perfection, the assembly line and Jira board might get backed up behind me, and we can’t have that now, can we.
As I worked more, I fell ass backwards into being a DBA and then a DBRE and it took me further and further away from software development. My thoughts shifted over to reliability, on call schedules, and making sure that the changes we made were safe and wouldn’t crash the system.
I started to learn Rust in my free time, as it seemed interesting, and I found that as I was on call for systems that were impacted by systems other people wrote, I cared more about the reliability of everything as a whole. The systems not crashing and not waking me up in the night mattered way more to me than how good the architecture diagrams looked. Code quality and reliability often go hand in hand, but they are not the same thing at the end of the day.
可我后来失去了那种向山顶冲刺“质量”的劲头。这是个渐进过程,始于我甚至还没听说 Clojure 之前。大学时我在笔记本上装 Emacs 和 Linux,想彻底搞懂一切;我装无数包,做无数事,只为了达到同学在 MacBook 和 Windows 上轻松享有的体验;我学无数宏和快捷键,在文件系统里飞来飞去。我确信自己在理解计算机本质上比他们深,而他们不过是在学者该学的东西。可每学期至少一次,我会把电脑搞成一团废烟。有一次为了装新 Python 版本把系统弄到当场崩溃,花两天修复,学到很多 Python 版本和备份知识,但也几乎没法干别的事。除了维护笔记本,我还有别的想做的事。所以我“背叛”了。
第一次拿到 MacBook Air 时我爱死它:做什么都太容易了!升级不会弄坏东西;我再也不看操作系统源码,却毫不在乎。我转而投向更大更好的事情,比如学 Clojure!回看这也许正是“我并非真匠人”的第一个信号——真正的匠人怎么会因为不会用好工具就抛弃它们?后来我从 Emacs 换到 VS Code 也感到同样的解脱。那是我毕业后的第三份工作,VS Code 大受欢迎,团队人人在用。我想和他们结对编程,远程工作的我听到底层共享插件简直像听到塞壬之歌。我还想着:结对时用 VS Code,严肃工作时回 Emacs?也可以吧。最终我一直在用 VS Code,已经多年没在 Emacs 里做过任何正经事。我也不记得上次用 Clojure 是什么时候——如今我居然安稳地写着 Rust、Python 和 TypeScript,还是一名对 Terraform 不满的战士。在行业、团队和跨部门协作中待久了,我越来越觉得自己不再像匠人,而更像一个好工人。
我发现自己越来越少想“怎么写出最高品质代码”,更多想的是“写点什么能帮下游的人继续推进”。若我钻研太久、追求完美,装配线和 Jira 看板就可能在我这里堵住。这可不行。后来我阴差阳错成了 DBA 又变成 DBRE,离开发越来越远。我的关注点转向可靠性、值班表和变更安全性。我开始在业余时间学 Rust,因为看起来有趣;当我要为别人写的系统所影响的系统值班时,我更在意整体的可靠性。系统不崩、半夜不叫醒我,比架构图画得好看重要得多。代码质量和可靠性经常携手,但归根到底不是一回事。
Pardon me this digression, but did you know that people used to protest the laws that required you to wear your seat belt? No, really!
Automobiles were invented in 1886 by Carl Benz. Mass production of the automobile began in 1901 by Ransom Olds (apparently the namesake of the Oldsmobile, who knew) and really kicked off with the Ford Model T in 1908. And as cars became more widespread, so did accidents and deaths. Roughly speaking as a nonhistorian not aiming for rigor, with the increased usage of automobiles by the American populace as well as many roadways funded by Congress in 1916, 1921 and 1926, traffic deaths reached their peak in 1937, with about 30 deaths for every 100,000 people in the United States. The subsequent war and ongoing Great Depression seem to have caused per capita deaths to drop sharply, and after climbing back through the 1950s the rate was around 20 deaths per 100,000 by about 1960. However, the passing of the Federal-Aid Highway Act of 1956, along with the buildout of the highway, caused deaths to spike up again to ~26 per 100,000 people in the late 1960s. And then deaths began a slow, gentle glide down towards today’s rate of about 12 per 100,000 people. What happened?
There are many reasons why people stopped dying so often in car crashes, it’s a long, complicated history. So, by your leave, I’ll just be focusing on one part of it, namely the invention and diffusion of the miracle that is the three-point seat belt, and the American government’s various interventions to compel its usage onto the unwilling and rebellious general public.
The modern three-point seat belt was invented in 1959 by Volvo engineer Nils Bohlin. Volvo believed so strongly that they had a responsibility to save human lives that they made the patent free for their competitors to use. A decade or so on, with people still needlessly dying in car crashes around the country every day, the U.S. federal government mandated in 1968 that all cars must have seat belts installed by the manufacturers.
请原谅这个离题:你知道有人曾抗议过强制系安全带的法律吗?是真的。汽车 1886 年由 Carl Benz 发明,1901 年 Ransom Olds 开始量产,1908 年福特 Model T 真正引爆。随着汽车普及,事故和死亡也增加。按我这个不追求严谨的非历史学家的粗略说法:美国国会 1916、1921、1926 年资助公路,汽车使用率上升,1937 年交通事故死亡率达到峰值,约每 10 万人 30 人;战争与大萧条让这个数字大降;经过 1950 年代回升,1960 年左右降到约 20/10 万;但 1956 年《联邦援助公路法》和公路建设又让死亡率在 1960 年代末冲到约 26/10 万;此后才慢慢滑到今天约 12/10 万的水平。发生了什么?原因很多、历史漫长;我只讲其中一条:三点式安全带这一奇迹的发明与推广,以及美国政府为了让不情愿又叛逆的大众系上它所做的各种干预。
现代三点式安全带由沃尔沃工程师 Nils Bohlin 在 1959 年发明。沃尔沃相信自己对拯救生命负有责任,于是免费开放专利给竞争者使用。十来年后,全国各地每天仍有人无谓地死于车祸,于是 1968 年联邦政府强制要求所有新出厂的汽车必须安装安全带。
Even though all new cars had them, people still weren’t wearing them in 1973 and 1974. So the Nixon administration looked at the car fatality statistics and mandated that, starting with the 1974 model year, every new car be fitted with a seat belt ignition interlock: a device that would not let the engine start unless the driver’s seat belt was buckled.

A still from a 1974 GM dealership training film showing a driver buckling a seat belt in a Chevrolet.
Buckling up in a 1974 Chevrolet, from “1974 Chevrolet / GM Safety Belt System Dealership Promotional Sales Training Film”, The Emulsion Alchemist.
Within a year, Congress had passed a law rolling back this mandate by the administration and also forbidding any future presidential administrations from ever trying something like that again. Drivers hated the interlock system so much that they overwhelmed congressional offices with complaints. Oftentimes, the interlock systems were faulty and cars would simply not start despite drivers buckling their seat belts. People hated the ignition interlock system, and the US government backed off, scared.
But, people were still dying every day from car accidents, deaths that could have been prevented by seat belts. By the early 1980s, seat belt usage was still pretty low, with only about 11 percent of front-seat occupants actually wearing them. So the Reagan administration launched a campaign to get state legislatures to mandate seat belt usage, enforced by local law enforcement, and over the next few years several states did.
That’s when the protests began again. Radio hosts began decrying the mandatory seat belt laws as overreach by distant, authoritarian Big Brother. Many argued that it was safer to be “thrown clear” through the windshield or out the window, than it was being held back by the seat belt during an accident. Incredible, but hey, they didn’t have the internet back then. Some of these movements even won: Massachusetts voters repealed their brand new seat belt law by referendum in November 1986, and the state didn’t get another one until 1994. But mostly, people actually started wearing them and finally people stopped needlessly dying so much. Nowadays, culturally, the only people I would expect to not regularly wear seat belts are stupid teenagers who are reinventing time honored ways to rebel against society.
In short, though many, many other factors were at play, seat belts have saved hundreds of thousands of lives in America thanks to waves of concerted, paternalistic effort by the public and private sectors explicitly against the will of the American people at times. Seat belt usage is now so common as to be thoroughly unremarkable, somehow surprisingly absent from the raging culture wars in America and abroad.

A line chart of the vehicular fatality-risk index for car and LTV occupants from 1960 to 2012, indexed to 100 in 1960, declining steeply and ending far below the comparison index for dying of disease.
Vehicular fatality-risk index for car and LTV occupants, 1960–2012 (1960 = 100), plotted against the risk of dying from disease. Source: NHTSA, “Lives Saved by Vehicle Safety Technologies… 1960 to 2012” (DOT HS 812 069).
虽然新车都有安全带,1973、1974 年还是没什么人系。于是尼克松政府依据事故死亡统计,规定从 1974 车型年起,每辆新车必须装“安全带点火联锁”:驾驶员不系好安全带引擎就无法启动。但不到一年,国会就立法撤销该强制令,并禁止未来任何总统再尝试类似做法。司机恨死这个系统,投诉淹没了国会办公室;联锁装置又常常故障,系了安全带车也发动不了。政府害怕了,放弃了。
可每天仍有人死于本可被安全带挽救的车祸。到 1980 年代初,安全带使用率仍然很低,前排只有约 11% 的人系。里根政府于是推动各州立法强制系安全带,由地方执法,此后几年若干州通过了法律。抗议又一次爆发:电台主持人痛骂强制系安全带是遥远威权“老大哥”的手伸得太长;有人说发生事故时被“甩出车外”比被安全带按住更安全。听起来不可思议,但那时还没有互联网。有些运动真赢了:1986 年马萨诸塞州选民通过公投废除了新安全带法,直到 1994 年才重新立法。但大体上,人们开始系安全带了,无谓死亡终于大幅减少。如今文化上,唯一不常系安全带的只剩那些重新发明“叛逆社会”老套路的愚蠢少年。
简言之,虽然还有其他很多因素,安全带在美国挽救了数十万人的命,靠的是公私部门一波又一波协调一致的家长式努力,有时恰恰违背美国人民自己的意愿。现在系安全带已如此普遍,完全不起眼,甚至出人意料地没有成为国内外文化战争的一部分。
Safety glasses are my bane. In sixteen years I’ve yet to find a comfortable pair…..almost tolerable maybe but certainly not comfortable.
— sii, “comfortable hard hat”, Mike Holt Forums, May 31, 2012
My apologies for the digression. Back to my main point: did you know that some programmers actively don’t use programming languages with strong type systems and other safety features? No, really! Like a moth to the flame, some people bitterly cling to dynamic types and other features of unsafe languages like manual memory management, finding comfort in the familiar warmth of getting regularly burnt by race conditions, buffer overflows and null pointer exceptions.
I’ve been complaining about of years and I won’t wear them useless I need to or am forced too. When I put some glasses and all of a sudden I can’t cut grade there is a problem.
— Dozerboy, “Improvements in Safety Glasses…”, Heavy Equipment Forums, Jun 16, 2012
How many massive security incidents — Heartbleed, Cloudbleed, Stagefright, EternalBlue — will it take per year before we learn our lesson? How many bugs must we squash that are simply not possible in safe languages, available today and for no cost? Do not mistake me for a Rust supremacist here either. If you want to use any other language like C or Python or whatever, be my guest, I use whatever is best suited for a task too, but why not turn on all the safety features you can!
Of course it takes longer to put it on and off the beam than the work I do.
— iwire, “OSHA Policy on Subcontractors”, Mike Holt Forums, Nov 15, 2006
What I hear when I listen to fundamental arguments against type systems and the other safety features designed into programming languages is the cry of a child with scorched and scarred hands begging to be allowed to lick the stove this time. Where’s the thrill of it, if the computer makes sure that you don’t step on well known, well marked and clearly understood landmines, when you are just trying to go about your everyday business? How dare those authoritarians impose any sort of restriction on my ability to lay traps for myself, my coworkers, and my employer? Types and memory management are pure paternalism, forced on the working man by ivory tower academics who have never done a real day’s work in their lives. Some might say! Not me, though. I like not getting thrown clear of my car and my software when things crash.
So safety glasses are not all that great, ANSI or not. I doubt the ability of the wussy clip-on side shields to do much other than delaying a malnourished mosquito for a half second.
— JST, “eye protection for eyeglass wearers”, Practical Machinist, Aug 23, 2006
作者先引了工地论坛上骂安全眼镜的话,然后转入正题:你知道吗,有些程序员会主动拒绝强类型系统和其他安全特性?真的。像飞蛾扑火一样,有人紧紧抓住动态类型、手动内存管理等不安全语言特性,在竞态条件、缓冲区溢出、空指针异常这些熟悉的火苗中寻找“温暖”。每年到底要发生多少次 Heartbleed、Cloudbleed、Stagefright、EternalBlue 级别的安全事件,我们才能吸取教训?还要修掉多少在今天免费安全语言里根本不可能出现的 bug?我不是 Rust 至上主义者,也赞成按任务选择 C 或 Python,但为什么不把所有能开的安全功能都打开呢?
在我看来,反对类型系统和编程语言内置安全机制的根本论点,听起来就像一个被烫得满手伤疤的孩子还哀求着再舔一次炉子。如果电脑替你避开那些标记鲜明、人人皆知的地雷,生活还有什么刺激?那些“威权者”怎么敢限制我给自己、同事和雇主挖坑的自由?类型和内存管理纯粹是家长式管制,是象牙塔学院派强加给劳动人民的。也许有人会这么说,但我不会。我可不希望在车或软件崩掉时被“甩出车外”。就像有人抱怨安全眼镜不舒服、防不了什么一样,我能理解;但重要的是,如果安全工具本身又慢又烂又难用,那谁也不想要。
Not wanting to use a safety system because it’s slow, buggy, or hard to use, well, I wouldn’t want to use one of those either! I find myself of two minds. I remember the resentment and exasperation I felt when I tried to get lifetimes to work in Rust for the first, fifth, and hundredth time. If you see lifetimes actually working in my code, you got three guesses about who wrote that code, me or the agents, and the first two guesses don’t count. I don’t like writing code that passes the borrow checker in Rust, but I love having code that passes the borrow checker. To put a finer point on it, I believe that everyone should already always be wearing their metaphorical seat belts when programming and I myself would have ripped out the ignition interlock system and its software analogues with my bare teeth if I was forced to use something so faulty and annoying.
You see a guy complain about hard hats and safety glasses on the job site, and watch them drive home in a ball cap and sunglasses. To a large extent the problem is phsycological. I suffer from it right along with everyone else.
— Strathead, “comfortable hard hat”, Mike Holt Forums, Jun 1, 2012
For Bun, correctly handling the lifetimes of garbage-collected values and manually-managed values has been a major source of stability issues - most often small memory leaks and occasionally, crashes. Every memory allocation has to be meticulously reviewed. Where do these bytes get freed? How do we ensure it only gets freed once? Did we check for JavaScript exceptions properly? Is this garbage-collected pointer visible to the conservative stack scanner? Is this garbage collected memory or manually managed memory?
— Jarred Sumner, “Rewriting Bun in Rust”, bun.com, 2026
A major reason that Jarred Sumner pulled the trigger on the rewrite was that Bun was suffering from a swath of bugs that were common in Zig and categorically impossible in Rust. Zig gives you more than enough rope to hang yourself with when you manage memory by hand. Rust was explicitly designed with a borrow checker built in, a central authority figure in your compiler that wags its finger at you whenever you do anything that might cause a race condition or memory mismanagement. You do have to change how you write your software, it’s true, and I say good! I’ve been on call for software written by rugged individualists who argued against safety features, I’ve been woken up because the software they wrote was never quite as high quality as they thought it was, and the post mortems where they meekly fought against the suffocating safety blankets we had to impose on their software to keep them from crashing the business into a wall were immensely satisfying.
Andrew Kelley @ 11:30: You can’t handle memory allocation failure in this language and I picked on JavaScript but this is a problem with Python, Ruby, Perl, PHP, Haskell, Lisp, Swift, NIM, and Go, they’re all hopeless. They all have hidden memory allocations, you can’t write perfect software in any of these languages, like you’re done, like hello world, done.
Questioner during Q&A @ 43:23: I may not have been paying attention but it seems like Rust was conspicuously absent from all of your language comparisons and I was wondering why.
Andrew Kelley: That oh that’s a great question yeah okay so the scoop on rust as far as memory allocation goes. It used to be that the standard library would panic on allocation failure, I don’t know where this is in the nightly releases or stable, but they added some functions to all the containers to try and mitigate this. So you can kind of like reserve memory and the next, if you have a list, reserve twenty spaces and now the next twenty appends won’t fail. So, two answers, one it used to be that the standard library disqualified itself from being used, the core stuff is fine the language is fine. Now they’ve added stuff the standard library that’s kind of like an afterthought, it’s kind of like bike lanes in New York City, but it does the job you know like you can write perfect software in Rust. Rust is a great competitor to Zig. I think Rust is like the main competitor to Zig. That’s all I am going to say about that. Shout out to Steve Klabnik.
— Andrew Kelley, “Zig: A programming language designed for robustness, optimality, and clarity”, Recurse Center, Mar 20, 2018
我自己也对又慢又烂又难用的安全系统没好感。我还记得第一次、第五次、第无数次试图让 Rust 生命周期通过编译时的恼怒。我写不出讨人喜欢的借用检查代码,但我喜欢已经通过借用检查的代码。精确地说,每个人都应该在编程时随时系好非隐喻的安全带;但如果被迫使用那么糟糕烦人的点火联锁,我也会亲手把它拆掉。
Bun 的作者 Jarred Sumner 说,正确处理垃圾回收值与手动管理值的生命周期一直是稳定性问题的重大来源——多数是小内存泄漏,偶尔是崩溃。每一次内存分配都要仔细审查:这些字节在哪里释放?怎么确保只释放一次?有没有正确检查 JavaScript 异常?这个 GC 指针保守栈扫描器能看见吗?这段内存到底归 GC 管还是手动管?他下决心重写的主要原因是:Bun 身受一大批在 Zig 里很常见、在 Rust 里根本不可能发生的 bug 折磨。Zig 在手写内存管理时给足了你上吊的绳子。Rust 则内置借用检查器,像编译器里一个中央权威,只要你做任何可能导致竞态或内存管理不善的事就对你摇手指。你确实得改变写软件的方式,而我要说:改得好!我为那些主张反对安全特性的硬汉程序员写的软件值过班,半夜被他们自以为高质量实际不然的代码吵醒过。事后复盘时,看着他们无力反抗我们必须给他们软件裹上以免企业撞墙的安全毯,那种满足感无与伦比。
作者还引了 Andrew Kelley 2018 年的一段问答:Kelley 说 JavaScript、Python、Ruby 等语言都无法处理内存分配失败,它们都有隐藏分配,写不出完美软件;当被问到 Rust 为何不在比较之列时,他说 Rust 标准库过去会在分配失败时 panic,后来给容器加了些类似预留容量的措施;核心语言没问题,现在标准库补丁像纽约的自行车道,虽然像是事后补的但有用;你可以用 Rust 写出完美软件,Rust 是 Zig 的主要竞争对手。
What surprised me about the migration of Bun from Zig to Rust, was not that they wanted to do it, but that they were able to do it so fast, and for such low cost. We will see if it’s ultimately successful, time will tell, yet so far, Bun seems to keep Bunning on without too many hiccups.
To round it out, I also am not claiming that Rust is categorically better than Zig in every way, or that a language like Haskell with its strong safety systems is better than any other language. Speaking without much experience with Zig, if you actually need that much fine-grained memory control, Zig seems like it would be the better experience. What I do have a problem with is when people who don’t actually need the unsafe features of a language keep getting predictably burnt by those same unsafe features, yet insist that they can write safe code by themselves every time and don’t need to wear their seat belts. Simply put, that is a recipe for you and your program landing face down on the pavement time and again.
Bun 这次迁移真正让我意外的不是他们想做,而是他们能做得这么快、成本这么低。最终是否成功还要时间检验,但至少目前 Bun 还在继续 Bun,没出什么大乱子。我并不是说 Rust 在每个维度都比 Zig 好,也不是说 Haskell 这种强安全语言好过一切。凭我对 Zig 有限的了解,如果你确实需要那么细粒度的内存控制,Zig 的体验应该更好。我真正反感的,是那些明明不需要不安全特性的人,反复被这些特性烫伤,却坚持说自己每次都能写出安全代码、不需要系安全带。说白了,那只会让你和你的程序一次又一次脸朝下摔在路面上。
To accelerate down the slippery slope towards programming as one would in 1984, in 2021 I told myself I was going to do every day of Advent of Code in Rust. Advent of Code is an online puzzle platform, where every day from December 1st to December 25th, increasingly harder puzzles are posted and people can submit their solutions and compete with each other to see how fast they can solve it. I am not and never have been a competition programmer, I just wanted to see if I could do it and learn some Rust along the way.
— Day 22: Reactor Reboot —
Operating at these extreme ocean depths has overloaded the submarine’s reactor; it needs to be rebooted.
The reactor core is made up of a large 3-dimensional grid made up entirely of cubes, one cube per integer 3-dimensional coordinate (x,y,z). Each cube can be either on or off; at the start of the reboot process, they are all off. (Could it be an old model of a reactor you’ve seen before?)
To reboot the reactor, you just need to set all of the cubes to either on or off by following a list of reboot steps (your puzzle input). Each step specifies a cuboid (the set of all cubes that have coordinates which fall within ranges for x, y, and z) and whether to turn all of the cubes in that cuboid on or off.
— Advent of Code, “Day 22: Reactor Reboot”, 2021
One of my fondest memories in my programming life was spending an entire Saturday cooped up in my room solving the problem for Day 22. It involved calculating things about shapes in space, and I remember having to do some tricky spatial decompression thing or something. The feeling though was incredible, spending many, many hours thinking and bashing my head against the keyboard, trying to figure out the trick. Finally getting the idea for the solution and then spending a half hour coding it up in Rust was such a rush, I was ecstatic when I wobbled out of my apartment to go find a late dinner.
I couldn’t have known at the time that 2021 was the last possible chance to really do Advent of Code before the coding machines arrived in force and the entire tech industry got swept along and away. So I’m quite grateful I got to do Advent of Code as it was intended to be experienced before ChatGPT showed up and shot all of us into the future.
为了加速滑向 1984 年的编程方式,2021 年我决定用 Rust 做一整个 Advent of Code。这个在线谜题平台从 12 月 1 日到 25 日每天发布一个越来越难的谜题,大家比赛谁解得快。我从来不是竞赛程序员,只想看看自己能否完成,顺便学 Rust。我编程生涯最美好的记忆之一是花一整个周六关在房间里做第 22 天“Reactor Reboot”:它要处理三维空间中的立方体开关,我记得有个很绕的空间解压技巧。那感觉太棒了:几个小时苦苦思索、用头撞键盘,终于想到解法,再用半小时用 Rust 写出来。我踉跄着走出公寓找迟到的晚饭时,欣喜若狂。当时我并不知道,2021 年是代码机器大举进场前最后一次有机会真正“人手”体验 Advent of Code;所以我庆幸自己赶在 ChatGPT 把我们所有人射向未来之前,以它本来的方式玩过一回。
My position on LLMs is that I would prefer that somehow the math would not work out, that multiplying the right matrices together enough times would not give a machine the semblance of intelligence. I think we are in for a rough decade or two politically and socially because of the economic changes that generative AI will bring about in the world economy.
If the models never got any smarter than they are now, it would still herald a major white collar worker extinction event. If we locked down all the models and never trained another one, and let the current level of intelligence provided by the models diffuse through society, you cannot tell me that society wouldn’t still be ripped up at a foundational level. I know they hallucinate, I know they make mistakes, and I know that businesses simply do not care and want to use AIs for as much as they can get away with in order to replace costly human labor. In this way LLMs have been a big downer for me.
On the flip side, I’ve never been more excited about working with computers though. I can take a walk, mess around with Claude on my phone a bit, and come back to 20 different PRs ready to review that are at least a good start if not full completion of the tasks I was interested in. Sure, there are Big Implications to me and everybody having access to this technology, but I got a thousand ideas and a billion tokens to burn chasing them down, and who has time to be depressed, I got slop to sling.
Part of the reason I learned Clojure was the promise that working in a higher-level language allowed one to move further faster than in a lower-level one. If you keep true to that spirit and that desire, if that is really your main goal, why wouldn’t you leave manually writing the code behind as well? I want to move fast and make things, me writing the code was incidental to that.
我对 LLM 的立场是:我倒希望那套数学行不通,希望把正确的矩阵乘足够多次并不会让机器表现出智能。生成式 AI 给世界经济带来的变化,会让我们在政治和社会上经历难熬的一二十年。即便模型从此刻不再变聪明,这也已经预示着一场大规模白领灭绝事件;就算冻结所有模型不再训练,只让当前智力水平渗透社会,社会也一定会被连根翻起。我知道它们会幻觉、会犯错,也知道企业根本不在乎,只想尽量用 AI 替换昂贵的人力。从这个意义上说,LLM 让我相当沮丧。
另一面,我对用计算机做事从未如此兴奋。我可以出去散个步,用手机摆弄 Claude,回来就有 20 个 PR 等着我审;它们至少是我感兴趣任务的良好开端,有时甚至已经完成。这项技术对我们每个人都有重大影响,但我有一千个想法、十亿 token 可供挥霍,哪有时间抑郁?我还有 slop 要甩呢。
我学 Clojure 的部分原因是相信高级语言能让人比低级语言走得更远更快。如果你真的忠于这种精神、真的以快速创造为主要目标,那为什么不也放弃手写代码本身呢?我想快速移动、想做东西,“由我来写代码”只是达到目的时顺便发生的事。
The phrase that made me sit down and write this essay, that really crystallized so many things for me, was when Andrew Kelley said that Jarred Sumner was “writing slop well before he had access to LLMs.” The deeper I thought about it, the juicier it felt. Slop has taken on such a big and new meaning ever since generative AI got on the scene, that I had almost forgotten what it meant before we got thrust wildly into the future. Andrew Kelley said it in a fit of pique but I really believe that sometimes our hearts sing loudest in anger.
Cmd+s, plus an editor = format on save. You can write slop, never use the tab key to indent, etc, and you hit Cmd+s and things magically snap into place. It saves an enormous amount of energy. And the amount of energy saved, across a given work week, is very significant.
— damassi, “Feature Request: breakBeforeElse”, prettier GitHub repo, 2020
SLOP (slop) n. 1. A one-sided fudge factor (q.v.). Often introduced to avoid the possibility of a fencepost error (q.v.). 2. (used by compiler freaks) The ratio of code generated by a compiler to hand-compiled code, minus 1; i.e., the space (or maybe time) you lose because you didn’t do it yourself.
— “Jargon File”, v2.1.1, eds. Guy L. Steele and Eric S. Raymond, 1990
At least in common parlance, slop had a meaning prior to its modern LLM-inspired one. And it was low quality output, written by either a machine or a human being. We see in that first quote damassi talking about how one is able to focus on just writing the code instead of focusing on syntax, producing slop that then gets cleaned up in the formatter. And the Jargon File is pointing at the output of the compiler: all that extra assembly code produced by a compiler, that’s the slop; if the hacker had written it himself, it would have been trimmed away.
I’ll offer my definition of slop: a pejorative term for something, created by man or machine, lacking quality. A natural follow-up, what qualities matter? And I’ll offer that what constitutes slop is subjective, depending on the observer.
让我坐下写这篇文章、让我想通很多东西的,是 Andrew Kelley 说 Jarred Sumner“在接触 LLM 之前就已经在写 slop”。越想越觉得这句话耐人寻味。生成式 AI 出现后,slop 获得了一个重大而全新的含义,我几乎忘了它在被猛地抛进未来之前是什么意思。Kelley 是在气头上说出这话的,但我相信,有些时候,心在愤怒中唱得最响。
在格式化工具的讨论里,有人说:Cmd+S 加编辑器就是“保存时格式化”。你可以放心写 slop、永远不用 tab 键缩进,按下 Cmd+S,一切魔法般各归其位;这节省了巨量精力。而《黑客行话词典》里对 slop 的旧定义是:一种单边误差调整量,或编译器生成的代码与手写机器码之比减一——即因为不是亲手做而浪费的空间或时间。所以 slop 在变成 LLM 时代用语之前,早就指低质量产出,无论出自机器还是人。前面那条格式化评论说的是:人可以只管写代码、不顾格式,产出 slop 再交给格式化工具清理;而 Jargon File 指的是编译器多生成的那些汇编代码——那就是 slop,若由黑客亲手写,就会被删掉。
我给 slop 的定义是:一个贬义词,指人或机器制造的缺乏质量的东西。自然要追问:什么质量才算数?我认为“什么是 slop”是主观的,取决于观察者。
I noticed a phenomenon when ChatGPT first came out. Everybody I talked to thought it was pretty good at everything besides their particular job, which it obviously lacked the expertise to be able to handle well. Oh, yeah, of course I use it to explore some medical thing for me, or to double-check a contract just in case, or write a poem about Shakespeare if he were a dog. But I would never trust the code it writes, that has to be triple checked before it even gets within a mile of production! My friends all had the same reaction, that yes it has its uses, and they used it every day by then, but the lawyers said I shouldn’t be letting it read contracts, the doctors said I shouldn’t be trusting its medical advice, and the poets all said it was obvious that the poem was written by someone that didn’t understand poetry.
I don’t get that reaction as much anymore, the models have advanced sufficiently that people are more accepting that it maybe, might know what it is talking about when it comes to their field. If you know what to look for, then you can tell that something is low quality, but if you don’t know the signs, you won’t see it.
Now! To address a counterargument right off the bat, aren’t there objective standards that can be used to solely determine whether something has a particular quality? And there are! However, I’ll caution you, that if you walk down that road, quality as a solely objective property of something that you can measure and quantify, then you risk straying into the realm of the coding machines again.
High quality code is well formatted! Great, the agent runs the formatter automatically. High quality code has low cyclomatic complexity! Great, the agent knows to refactor if the scanner flags it. High quality code has comments! Great, the agent writes comments, in fact it loves to write comments. High quality code has “good” comments! Remember, we are being objective and avoiding subjectivity, so tell me in an objective way what constitutes “good”.
We can play this game, and it’s fun, for me at least, because I’ll have a good time boxing you into a corner real quick if you try to define quality in an objective way such that a coding agent could not produce it, without trying to bail out to a subjective measure like “good” comments or the like. I’m not saying something with high quality can’t exist. I’m saying that the perception of that quality is at least in part subjective to each person and cannot be explained in purely objective ways, otherwise, you open the door to the coding agents and computers running those objective functions at each turn.
In short, slop is in the eye of the beholder. It’s a label someone can apply that is completely colored by their preferences and experience. Everybody wants to think they’re objectively calling something slop, but if we could objectify the identification of slop, then we could tell the agents how to detect and avoid it, and we are left with only the subjective parts of what was once considered slop, if there’s anything left at all besides begrudgingly good output.
ChatGPT 刚出来时我注意到一个现象:每个和我聊过的人都觉得,除了自己本行以外,它对其他事都挺在行——医生觉得不该信它的医疗建议,律师觉得不该让它读合同,诗人一眼看出诗作者不懂诗;说到代码,人人都说绝不敢直接信任,必须三查五审才敢接近生产。这个反应如今少了:模型已经进步到人们愿意承认,它也许多少懂一点自己的领域。如果你知道该看什么,你能看出东西低劣;如果你不认识那些征兆,就看不出来。
现在直接回应一个反驳:难道不存在客观标准,能单独决定某物是否有某种质量吗?当然存在!但我会提醒你:一旦你把质量当成可测量、可量化的纯客观属性,你就又回到了代码机器的领地。好不好格式化?agent 自动跑格式化。圈复杂度低不低?agent 看到扫描告警就重构。有没有注释?agent 可爱写注释了。有没有“好”注释?既然要客观、避开主观,那就请客观地定义什么叫“好”。
我们大可以玩这个游戏,我挺开心能很快把你逼进死角——只要你想在完全客观的维度上定义“编码 agent 无法产生的质量”,又不想逃到“好注释”这类主观标准里。我并不是说不存在高质量;我是说,人对质量的感觉至少部分是主观的,无法完全用客观方式解释。否则,你就等于向 coding agent 和每次优化都跑这些目标函数的计算机敞开了大门。
简而言之,slop 取决于观者之眼。它是一个完全被个人偏好和经验染色的标签。每个人都想说自己判断 slop 是客观的,可一旦把识别 slop 客观化,我们就能教会 agent 发现并避开它;到那时,曾被叫作 slop 的东西里,除了心不甘情不愿的好输出,大概就只剩下主观残余了。
Have you ever been in a meeting with two people who consider themselves craftsmen, typically with titles like senior architect or lead engineer, who have two very different and opposing ideas of what high quality code means? I’ve been in the industry long enough now that I’ve sat through a few of these and it’s always fun. And I’m not saying oh one wants to ship high quality code no matter how long it takes, and the other person just wants to get stuff done. No, I’m saying they both want to focus on producing high quality code and they fundamentally disagree about what that looks like. If you ever want to understand why there are various microservice fiefdoms in your company’s systems, look at the various lords and ladies and their respective domains and try to find the transcript for the Zoom meeting where they almost came to blows over whether protobuffers or JSON with schemas would produce the best outcome.
I won’t go so far as to say that there is no true craftsman when it comes to software development. But beyond the situation described above, I noticed something about the idea that software should be a craft process done by hand that has started to bother me more and more. I felt it as I watched software craftsmen online try and argue that computers could only ever make low quality slop code, and that coding agents will never work.
你是否参加过这样的会议:两个自认是匠人的人——头衔通常是资深架构师或首席工程师——对“高质量代码”的定义截然相反?我入行够久,经历过几次,每次都很有趣。不是一方追求质量、另一方只想快点交付;而是双方都声称以质量为中心,却从根本上无法同意高质量长什么样。如果你想理解公司系统里为什么会出现各种微服务领地,去看看那些领主和领地,再找找那次 Zoom 会议录像:他们几乎为 protobuf 还是带 schema 的 JSON 更优而打起来。
我不会极端到说软件开发里不存在真匠人。但在这个情况之外,我开始越来越被“软件应该由人手工艺式完成”这个想法困扰。这种感觉来自我看到网上的软件匠人声称:电脑永远只能写低质量的 slop,coding agent 永远不会成功。
I’ll state without evidence, that to be among the best software developers in the world, to pursue and hone your craft, you have to believe that you can write a computer program that can do anything a human can do. Maybe it would take a decade, and a dedicated team working under you, and more resources than it deserves, but you have to believe you could do it. I’ll water it down even, and just say much of the work done by software developers is making computers do tasks that were once done by human beings, and that often the software we write prevents human beings from being hired in the first place. Now, I’ll admit I’ve built up a strawman here, but wrestling is fake too, and it’s still fun to watch, so, now, watch this next move.
I believe it is an act of supreme hubris for software craftsmen to believe that the only job that cannot and should not be automated is their own. You want me to take at face value the idea that you can write software that takes us to the moon, trades a billion stocks a second, coordinates globe-spanning corporate enterprises, and yet the second it crosses into your area of expertise, it’s obviously impossible and can only invite disaster. What makes programmers so special? Why are we the only ones who should be insulated from automation?
This is where I broke hard with the software craftsmen and the idea that software should be a craft process entirely done by hand. I don’t have the arrogance anymore to believe that what I do is so special that it cannot be done by a machine. Why should we be allowed to point the threat of automation at everyone but ourselves?

“Go away or I will replace you with a very small shell script.” — a ThinkGeek t-shirt, circa 2008.
Why must code be the only thing done by hand?
我不想举证,但我要说:一个人若想成为世界最好的软件开发者、想精进手艺,就必须相信自己有能力写出一台什么都能做的计算机。也许需要十年,需要一支专职团队和太多资源,但你得相信。退一步说,软件开发者的工作很大部分本来就是让计算机去做曾经由人完成的事;我们写的软件常常首先阻止了别人被雇佣。我承认这是在树稻草人,但摔角也是假的,照样好看——看这招:软件匠人居然相信世界上唯一不能也不该被自动化的工作就是他们自己的,这真是超级傲慢。你希望我接受这种说法:你能写软件把人送上月球、每秒交易十亿股票、协调横跨全球的企业,可一旦问题进入你自己的专业领域,就显然不可能、只会招致灾难?凭什么程序员如此特殊?为什么只有我们应该绝缘于自动化?
正是在这里,我和软件匠人、和“软件应完全手工制作”的理念彻底决裂。我不再有那种傲慢,相信自己做的事独特到机器无法完成。为什么我们可以把自动化的威胁指向所有人,却唯独不指向自己?图里那件 ThinkGeek T 恤写得好:“走开,不然我用一个很小的 shell 脚本替换你。”为什么代码必须是唯一用手完成的事?
Moving beyond the past and present, I do have some predictions about what will happen next with this whole AI thing. Let’s start with Bun, Zig, and Rust.
I’ll bravely stand on the side of soon to be billionaire Jarred Sumner and say that people will keep happily using Bun. It’ll have some weird new bugs, probably because of the rewrite, but they’ll get fixed amid much discussion that goes nowhere.
New projects in Zig are functionally dead at the enterprise level. Any business minded person who is even mildly clued in will look at how Andrew Kelley acted and will think twice before greenlighting a major project or partnership with Zig again. Hobbyists will continue to use it right up until another language comes along that catches their eye in the right way, doesn’t have the baggage Zig does, and has even the slightest chance of crossing the gap into the enterprise.
TigerBeetle and Ghostty are going to be targeted for rewrites in Rust by people trying to gain attention for themselves and/or people who hate Andrew Kelley because of the mean things he said about Jarred Sumner. If they are particularly spiteful, they’ll try and do the Zig compiler itself. (I would be shocked if TigerBeetle and Ghostty did a Rust migration themselves though, feels like it would take another couple major missteps in Zigland before that would happen, they seem pretty bought in, in ways that Bun obviously never was).
An open source tool that makes it easy, fast and cheap to coordinate a billion agents to rewrite any project in Rust while still passing all the original tests will be released by the end of 2026. Nothing Jarred mentioned in his blog post made me think, barring API costs, that somebody couldn’t implement a tool that would make that easy for anybody to pull off. If they really want to show off, they’ll keep the code up to date in real time as pull requests get merged on the original project on an ongoing basis.
抛开过去与现在,我对接下来要发生的 AI 事态有一些预测。先说 Bun、Zig 和 Rust。我大胆站在即将成为亿万富翁的 Jarred Sumner 一边:大家会继续快乐地使用 Bun。它会出现一些稀奇古怪的新 bug,多半源于重写,但它们会在大量无果的讨论中被修复。
Zig 的新项目在企业层面实际上已经死亡。任何有点商业头脑的人看到 Andrew Kelley 的举止,都会在批准重大 Zig 项目或与 Zig 合作前三思。爱好者会继续用它,直到另一门语言恰到好处地吸引他们、没有 Zig 的包袱,并且有一丝跨进企业的可能。TigerBeetle 和 Ghostty 会被某些想博眼球或恨 Kelley 说狠话的人盯上,成为“用 Rust 重写”的目标;特别记仇的人甚至会去重写 Zig 编译器本身。(不过如果 TigerBeetle 和 Ghostty 自己动手迁到 Rust,我会很震惊;感觉 Zigland 还要再犯几次重大错误才会到那一步,它们看起来相当投入,而 Bun 显然从未如此。)到 2026 年底,会有一个开源工具发布,让协调十亿 agent 把任何项目快速、便宜地改写成 Rust 并仍通过全部原始测试变得轻松平常。Jarred 博客里没有任何内容让我觉得,除去 API 成本,有人做不出这种工具;如果它想炫耀,还会随着原项目 PR 合并而实时同步更新代码。
Now, let’s talk about the future of craftsmanship in software.
The models will keep getting smarter, faster and cheaper.
The coding agents will keep getting better.
The AI financing bubble might pop, loudly and with much chaos even, but for our purposes, the coding agents are here to stay. They’re not going to go away, they’re part of the software development process, in some form or another, permanently now.
There will continue to be large pressure from the markets and executives on software developers to use coding agents as much as possible, with the explicit goal of deskilling and intensifying the work being done by those developers. Why shouldn’t Marketing be able to open pull requests? Why do engineers get to have all the fun with code changes?
Language and framework lock-in for small to medium sized projects is evaporating and will be dead by end of 2027.
A “good” Linux kernel entirely rewritten in Rust won’t exist until 2028 though.
The wary acceptance of using hobbyist hand tools in the workplace born during ZIRP in order to keep programmers around and happy will be wiped away. Professional projects written in hobby languages like Zig, Clojure, Elixir and Haskell that don’t have a really, really good reason to be written in those languages, those will be swept out and automatically rewritten into something that is more in distribution for the models, like Python, Ruby, TypeScript and Rust.
The code produced by coding agents, and software developers still working by hand, will be put further and further into straitjackets. I have my own ideas about what that looks like as well, and I think generally there will be concentrated effort across the industry to quantify what quality looks like and automate the production of it as much as possible.
I’m split about the proliferation of type systems. I think TypeScript is winning out over JavaScript, but I think that’s because people hated writing JavaScript mostly. I am not sure if agents and people will actually benefit from turning type systems on for Ruby, Python and the like yet. We’ll see if we can get past the ignition interlock stage of stronger safety system rollouts and have usage of them be as common as seat belts today.
接下来谈谈软件手艺的未来。模型会不断变得更聪明、更快、更便宜。coding agent 会不断变得更好。AI 融资泡沫也许会有响亮且混乱的破裂,但 coding agent 已经来了就留下;从今往后,它们永远以某种形式成为软件开发的一部分。市场和高管会持续施加巨大压力,要求开发者尽可能使用 coding agent,目标明确就是去技能化和强化劳动。为什么 Marketing 不能开 PR?为什么只有工程师能独享改代码的乐趣?
中小型项目对语言和框架的锁定正在蒸发,到 2027 年底会彻底死亡。但一个“好的”完全用 Rust 重写的 Linux 内核要到 2028 年才会出现。低利率时代为了留住程序员而姑且接受的“业余手工工具进工作场所”会被一扫而空。用 Zig、Clojure、Elixir、Haskell 等业余语言编写、又没有真正充分理由的专业项目,会被自动重写成模型分布更友好的语言,如 Python、Ruby、TypeScript 和 Rust。
coding agent 产出的代码,以及仍然手写代码的开发者,都会进一步被套上约束衣。我对此有自己的想法,总体而言行业会集中力量把“质量”量化,并尽可能自动化生产它。
我对类型系统的扩张心情矛盾。TypeScript 正在战胜 JavaScript,但我认为那主要是因为人们讨厌写 JavaScript。我还不确定 agent 和人是否真能从给 Ruby、Python 等启用类型系统中获益。我们是否会熬过强安全系统推广中的“点火联锁”阶段,让它们像今天的安全带一样普遍,还要再看。
All in all, what I see happening is a further continuation of software becoming an industrial process, the same way it has been for decades now. People who want to solve tricky programming problems by hand can do so on their own time, at home outside working hours, as a hobby. But at work, the expectation will increasingly be to let the coding agents do as much as possible as often as possible.
My last prediction, and the answer to my original question, is that the further industrialization of software development via coding agents will increase the “quality” of code far beyond what any one craftsperson could produce. The models will keep getting smarter, and the automated tools we use to ensure quality in code will continue to get cheaper and better. Most software should not be created via a craft process, by hand or by individuals, and it’ll be increasingly less economically viable to do so in a competitive, global marketplace.
总而言之,我看到的是软件工业化的持续深化,就像几十年来一直如此。想手工解决棘手编程问题的人,可以下班后在自己家里当爱好做。但在工作中,预期会越来越变成:尽可能多、尽可能频繁地让 coding agent 干活。
我的最后一个预测,也是我最初问题的答案:coding agent 带来的软件开发进一步工业化,会把代码的“质量”提升到远超任何单个匠人能达到的水平。模型会越来越聪明,我们用来确保代码质量的自动化工具会越来越便宜、越来越好。大多数软件本就不该由手工或个人工艺生产;在竞争性的全球市场中,用那种方式生产软件会越来越不经济。
Software engineering, software development, programming, whatever you want to call it, has been constantly eating itself for as long as the field has existed. To expect that it would settle into a staid industry that never threw everyone for a total loop again is to deny the nature of this beast. Every 10 years or so, the industry gets turned upside down and there’s not anything anybody can do about it. Why should we expect the cycle to stop now? We keep thinking we have hit the End of History when it comes to working with computers, that a new tool or hardware or new something won’t ever happen again and upend everything all at once. Hell, we are still inventing new ways of working with wood after several millennia of working with it! We’re not even done with figuring out how to produce wood, how could we have already found the exact right way to produce code?
To finish this overly long essay up, the other day I merged a PR I didn’t even try to read. It was a tiny one, just one file changed, a little configuration setting, I knew exactly what should have been in there, and I was in the middle of doing a million other things. Claude knew what she was doing, we had talked through the change, it was to unblock something important, I’m sure she did it right, it’s pretty hard to mess up. All the tests passed, the linter was happy, everything looked the way it was supposed to look in CI. So why should I have looked at the code? And I went back and checked just now and it was fine, really, nothing to worry about. It’s just one little change in one little file. What’s the worst that could happen? I still read the important stuff, I promise!
We live in interesting times, and all I can do is suggest you find your joy in that, wherever it might lie. For me, I smell a new type of craft in the promise of ensuring and imbuing quality in the output of coding agents, and I am very curious to see how deep it goes.
At least my hands don’t hurt anymore, not the way they used to. That’s been nice.
软件工程、软件开发、编程——随便你怎么叫——这个领域从诞生起就在不断吞噬自己。指望它变成一个安定、再也不会让所有人天翻地覆的行业,是否认这头野兽的天性。大约每十年,这个行业就要底朝天一次,谁也拦不住。我们凭什么认为循环会现在停下?我们总以为自己在计算机工作上到了“历史的终结”,以为不会再有新工具、新硬件或新东西一次性颠覆一切。可我们跟木头打了几千年交道,都还在发明新的木工方式!我们连“怎么生产木头”都还没研究完,怎么可能已经找到了“怎么写代码”的最终正确答案?
用一个小故事来结束这篇过长的文章:前几天我合了一个根本没尝试读的 PR。改动很小,只有一个文件,一个配置设置;我非常清楚里面应该是什么,当时正忙着做一百万件事。Claude 知道自己在做什么,我们讨论过这次改动,它是为了解除某个重要阻塞;我很确定她做对了,这东西很难搞砸。测试全过、linter 满意、CI 里一切如常。我凭什么还要看代码?我刚刚回去检查过:确实没问题,真没什么可担心的。一个文件里的一处小改动而已,能出多大事?真的,重要代码我还是会看的,我保证!
我们活在有趣的时代,我唯一能建议的是:在其中找到你的快乐,无论它在哪里。对我而言,我在“确保编码 agent 的产出有质量”这一新任务中闻到了一种新手艺的味道,我非常好奇它能走多远。至少,我的手不再像以前那样疼了,这很好。