与 AI 协作:术士学徒问题的具体案例

与 AI 协作:术士学徒问题的具体案例

AI 是开发中的强大工具,但它可能导致“术士学徒问题”,即开发者变得依赖 AI,并失去了理解和解决自身系统内问题的能力。在关于修复 hyperscript 解析器回归问题的详细记录中,Carson Gross 展示了 AI 如何在调查和测试生成方面表现出色,但在高层架构设计和防止技术债方面表现挣扎。

AI 在根本原因分析和测试方面的优势

AI 智能体,特别是 Claude,被证明在快速识别 bug 的根本原因方面非常有效。在 hyperscript 0.9.91 的回归案例中,一个特定的表达式——fetch {% url 'trade:get_symbol_data' %}?symbol=${symbol} as JSON——无法正确解析,因为 as JSON 修饰符被当作了转换表达式,而不是 fetch 命令的修饰符。

Claude 识别出,对 gofetch 命令进行重构以共享公共方法 parseURLOrExpression(),无意中扩大了语法范围以包含通用表达式,导致解析器过早地消耗了 as 关键字。

除了分析之外,AI 在生成针对性的、小规模的测试以验证 bug 及其随后的修复也具有高度能力。这使得开发者能够创建比他们手动编写更有精力的测试套件,这对于维护旧项目特别有利。

AI 在架构设计方面的失败

虽然 AI 在分析方面很快,但在提供简洁、通用的解决方案方面却很挣扎。AI 提出了三种不同的修复方案,其中两种是有缺陷的:

  1. 特定的 Hack:第一个提案建议首先解析一个“类字符串”的叶子节点,这虽然能修复眼前的 bug,但在通用情况下会失败,例如当变量被用作 fetch 目标时。
  2. 不必要的复杂性:第二个提案建议向解析器添加一个 noConversions 标志,这会使解析器具有上下文敏感性。虽然 hyperscript 解析器本身已经是上下文敏感的,但这会引入不必要的内部状态和技术债。
  3. 过度宽泛的应用:第三个提案在人类开发者的引导下,利用现有的“follows”基础设施来防止 as 关键字被解析为表达式。然而,它将此修复应用到了共享的 parseURLOrExpression() 方法中,这破坏了 go 命令中的 as 转换表达式。

最终的正确解决方案是由人类开发者实现的,他将特殊情况专门缩小到 FetchCommand#parse() 方法中,从而确保 go 命令不受影响。

人类在环中的角色

为了避免呈指数级增长的技术债,知识渊博的人类必须留在环中,充当“术士”而非学徒。这确保了解决方案符合现有架构并保持系统的整体连贯性。

Hacker News 线程上的社区讨论强调了几个关键见解:

"AI 擅长分析和样板代码,但不擅长进行良好设计所需的批判性思维……LLM 没有世界模型。它们不像人类那样研究并思考设计。"

"如果它真的擅长为自己设计智能测试,那么所有那些较弱的被拒绝的方案都可以避免。"

AI 作为资深开发者的辅助工具

对于资深开发者,AI 可以缓解与年龄相关的记忆力下降和长时间工作的能力下降。通过作为记忆辅助工具和处理样板代码及测试的“磨床”,AI 允许年长的开发者更高效地在项目之间切换,并减少处理繁琐任务的精力消耗。

然而,存在一种担忧,即过度依赖 AI 可能会加速“智力的迟钝化”和批判性思维能力的普遍退化。

结论

有效的 AI 辅助编程需要一种平衡:利用 AI 进行调查、测试生成和快速原型设计,同时依靠人类判断来进行架构决策并防止技术债。盲目接受 AI 智能体提出的第一个或第二个方案是会导致代码库长期不稳定的风险。

Sources