思想领袖

AI 应用构建的未来取决于类型安全

mm

AI 生成的代码可能会编译,但如果没有严格的类型安全,成功是非常短暂的。类型安全是防止脆弱代码腐烂成隐藏的 bug 和运行时故障的防护栏,当系统扩展时,它会阻止这些问题的发生。

我们必须开始通过上下文、指令、linting 和反馈循环来强制 AI 遵循严格的类型约束。这需要额外的几个小时,但是它会产生持久的代码。

激励问题

AI 想要取悦你。它优化了给定的奖励函数,大多数时候这只是“它是否编译?”这意味着它会削减每一个必要的角落来获得绿色对勾。这些捷径在编译时看起来很好,但是它们在运行时会崩溃。

这就是为什么 AI 喜欢 any。或者它选择一个宽泛的类型,如 string,而不是更严格的类型,如 UUID。代码编译,但是正确性已经被破坏。更糟糕的是,AI 不记得它之前写了什么,所以没有类型安全,项目很快就会在复杂性增长时崩溃。

两种类型的错误

AI 生成的代码 运行时,你通常会看到两种类型的安全问题:

1. 编译时错误

  • 发生了什么: 编译器捕获到声明的类型和传递的类型之间的不匹配。
  • 人类如何解决它: 决定调用者是否错误(将 42 转换为 string)或函数签名是否错误(将其更改为接受 number 类型)。
  • AI 如何“解决”它: 将参数类型更改为 any。问题“解决”,但你刚刚删除了将来会捕获错误的防护栏。

2. 运行时错误

  • 发生了什么: 编译器认为一切都很好(通常是因为类型被放松),但实际的运行时值与假设不匹配。
  • 人类如何解决它: 跟踪变量到其源头(如 API 或数据库查询),并在边界处修复类型,以便数据以适当的 string 形式输入。
  • AI 如何“解决”它: 没有上下文,它会猜测。也许它会将所有内容包裹在 String(…) 中,或者简单地将类型扩大。崩溃消失,但逻辑现在被破坏。 Number 类型的数学运算现在变成了 string 类型。

这种运行时错误 → AI “解决” → 类型放松的循环迅速加剧。 结果是一个编译良好但不可信赖的代码库。想象一个医疗保健系统,医生的轮班由应用程序管理。类型不匹配:一个 int 类型的小时被视为 string 类型。AI “解决”它通过将类型放松为 any。代码编译,错误消失,但轮班计算悄悄地破坏,双重预订医生,整个医院的一翼都没有覆盖。

数据库乘数

连接到数据库的那一刻,错误就会倍增,且其原因变得更难追踪。SQL 有类型的原因。每个模式(INT, TEXT, UUID, BOOLEAN)都编码了对数据的假设。

当 AI 将所有内容都平坦化为 string | any 时,你会失去这些保证:

  • 坏写入: 将“true”插入到布尔字段中会编译,但会破坏数据库。
  • 坏读取: 查询返回 NULL,但 AI 假设是字符串,导致运行时崩溃。
  • 破坏关系: 如果关系键被视为 UUID,但 AI 将其视为 string,并错误地发送垃圾值,连接将不会崩溃,但不会返回任何数据。这会隐藏错误,直到它们以缺失或不一致的结果为形式出现..

这就是为什么严肃的团队使用类型化语言并从模式到 API 强制执行类型安全的原因。如果你不这样做,数据库就会停止保护你,隐藏的问题就会迅速加剧。

为什么成熟的团队强制执行严格的类型约束

严格的类型约束不是为了减慢开发人员的速度。它是为了使扩展成为可能。

类型:

  • 将意图编码到代码中。
  • 使重构变得安全和可预测。
  • 在错误进入生产之前捕获整个类别的 bug。
  • 向未来的开发人员(和 AI)展示如何使用函数或对象。

没有类型安全,AI 的代码质量会迅速下降。有了类型安全,相同的 AI 会产生可靠的代码。

如何强制 AI 遵循类型安全

你必须像对待初级工程师一样对待 AI。快速、有才华,但如果没有方向,就会粗心大意。

提供正确的上下文

给它可以使用的接口和类型。展示使用示例。对代码结构有明确的意见。

给出严格的指令

非常明确地告诉 AI 不要使用 any,永远不要允许 unknown,并且每个方法、对象和变量都必须有类型。预计它会很难遵循这些指令(尤其是在第一次尝试时)。

使用 linting 强制执行

就像审查初级开发人员的代码一样,你需要检查 AI 的代码。设计自定义的 lint 规则来定义“良好代码”对你的意义。将 linting 失败反馈到模型,直到它通过。可能需要多轮,但它会将奖励函数转向包含类型安全。

迭代检查

编译时错误、运行时日志、点击测试。每次迭代都会强制 AI 紧缩类型,更加接近生产级代码。

更好的构建方式

我已经明白,牺牲原始生成速度来获得更高的质量是值得的。这意味着为 any 类型打零容忍战,强制执行多个反馈循环和严格的 linting 规则,AI 必须在代码完成之前通过这些规则。需要不断的努力,但这是保持质量不下降的唯一方法。

我之前提到一个关键点:一旦 AI 开始通过放松类型来修复运行时错误,你就会进入一个恶性循环。每次修复都会去掉另一个防护栏,结果会迅速加剧,形成一个编译良好但脆弱且难以维护的代码库。相反,如果你强制 AI 在每次迭代中尊重类型安全,你会创建一个美德循环。每次迭代都会紧缩防护栏,代码库变得更干净,质量会迅速提高,变得可靠且值得信赖。

这是我认为能够提供持久代码质量的系统。每次迭代都是为了提高标准,而不是降低标准。这也是最好的工程团队选择强类型语言的原因。 类型安全是可维护性的基线防护栏,让 AI 忽略它将保证你的应用程序永远无法达到生产级别。

Brad Eckert 是一位终身企业家和工程领导者,拥有十多年的经验,从产品的想法阶段到客户交付和更远。作为 MIT 的毕业生,他现在是 Woz 的联合创始人和 CTO,Woz 是一家由 Y Combinator 支持的 AI 平台,允许任何人无需编码即可构建和扩展软件业务。