AI 生成代码能跑,质量和可维护性可靠吗?
深入讨论 AI 编程的核心困境:应用易于运行但代码质量堪忧。引发对 AI 辅助编程未来的反思。
深入讨论 AI 编程的核心困境:应用易于运行但代码质量堪忧。引发对 AI 辅助编程未来的反思。
让 AI 成为自己的审计员
应用已经能运行了。演示也成功了。它已经部署到一个真实的 URL 上,任何人都可以把链接发给朋友。对大多数第一次使用 AI 构建应用的人来说,这就是终点。但实际上,这更接近整个过程的中点。
“能用”和“好用”是两个不同的问题,而这两个问题通常要由两种不同的方式来回答。现代 AI Agent 非常擅长解决第一个问题。描述你想要什么,它就能生成可以运行的东西,而且往往第一次尝试就能成功。
但这个东西究竟好不好——是否安全、实现的是不是真正的需求而不只是演示过的功能、当创造者之外的人使用它时能否经得住考验——则是另一个问题,而 AI Agent 在这方面远没有那么可靠。真正的工作,以及真正的学习,就藏在这个问题里。
这是完成第一个 vibe-coded 项目后自然而然的下一步。构建已经结束了。接下来,该看看要如何对待构建出来的这个东西。
我们可以用一种很实用的方式来理解 AI 在这个过程中能做什么、不能做什么:它提供的是原材料,而不是最终完成的建筑。Agent 可以在几秒钟内生成能够运行的代码。但这些代码是否适合放进一个会被真实用户使用的产品中,需要由人来判断,而且这种判断必须掌握在人手里,而不是交给模型。
这也是整个行业一直在反复讨论的问题。绝对初学者、软件创造者与高效开发者之间的距离,从未像现在这样近。但过去位于这几者之间的那层专业经验——开发者在团队里花费多年时间解决真实问题,逐渐理解“好”究竟是什么样子——却因为 AI 压缩了成长旅程的早期阶段,而变得更难获得。
对软件创造者来说,好消息是:这个缺口并不只是一个需要担忧的问题,也可以主动采取行动来弥补。这个行动,就是审计构建出来的东西,而且从第一个项目开始就可以这样做。
开发得快,也可能意味着毫无防护。一个下午就构建完成的应用,可能刚刚上线,几小时之内就泄露用户交给它的所有数据。
这并非假设。
由初学者构建的应用,已经出现过这样的情况:数据库以默认的完全开放状态直接进入生产环境;本应要求身份验证的 endpoint 没有任何认证;secret key 被直接提交到公开代码中。因为应用能够运行,所以构建者觉得它已经完成了。缺失的那一部分一直不可见——直到问题真正发生。
这种情况如此常见,有其结构性原因。当 AI 接管初始化和 boilerplate 时,它也悄无声息地替人做出了一百个细小的决定。如果一个人采用缓慢的传统方式亲手构建,那么至少会看到这些决定逐一出现。其中一些决定与安全有关。
大多数默认配置的设计目标都是让东西运行起来,而不是确保它安全;“能运行”和“安全”采用的并不是同一套默认标准。一个从未学习过底层概念的软件创造者,可能不知道哪里出了问题,不知道该去哪里检查,也不知道下次应该问什么。但如果他们把审计视为工作的一部分,就很有可能在其他人发现问题之前把它找出来。
“审计”听起来像一个属于资深工程师的词,仿佛它只会出现在有检查清单和合规专员参与的会议室里。但对于第一个项目来说,审计的规模要小得多,也实用得多。它只是一组需要针对现有成果提出的简短问题。真正的技能,就在这些问题本身。
它实现的是原本想要实现的功能,还是只实现了演示过的功能?演示走的是 happy path:输入正确、点击符合预期,而且只展示提前排练过的那一条流程。真实使用的情况要混乱得多。
字段为空、文件类型错误,或者按钮被按了两次时,会发生什么?
是否有任何人的数据暴露在外?如果应用存储了任何东西——一个电子邮件地址、一条登录信息,甚至只是一张上传的照片——需要追问的就是:谁能够访问它?陌生人能读取数据库吗?
代码本身是否直接写入了任何敏感信息?
能否向其他人解释这个应用是如何构建的?不必逐行讲解,但至少能用直白的话说明:其中有哪些活动部件,每个部分分别负责什么?如果诚实的回答是“不能”,这并不代表失败。恰恰相反,这是新手构建者能够发现的最有价值的信号,因为它准确指出了下一步应该学习什么。
AI 悄悄跳过了什么?为了尽快达到“能运行”的状态,每个 Agent 都会做出取舍。错误处理、验证,以及会拖慢初稿速度的安全实践——这些最有可能被省略,也最值得直接追问。
当使用者不再只有一个人时,会发生什么?一个仅由一名用户构建和测试的应用,在十个人甚至一万人同时出现时,会表现得完全不同。哪怕只是想象这种变化,也能暴露出单人演示永远无法发现的问题。
提出这些问题,并不要求事先知道答案。你只需要知道这些问题应该被问出来。而得到答案最有效的方式,就是去问最初编写这些代码的同一个工具。
使用 AI Agent 时,最常见的错误,是把它当作苦力,告诉它应该输入什么,然后不加判断地接受它返回的一切。如果把同一个工具当作教练,它就会成为人类有史以来最出色的学习工具之一。这种教练式用法不仅适用于构建,也同样适用于评估。诀窍在于:让 Agent 重新审视自己的输出,并要求它作出批判性评价。
只需要少数几个 prompt,就能完成大部分工作:
“逐行带我读一遍这段代码,并解释每个部分的作用。”
“为了让它运行起来,你省略了哪些安全实践?”
“在真实用户开始使用之前,你会修改哪些地方?”
“用户数据存储在哪里?现在谁能够访问它?”
“资深工程师会指出这段代码中的哪些问题?”
这些回答可以同时完成两件事。它们会暴露需要修复的具体问题,也会在这些概念真正产生影响的具体情境中,教会构建者问题背后的原理。
如果新手构建者读到了一段关于数据库连接为什么不安全的解释,那么他在五分钟内学到的安全知识,可能比一周的抽象教程还要多。因为这个知识与他亲手制作并真正关心的东西联系在了一起。
这就是教练与拐杖之间的区别。让 AI 解释代码为什么以这种方式运行、拆解它省略了什么、逐步说明自己的推理过程,这才是学习。让 AI 写完整个项目,自己只在旁边点头,然后再让 AI 宣布项目已经完成,则与永远照着教程操作是同一个陷阱……只不过把视频换成了聊天机器人。
经验丰富的开发者通常会建立一份个人检查清单,并在发布任何东西之前执行检查。有些清单包含几十个项目,是在多年成功与失败的发布经历中逐渐积累出来的。清单上的每一项,都代表着某个曾经发生过的具体问题,而且当时造成的后果足够严重,让人决心绝不再犯。这份清单不是别人交给他们的,而是对所有过往故障的压缩记录。
软件创造者可以立刻开始建立自己的清单,而这会成为整个过程中回报最高的习惯之一。第一个版本可能只有一项。此后,每当某个东西出错、审计发现一个问题,或者 AI 指出了某项被省略的内容,清单上就增加一行。
几个月后,这份不断增长的清单,就会逐渐提供过去由中间经验层所带来的东西:一种来之不易的判断力,知道应该检查什么、哪些地方容易出错,以及“完成”究竟意味着什么。
持续提出问题所积累的成果,也会在这里产生回报。每次审计都会扩充你的清单;清单又会让下一次审计变得更快、更敏锐。随着时间推移,那些过去需要专门查找的问题,会变成构建者下意识提出的问题——而这正是对“专业能力”的一种实用定义。
你无法从教程中获得品味或判断力。它们来自构建真实的东西、亲手把它们弄坏、检查哪里出了问题,并与其他正在做同样事情的人交流经验。AI 已经让构建变得很快,但它无法认真审视人们做出来的东西,并判断它是否真的足够好。
真正值得精进的正是这一部分,而与其他人一起学习,是掌握它的最佳方式。
MLH hackathon 是一个能让你在周末与那些比自己领先几步的人一起发布作品、再把它弄坏的地方。
在 DEV,审计过程可以变成一篇文章:构建了什么、哪里出了问题、代码审查发现了什么,以及最终修复了什么。
在一个地方构建你的作品,再到另一个地方记录它教会你的东西。这样,下一个发布自己第一款应用的人,就能站在比你当初稍远一点的位置开始前进。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。