你还阅读代码吗?

Lobsters Hottest 新闻

摘要

本文探讨了两种AI增强编码方法——保持代码理解的加速者和更多委托AI的氛围编码者——并讨论了它们对软件维护和团队动态的长期影响。

<p><a href="https://lobste.rs/s/qiwlzz/do_you_still_read_code">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/09/14 21:05

# “你还会阅读代码吗?” • zanlib 来源:https://zanlib.dev/blog/do-you-still-read-the-code/ ###### 2026年9月14日 --- 这个问题与更温和的“你会阅读代码吗?”之间存在显著差异。“仍然”这个词暗含了一种进步理论:阅读代码正在成为过时的做法,就像背诵电话号码或展开纸质地图一样,而提问者似乎想知道你是否恰好不是那些固守旧习的模糊主义者。 我广泛使用AI,并阅读它生成的内容。这是我关于如何开发软件的深思熟虑的选择,至少在我的工作中如此,因为我需要对自己提交和部署的代码负起合理的责任。其他人做出了不同的选择,有时经过了相当仔细的考量。但我们已经开始共享代码库,却未必对每种方式对同事的要求达成共识。 很难判断哪种选择会胜出。“仍然”这个词假定事情已经尘埃落定,而如今制作一个可运行的应用程序确实变得容易多了。但要找出在需求、开发者和工具链变化过程中维护它的代价,则需要更长的时间。我们现在对团队如何工作做出了承诺,其后果只有在后期才会被感受到和理解。两种思维方式在宣布自己胜利时所展现的自信,似乎都有些为时过早。 ## 加速器与氛围编码者 据我所知,如今使用AI主要有两种流行方法。 *加速器*使用AI帮助将他们的理解转化为代码。他们打算保留足够的对实现的理解,以便能够解释从意图到代码转换背后的推理,预见变更的后果,并维护由此产生的模型和实现。阅读生成的代码是这种承诺的一部分。 对于加速器来说,语言模型和运行环境大致与文本编辑器及其插件属于同一类别:它们现在可以更快地编码。他们投资于自己持续解释和更改实现的能力。大型变更的审查过程很慢,一个被认定为错误实现模型的生成差异会被重写,每当团队的阅读速度跟不上生成速度时,认知债务(1 https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-storey)边际注释1Storey, M.-A. *从技术债务到认知与意图债务:重新思考AI时代的软件健康度* (https://arxiv.org/abs/2603.22106). arXiv 2026; p. 3↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-storey-1)就会堆积起来,而整个过程需要的纪律性非常难以维持。 *氛围编码者*旨在将实现及其持续修订委托给AI。他们的注意力转向指定所需行为、提供上下文和领域知识,以及建立评估结果是否令人满意的方法。理解每个实现细节不再是你工作的预期产出。 氛围编码者期望语言模型抽象掉实现,将它们与编译器和框架归为一类:不再需要理解技术细节。他们投资于自己持续指定、重新生成和评估代码的能力。随着需求的重写或遗忘、上下文在会话之间漂移、工程时间用于策划代理能看到的内容以使其远离“愚蠢区域”(3 https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-horthy)边际注释3Horthy, D. *禁止氛围:在复杂代码库中解决难题* (https://www.youtube.com/watch?v=rmvDxxNubIg). YouTube 2025; 5:55↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-horthy-1),意图债务(2 https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-storey2)边际注释22Storey 2026; p. 3↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-storey2-1)可能会累积起来,而整个事情的成败取决于由Anthropic或OpenAI控制的模型质量。 这种区分关乎开发者与输出的关系,而非模型写了多少。4 (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-willison)边际注释4Willison, S. *并非所有AI辅助编程都是氛围编码(但氛围编码很棒)* (https://simonwillison.net/2025/Mar/19/vibe-coding/). 2025↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-willison-1)一个加速器可能生成功能的几乎每一行代码,但仍然理解构建了什么,并承担起背后推理的责任。一个氛围编码者可能花费大量时间来完善规范及其验收标准,同时有意地将由此产生的实现视为可丢弃的。成为加速器并不意味着在向模型提问前就知道答案——你可以使用生成的代码来探索一个你尚未理解的问题,只要你打算在代码进入主分支之前获得这种理解。5 (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-abstain)边际注释5还有第三类人完全拒绝在编程中使用AI。我遇到的反对意见大多是法律(通常与版权相关)或道德方面的,虽然值得认真讨论,但这超出了本文分析的范围。我还没遇到过任何组织出于实用工程原因而在商业软件开发中避开AI:因为他们相信生成的代码会使其软件变差,最终成本高于收益。如果你在这样的组织工作,请随时联系我。我很想听听相关情况。↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-abstain-1) ## 纳尔依然无敌 我自己的偏好源于我认为编程的目的。我之前写过(https://zanlib.dev/blog/books-debts-and-delicatessen/),编程本质上是纯粹的应用哲学。那时我还没读过彼得·纳尔的文章(6 https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-naur)边际注释6Naur, P. *作为理论构建的编程*。微处理与微编程 1985↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-naur-1),该文章随着LLMs的兴起重新受到关注,它在三十五年前就提出了类似的观点。 这本质上是同一个论点,由一个聪明得多的人阐述得更好:代码并非编程的真正产物。如果说有什么不同的话,我们误将代码视为资产,而它通常确实是一种负债。真正的产物、资产是背后的模型或理论。这种理论是一种知识,它不仅让人能够做某事,还能解释它、回答关于它的问题、用它来预测未来,并在情况变化时调整它。拥有这种理论的程序员具备三种能力: > “拥有程序理论的程序员可以解释解决方案与它帮助处理的世界事务之间的关系。……拥有程序理论的程序员可以解释程序每个部分为何如此。……拥有程序理论的程序员能够对任何修改程序以支持世界事务新方式的要求做出建设性的回应。” 换句话说,源代码只是编程活动的一种产物,但由于它更显眼,它被赋予了比在产生它过程中获得的理解更高的价值。这就像我们把燃煤电厂冷却塔冒出的蒸汽当作主要输出,而不是电力,仅仅因为电是看不见的。 软件工程师的一部分工作是为迄今为止仅被隐含理解的业务部分命名和结构化。这在代码之外也有好处:它可以帮助我们建模其工作的人理解他们的工作,并以新的视角看待他们工作的某些方面。 编程是(https://zanlib.dev/blog/a-voice-from-nowhere/#the-path-underneath)一种梳理现实沙粒的方式(7 https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-pirsig)边际注释7Pirsig, R. *禅与摩托车维修艺术*。Vintage 2004; p. 72↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-pirsig-1)。我们将一物与另一物区分开来,为这些区别命名,并构建一个系统,其行为让我们发现我们的梳理在何处有用,又在何处出错。 根据事物的表面(https://zanlib.dev/blog/naming-things/)来命名会将我们锁定在对产品的某种理解模式中,这可能是偶然的;根据其本质属性来命名则更灵活,但需要更多的精力去发现和结构化。而运行中的软件只能测试梳理的后果。判断模型是否契合领域,仍然需要与被建模的人和流程接触。一套通过的测试套件只能证明程序做了你所说的,而不是你所说的对应了现实。 程序员对领域的理解会随着他实现的过程而改变。你可能讨论需求,甚至在白板上画出来,但你的概念分析可能经不起与代码的第一次接触。当你必须考虑每种情况时,你可能会彻底改变对问题的理解,被迫从头再来。 那么,实现不仅仅是将规范翻译成可运行的代码,也是修订规范的地方之一。氛围编码者似乎押注于理论可以通过指定和运行软件来构建,而无需处理其实现。对此我并不十分确定。 ## 选择与漂移 选择加速器或氛围编码者方法涉及不同的承诺,即使同一个人可能为不同的项目,甚至同一项目内的不同子模块做出不同的选择。 例如,我可能会在临时性或探索性项目中倾向于氛围编码,在这些项目中,我实际上并不关心底层实现,只想在屏幕上看到东西。问题在于,一个人可能在没有认真思考如何正确委派的情况下,就停止了对实现的理解。你开始浏览差异而不是阅读它,你需要大量时间来回想甚至为特定的实现选择找到理由,最终,找出你实际构建了什么的唯一实用方法就是询问模型,而无法验证模型告诉你的是否正确。 这就是为什么我不认为这两种方法是某种连续谱。你可以在一个模块中是加速器,在另一个模块中是氛围编码者,但不能在两者之间半途而废。一个漂移的加速器最终不会停留在两种方法之间的某处;他最终默认成为一个氛围编码者,却没有深思熟虑的氛围编码者为了弥补缺失的理论而建立的关于规范和评估的运行环境。 就我的商业工作而言,阅读生成的每一行代码是确保我不会漂移的好方法。它不能保证我的理解,但它提供了反复发现理解与实现在何处产生分歧的机会。 而它们之所以会分歧,是因为代理仍然会做出愚蠢的选择,并且常常不尊重一些人类的维度,比如时间,这些维度无法表达为文本输出。一个只添加测试的代理只关注终端输出;对于那个代理来说,测试现在需要三倍时间来运行并不重要。但速度对人类很重要。同样,上下文窗口被污染而漂移到“愚蠢区域”的代理会开始犯下明显的局部错误,比如在其他组件内部声明React组件,或违反hooks的规则。 ## 一场不愉快的结合 我不想这听起来像是一份加速器宣言,因为我完全愿意承认氛围编码者可能是对的,AI会使查看代码过时——我只是目前还没有看到足够有力的证据支持这一结论。 但我确信的是,有一种明显有害的做法:将偏好不同方法的人放在同一个团队中,而没有事先建立期望和边界,然后又不遵守它们。 加速器可能需要承担起重构理解的任务,而原作者从未打算保留或从一开始就没有这种理解。氛围编码者可能需要解释附带的实现选择,即使他花了大量时间完善开发流程以有意使这些选择可丢弃。任何一方都可能通过强加未声明的维护期望而使另一方的工作变得更困难。 在普通通信中,向他人发送未经过滤的AI输出是不礼貌的(https://zanlib.dev/blog/reliable-signals-of-honest-intent/)。但当这开始涉及代码、意图以及对生产环境问题的责任时,礼貌就变成了一个工程问题。在合并更改之前,同事需要知道这些更改打算如何维护:是通过开发者对实现的理解,通过规范以及既定的代码生成和严格测试流程,还是两者的某种组合,只要明确哪些部分属于哪种方式即可。 ## 阅读是否足够 所有这些都没有让加速器的立场变得舒适。 技能在不使用时会退化,仅仅审查AI生成的代码,而不是自己敲出来,是否足以接管并在情况需要时切换回手动编码,仍有待观察。一些经常被推测的情况,比如主要AI实验室破产或大幅提价,似乎已不再是问题(我们可以访问许多足够高质量的开源权重模型提供者,必要时可以继续前行),但可能存在一些我们未预见到的自动化危险(8 https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-bainbridge)边际注释8Bainbridge, L. *自动化的讽刺* (https://www.complexcognition.co.uk/2021/06/ironies-of-automation.html). Automatica 1983 (!!!)↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-bainbridge-1))。也许任何继承了一个氛围编码,甚至是加速生成的代码库的人,会发现维护起来困难重重。 宣布人类仍然负责是容易的。安排工作使人类保持履行这种责任的能力则要困难得多,并且需要非常多维度的决策。结果可能是,加速器方法只是通往职业倦怠的快车道。 审查所有内容意味着对你一次能处理多少陌生工作设定了限制。在使用AI编码时,你仍然需要确保你的需求建模得到保证,并且实现不会漂移;否则,自我审查输出的工作将是那种最糟糕的工作——“非常无聊但非常负责,却没有机会获得或维持处理这些职责所需的素质。”9 (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-def-bainbridge2)边际注释9Bainbridge 1983; §1.2↩ (https://zanlib.dev/blog/do-you-still-read-the-code/#marginnote-ref-bainbridge2-1) 这是一种对高要求实践的有意识选择,其成功需要的远不止良好的意愿。如果软件开发能够完全自动化,那么加速器方法或许会成为通向更糟糕未来的道路。

相似文章

Agentic Code Review(15分钟阅读)

TLDR AI

分析AI编码代理如何将瓶颈从编写代码转移到审查代码,数据显示代码变更量增加861%,缺陷率上升,使得代码审查成为软件工程中最具杠杆效应的技能。

AI编程:摆脱氛围

Hacker News Top

这篇文章反对在编程和学习中过度依赖AI,强调应采取平衡方式,让AI辅助而非取代技能培养,以确保真正的理解。

AI时代下的代码审查生存指南

Lobsters Hottest

作者探讨了AI在代码审查中引入大型代码差异所面临的挑战,并寻求在保持人类理解的前提下应对这些挑战的策略建议。