本文结合我近期 Agentic Coding 的经验,讨论这一范式在实践当中可能遇到的问题。
首先说明,以目前 LLM AI 的能力,能够针对任意通用任务生成疑似正确(Plausible)的方案、流程或代码等,是完全可以做到的,但是以此为由声称“某某领域已死”[1]则大可不必。因为从生成似是而非的原型,到实际经得起考验的产品,仍然存在 AI 不能覆盖的鸿沟。不过,如果你的需求并不复杂,似是而非的结果已经可以满足需求,那也很好。
例如在发扬 LLM Writes Plausible Code[2] 的这篇文章里,作者抨击了一个号称 LLM-driven 用 Rust 重写的 SQLite 性能不行,所举的例子是一个简单任务 SQLite 原版花了 0.09 毫秒,但是重写版花了 1815.43 毫秒,也就是上万倍的差距。但是就这个简单任务而言,它也就花了一秒上下。如果你的需求就到这了,难道你会觉得一秒完成任务的这个 Rust 重写的版本有什么不好吗?
目前基于大语言模型的生成式人工智能,核心动作是现有知识的搜索和组合。
你问 AI 任何一个观点或设计方案,他的回答很多时候能找到现有的博客、文档或代码片段的痕迹。这也不奇怪,因为大语言模型代表的这条路,就是基于现有语料库做训练,针对给定输入,基于概率生成最可能的输出。
这就推理出两个重要的现象:
第一,大部分现有代码都是浆糊(Big Ball of Mud)。
因为现实当中的程序员大都倾向于就地打补丁,莫名其妙复用代码,遇到新需求就加若干个 if-else 或 options 硬改解决需求。这就把当前阶段的 Coding Agent 训练成了倾向于短平快解决问题的 AI Slop 喷射器。正好这种风格也符合模型厂商的需求:对于用户输入,用最小的推理成本生成一堆似是而非的输出,赌一把用户能够就此满足。
这里典型的例子,就是我常提到的为什么 AI 写并发代码经常容易丢三落四,因为你能找到的并发代码语料,基本都有各种考虑不全的竞态条件。所以在模型厂商针对这个场景做调优之前,AI 只能遵循 Garbage In Garbage Out 的定理,较大概率生成低质量的并发代码。
“或许下一代模型根据新的语料天然就能选对策略。其实这也是目前模型厂商在做的事情:人工选育正确方案调整权重,agent 里反复炼丹式的尝试校准方向。所以嘛,人工智能还是那个熟悉的有多少人工就有多少智能。
【引用自我 4 月 14 日的推文[3]】
第二,软件工程实践中有控制软件代码复杂度的解法;较低的代码复杂度有利于提高 Coding Agent 上下文信息密度;Coding Agent 让软件工程实践能够轻松落地。
由于驱动 Coding Agent 的大模型目前的语料还是基于过往人类活动生产的代码,因此在没有出现新的编程范式之前(下一节会讨论新的编程范式为何难以产生),最好的提升 Coding Agent 生成软件的方式,就是利用现有软件工程的实践。
这些实践包括但不限于:
- 通用的领域设计语言
- 限界上下文界定的模块化设计
- 跟随代码演进的活文档
这里首先说明几个入门级的软工手段,由于它们容易被误用,尤其容易在 AI 加持下放大其滥用的后果,因此需要专门做反论。
第一个是被 Don‘t Repeat Yourself (DRY)[4] 原则影响导致过度抽象。
这点 Claude Code 和 Codex 当前的模型都有这个倾向,即动不动就抽一个方法/模块出来,然后自己发散出许多不需要的需求,来回做泛化的“可复用”设计。
我在鉴赏过若干被曲解后的“设计模式”毒害的 Java 代码后,深刻理解到太过超前的抽象就是提前优化(Premature Optimization[5])。我自己总结出来的黄金准则就是:第一遍写 一段逻辑时,顺着写下来;第二次遇到相同的逻辑或可以复用部分代码块时,复制粘贴代码;第三次重复时,再考虑是否抽取公共代码。抽取时,原则是准公共代码是否在逻辑上是相同的意涵,还是碰巧使用了相似的代码实现。
是的,很多被 DRY 抽取出来的公共函数,从一开始就要为不同调用路径提供不同的配置参数来调整内部行为。这样的 DRY 很可能是无效的。同时,这会误导 Coding Agent 在错误的抽象上渐行渐远,最终左脑搏击右脑,彻底不知道注意力应该放在哪里。
关于 DRY 的反论,我上面的观点其实软件工程实践也早有总结,称之为 You aren’t gonna need it (YAGNI)[6] 原则。
进一步的讨论和案例,可以参考:
- Yagni By Martin Fowler[7]
- KISS vs DRY in Infrastructure as Code: Why Simple Often Beats Clever[8]
- John Carmack on Inlined Code[9]
第二个是测试驱动开发(Test-Driven Development, TDD)。
“我对 TDD 的评价一直都非常低。
如同我前两天说 DRY 不是教条,TDD 某种程度上是一个入门级知识点:不写测试当然是不对的,但是并非所有代码都需要被测试覆盖。
不加区分的运用 TDD 会导致写出很多垃圾测试。实际上,你变代码就要跟着改的种测试,没有价值。
我一向都是只写行为测试和回归测试,即测试软件端到端应该表现出什么行为,以及确保过去出现过的问题不再发生。绝大部分内部实现不需要追求 100% 的测试覆盖率。
【演绎自我 4 月 13 日的推文[10]】
AI 极大降低了写测试的精神健康损耗。我的体感是有了 AI 以后,那些该写而懒得写的测试,我写得更多了。
但是这里需要反论的是,把测试本身当成黄金指标,似乎有了测试就万事大吉,甚至不顾一切的追求高测试覆盖率。在 Codecov 一类的工具会因为改一行测试就误报覆盖率下降的当下,我对测试覆盖率没有任何信任可言。
正如软件工程当中的一句谚语:测试只能证明功能存在,不能证明 BUG 不存在。假装被一大堆测试包围的代码就是高质量代码,是一种自我欺骗。这实际上是一个古老的编程流派之争,即 Worse Is Better 或说在明显地没有缺陷(Obviously Bug-Free)和没有明显的缺陷(No Obvious Bugs)之间取舍。
相关内容可以参考以下材料:
- Tests Cant Prove The Absence Of Bugs[11]
- The Rise of Worse is Better By Richard Gabriel[12]
- Two Ways To Design[13]
AI 很擅长写出没有明显的缺陷的代码,因为自动补齐下一个 token 是其原生能力,不加限制的前提下,AI 能够无限的把代码编下去。
AI 其实也能够写出明显没有缺陷的代码,但是这需要人先给代码库奠基。AI 仿照现有风格的能力是很强的,但是语料库的影响仍然很严重。因此走第二条路往往还是需要人主动介入不断地回顾和修正代码库。当然,这个修正的动作本身可以由 AI 执行。
“群友:AI 重构代码也是非常麻烦,你不让它建新文件完全重写,它能纠结类型错误纠结到底。特别是很长的代码,我只好让在新文件搞,但是搞的时候参考老代码,搞完了再替换掉。
我:这种我一般是自己动手写核心和框架,然后让 AI 学。其实我写的代码等于 harness/spec 只不过我用代码表达出来更快。
回到一开始提到的三个重要的控制代码复杂度的软工实践,主要来自两本书:
- 《领域驱动设计》[14]
- 《活文档:与代码共同演进》[15]
相关的讨论可以参考:
- 活文档就是反文档
- @yetone 的推文[16]
- 我在 3 月 18 日的推文[17]
- @STRRL 的《我对 Spec Driven Development 的看法》[18]
说起来,有人问过我这类传统软工书籍要怎么阅读。我只能说一开始没有经验的时候可以硬读,然后找人交流。到了某个节点,你会发现你扫完一本书,能够提炼出哪些是作者的核心观点,哪些是时效性很强的例子。就像我上面引用的两本书,书里举的例子很多,但是读的时候只需要略过就行,而不需要刻板的记忆和沿用书中具体的做法。
由此我就想到,相当一段时间内,有部分程序员对《设计模式》[19]的印象就是“过度设计”,尤其是某些 Java 软件当中叠床架屋的设计。然而《设计模式》一书的核心价值,是帮你定义哪些代码是“可复用”的,可以用何种固定模式编写出可复用的代码,在哪些场景下应该使用这些模式。
实际上,《设计模式》的副标题就是“可复用面向对象软件的基础”。书中简明扼要的定义了应用程序、工具库和框架三种类型的软件,能够帮助程序员(现在则是 Coding Agent)很好的分类代码需要复用或被复用的情形。同时,书中时效性很强的就是具体的模式和实现。其中明确提到,有些模式需要编写额外代码实现,其实是受语言约束所致。
某种程度上,我们可以把设计模式看做是 Coding Agent 的技能(Skills)库。Agent 能够一目十行,比人更加不知疲倦的加强学习和记忆这些模式。所以我会说 Coding Agent 降低了软工实践落地的成本,对整个软件行业来说是一件好事。
“如果之前的软件工程实践是正确的话,真不应该发现有什么差别。反而会因为软工实践更好落地而开心。当然压力就是要 Review 的内容绝对数量变多了。
Reply-To: 不知道为什么那么多人排斥 AI 编程,不就是做项目经理么?拆解项目,分配任务,review 代码,盯文档和测试。不一样的么?唯一的不一样可能就是盯文档和测试更多一些了。
【引用自我 4 月 14 日的推文[20]】
这套方法论源远流长,可以参考《程序设计的模式语言》[21]系列,一共五卷。
从上一节我们可以看到,软工实践很多是不可量化的经验。它们或许生效,或许不生效,甚至有截然相反的原则,可能各自在某些场景下是有意义的。
“(Agentic Coding)跟 AI 下围棋有很大不同。AI 下围棋有一个明确的优化指标,就是最后这局棋要赢。要赢的话,每一步棋都可以算目数,算后面的演变成果。所以 AI 自己跟自己对弈可以提升棋力,棋力就是算力。全程有一个终局算目数要赢的目标可供回归。
但代码写得对不对,需求解决得好不好,除了很少一部分可以用测试验收解决,大部分现实世界的需求无法建立一个可靠的回归指标。如果世界因 Agentic Coding 发生真正生产力革命性变化,一定是因为发现了非常好的工程回归指标,能够验证代码质量或软件效果。如果出现这种东西,我觉得用 AI 可以高效地把生产力往上抬高一个台阶。但目前的事实是,大量的编程指标还没有建立起来。
【引用自我 3 月 13 日的推文[22]】
AI 可以生成代码,代码可以编译运行。确保测试通过是一个明确的指标,目前 AI 的智能基本能够实现在不卡死的情况下,根据测试失败的反馈,不断地修正代码,直到测试通过。(如果实在不行,我们神奇的 Claude Code 会选择修改测试或者硬 Hack 让测试命令别报错。)
但是程序设计时间消耗的大头并不在拼写代码,而在讨论需求、确定边界和方案调研上。很多这类问题,并没有一个明确的评判指标,为了可靠验收,最终还是要人去理解需求和知悉、确认调研的结果。当然,AI DeepResearch 和生成一个差不多得了的 stub 能够大幅提高这些工作的效率,但是总的还是一个 assistant 的定位。也当然,不排除有人根本就不在乎验收,点接收让用户去测试去吧。这其中有一部分是人性使然,也有一部分是确实并不是所有软件都要那么厉害。
“当然维护动作你可以让 AI 去 Review 和生成建议,但是大家用过 AI Review 的都知道 AI 的意见是不能都听的。当然近期 false positive rate 已经有明显下降,没那么高血压了。
而且这里会有一个时间窗口问题,就是一旦你开始 handoff 给 AI,在相当一段时间内,由于人天性的懒惰,你一定会什么也不看先 accept 再说。后来遇到瓶颈,就看你要花多少精力扭转这个习惯跟填之前埋下的坑。
如果你没有遇到这个瓶颈,非常好,你是 Vibe Coding 的目标用户。要知道海量 researcher 用 pickle 写本地文件 dump 一堆数据模型,也没什么问题。
以前 Review 压力没那么大,因为 PR Author 自己肯定看过一遍。AI 目前没有稳定的行为特征,会犯人不会犯的错。所以在搞清楚 AI 通常犯什么错,或者能够一定程度约束 AI 犯错的范围之前,Review AI Patch 的开销就是跟自己写一遍或者至少大致想一遍是差不多的。而这个部分,一直以来才是软件开发主要的时间开销。
【引用自我 4 月 13 日的推文[23]】
有一部分人声称自己不看代码也能生成解决问题的软件。这部分人一般对业务非常熟悉,能够通过业务指标来判断代码是否完成了目标。当业务目标被拆分到多个模块当中,且每个模块并不复杂的情况下,AI 在这种行为测试明确、有限,且行为测试即验收标准的场景下,能够表现出不错的软件开发能力。
这里隐含了两个问题:
- 实际上,这部分人提供了海量上下文来填平 AI 缺失的经验。他们可能不写代码,但是前文提到的开发软件主要消耗时间的讨论需求、确定边界和方案调研,他们都是要做的。
- 不看代码很多时候是因为这部分人已经多年不看代码或者从来没看过代码,用进废退了高效阅读代码的技能。条条大路通罗马。如前所述,我写的代码等于 harness/spec 只不过我用代码表达出来更快。
不写代码并不是一个一定更优越的方案。我用 AI 是为了提效,如果为了让 AI 达成目标,我必须花时间提供海量上下文,用同样的消耗做到我以前做的同样的事情,那这跟编程语言之争有什么区别?我说用 Go 写得快,你说用 Java 写得快,结果是一样的,付出的努力也是一样的,那大家相互尊重各走各路完成目标就好了。
关于 AI 需要更多上下文的问题,我举一个很简单的例子:
“Web 应用的登录鉴权,你什么都不说,AI 可能会根据语言和生态随便套一个流行的模型就上了。如果生态里没有,AI 大概率会闭眼睛弄一个账密登录的方案。这个时候,你告诉它,现在流行的是没有密码的 One-Time Password 登录,它很可能不会问你用什么 OTP 方案,而是直接 Mock 一个实现然后告诉你已经完成。
当然,现在你知道问题是啥了,你会说那你在 prompt 里写清楚,或者在 plan mode 里把需求定清楚,或者加载对应 skill 就行。问题是这其实是一个 unknown unknowns 的事情。所以我才认为,对于创造性程序的开发,或者用户体验非常重要的软件,AI 实际每段核心代码的产出都需要 Review,因此 Agentic Coding 的带宽瓶颈实际来源于 Review 带宽。而人自己写一遍,就是一种自然的全面 Review 的方式。所以跟 AI 交互,用 AI 去探索可能性,让 AI 生成 stub,再由人定期维护核心设计和框架实现,是我目前看到在生产高质量软件场景下,生产力提效的上限。
【引用自我 4 月 13 日的推文[24]】
再举一个例子:
“在开发 ScopeDB 的过程里,我经常惊讶于 @andylokandy 随手就告诉我一个 Rust 库可以解决特定问题,或者翻出来一个标准库接口;也经常被 ANDY 和 @leiysky 随手翻一篇论文出来做参考,随手丢一个友商文档做对比,感到自己怎么这么没知识。
当然我也有自己莫名其妙知道的很多诡异的细节。这些东西实际能解决问题,且在特定场合能提效十倍以上,甚至是唯一正确的解法。你去问 AI,大概率没有这么高水平的组合结果出来,甚至都搜不到。这就是我之前提过的,很多知识不在语料库里。
模型厂商正经不正经拿到的语料是有限的,其某些方面的水平可能超过中位数从业者,但是有能力瓶颈。而且,现在掌握语料的人和组织已经很快意识到手中信息的价值,并不会轻易共享出来。未来的发展还需要再谨慎观察。
之前传说过这种能力能够通过 skills 共享,我很好奇有没有哪位前端开发者用 @antfu7 公开的个人 skills 完成了某些具体工作,实际体验如何。前端圈涌现出更多的 @antfu7 了吗?
gstack 是更有流量的尝试,有很多人都分享了自己的体验。各位可以自行评判。
【引用自我 4 月 13 日的推文[25]】
参考资料
[1]
“某某领域已死”: https://x.com/tison1096/status/
[2]LLM Writes Plausible Code: https://x.com/KatanaLarp/status/
[3]4 月 14 日的推文: https://x.com/tison1096/status/
[4]Don‘t Repeat Yourself (DRY): https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
[5]Premature Optimization: https://wiki.c2.com/?PrematureOptimization
[6]You aren’t gonna need it (YAGNI): https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it
[7]Yagni By Martin Fowler: https://martinfowler.com/bliki/Yagni.html
[8]KISS vs DRY in Infrastructure as Code: Why Simple Often Beats Clever: https://rosesecurity.dev/2025/11/14/kiss-versus-dry-iac.html
[9]John Carmack on Inlined Code: http://number-none.com/blow/blog/programming/2014/09/26/carmack-on-inlined-code.html
[10]4 月 13 日的推文: https://x.com/tison1096/status/
[11]Tests Cant Prove The Absence Of Bugs: https://wiki.c2.com/?TestsCantProveTheAbsenceOfBugs
[12]The Rise of Worse is Better By Richard Gabriel: https://web.archive.org/web/20040619155500/http://www.jwz.org/doc/worse-is-better.html
[13]Two Ways To Design: https://wiki.c2.com/?TwoWaysToDesign
[14]《领域驱动设计》: https://book.douban.com/subject//
[15]《活文档:与代码共同演进》: https://book.douban.com/subject//
[16]@yetone 的推文: https://x.com/yetone/status/
[17]我在 3 月 18 日的推文: https://x.com/tison1096/status/
[18]@STRRL 的《我对 Spec Driven Development 的看法》: https://strrl.dev/post/2026/my-thought-about-spec/
[19]《设计模式》: https://book.douban.com/subject//
[20]4 月 14 日的推文: https://x.com/tison1096/status/
[21]《程序设计的模式语言》: https://book.douban.com/subject//
[22]3 月 13 日的推文: https://x.com/tison1096/status/0
[23]4 月 13 日的推文: https://x.com/tison1096/status/
[24]4 月 13 日的推文: https://x.com/tison1096/status/
[25]4 月 13 日的推文: https://x.com/tison1096/status/
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/271005.html