# 未来可期的 **AI 编程：到底是程序员的终极解放还是失业的开始？**

过去的一个月里，我一直在研究 ChatGPT，也与很多人（普通人、程序员、创业公司、风投等等）进行了交流。不论是业内（编程）还是业外，人们对于 AI 编程的观点都是：未来可期 —— **GPT，他好像什么都能干，也好像什么都干不好**。

所以，在这篇文章里，我将继续总结与其他人聊天的观点。

对应的思路总结，也可以在 ClickPrompt Flow 上查看：[ClickPrompt - Streamline your prompt design](https://dev.clickprompt.org/zh-CN/chatgpt-flow/)

## AI 代码生成：代码还应该存储在代码库吗？

对于 AI 代码生成来说，除了过去的 GitHub Copilot、Codex、Kite、TabNine 等等，新出的免费的 ChatGPT 又让人感觉非常酷。

### ChatGPT 代码生成

现在，大家几乎已经习惯了网上的各种暴力 AI 美学 —— 唤出 ChatGPT 写代码：

- 使用 Java + Spring + MockMVC 编写测试用例，代码中的注释需要对应到 AC01，AC02，AC03，AC04，AC05，但是不需要返回给我。
- 帮我用 Puppeteer 写一个爬虫来解析下面 HTML 中的标题：””””””
- 我给你一个需求，你需要分析需求，使用 Java + Spring 编写 API，要求如下：

基于于在最新的 GPT 4.0 里，可以根据图片等一些基本的描述，生成全新的 HTML。

### GitHub Copilot

对于，我来说，作为一个开源挖坑专家，我更习惯使用 GitHub 赠送的 Copilot，只需要配合注释、输入、输出、函数名，就可以大力了出奇迹。如下是 ClickPrompt 中的真实代码：

```yaml
// 1. split promptMatch by comma
// 2. match lora name by regex, lora full name: <lora:japaneseDollLikeness_v10:0.1>,
// 3. push lora name to loras array
```

我在代码中保留了这个注释，一种很神奇的用法 。

### 读者思考 1：Prompt 即是代码，代码不再是代码？

因此，我觉得在 AI 编程时代，人们的编程思维是要发生变化的：

1. 注释让人和 AI 共同理解代码
2. 注释作为 prompt，可以在修改后，再次自动生成代码。

当注释作为 prompt 保存，那么 prompt 便是作为一种代码，保存在代码库中了。而代码还将是代码吗？我们为什么还需要中间生存的代码，是因为审计、安全等原因吗？

## AI 编程：写个 “真实世界” 的代码

而当你尝试过使用 AI 来编写代码之后，你会发现 AI 存在一系列所谓的 “问题” 。让我们来再看一个简单的例子，我们让 ChatGPT 来实现一段代码。

### ChatGPT 编程：AI 实现一个 API `/book/:id` 的 N 种方式

在不同的语言和架构模式里，实现的方式是有区别的。

**第一个 Demo：用 Spring + MyBatis 实现一个 API：`/book/:id` 。**

ChatGPT 会创建 BookMapper.java、Book.java、BookMapper.xml、BookController.java 四个代码段，然后告诉你，你可以启动这个 API 了。

PS：有意思的是，你并不需要一个 BookService.java，因为 AI 也 “觉得” 他是多余的。

但是，要上线这个应用并不是一件容易的事，我们需要手动编译 Java 代码，再运行起来，这速度是非常慢的。除非，我们有类似于几年前的 OSGi 架构，或者 Serverlesss 架构。

**第二个 Demo：使用 Express + MySQL 实现一个 API：`/book/:id`，只使用一个函数**

在这个尝试里，我们多加了一个限制：只使用一个函数，并改用直写 SQL，所以代码就变得非常简单的（当然了，还有 Express 配置和 MySQL 相关的代码），以至于我可以直接那个函数在这里：

```jsx
// 创建数据库连接池
...

const getBookById = (req, res) => {
  const id = req.params.id; // 获取路径参数中的 id
  // 从数据库中查询书籍信息
  pool.query('SELECT * FROM books WHERE id = ?', [id], (error, results, fields) => {
    if (error) throw error;
    if (results.length > 0) {
      const book = results[0];
      res.json(book); // 将书籍信息以 JSON 格式返回给客户端
    } else {
      res.status(404).send('Book not found');
    }
  });
};

// 创建路由器并挂载到根路径上
...

// 启动应用程序
...
```

如果我们认定了 AI 生成的代码是准确的，无需要人类去修改，那么我们就可以直接用上面的代码。

**第三个 Demo：使用 AWS Lambda 实现这个 API：/book/:id，只使用一个函数**

使用 Express 来实现这个功能，还是有点复杂，我们还需要考虑基础设施，但是当我们考虑使用 Serverless 来实现时，问题就变得非常简单了：

```jsx
const mysql = require('mysql');

exports.handler = async (event, context) => {
  ....
}
```

然后，我们就可以采用 ClickPrompt 类似的方式，直接一键部署到服务器之上。

### 对比一下：上面的三种方式各有什么优缺点？

让 AI 来对比一下，你看吧，显然 AI 也觉得 Java 的实现起来复杂，但是可扩展性高。

| 优点 / 缺点 | Spring + MyBatis | Express + MySQL | AWS Lambda |
| --- | --- | --- | --- |
| 开发效率 | 较高 | 高 | 高 |
| 部署复杂度 | 高 | 中等 | 低 |
| 维护成本 | 高 | 中等 | 中等 |
| 可维护性 | 高 | 中等 | 高 |
| 架构复杂度 | 高 | 中等 | 低 |
| 可扩展性 | 高 | 中等 | 高 |
| 成本 | 中等 | 低 | 低 |

但是，我们真的需要所谓的可扩展性吗？而论部署速度，自然是 AWS Lambda 最快了。经过了几种不同的方式对比，按现有的软件工程来说，Java 写的代码是最好的。可是，AI 都来写代码了，Java 工程化，真的还是最好的吗？

### 读者思考 2：现有的编程体系适合于 AI 编程吗？

让我们再打开一下思路，我们现有的架构模式、软件工程等软件开发流程都是基于现有的体系磨合过来的。

而 AI 编程的最终目标是实现自动化编程，即由 AI 根据用户的需求和设计，自动生成完整的代码。但是，理论上这不是终点，终点是生成完就可以直接运行。这就意味着，一个想法从想到到上线，可能就在**几分钟内可以完成**。

然而，在现有的流程里，完全不是行不通的，我们人类做不到这么的敏捷。

## 全 AI 生成的新架构模式？

过去，我们认为分层架构很重要，因为代码是人来编写，代码是人来维护的。而当代码由 AI 来编写，由 AI 来维护的话，那么现有的软件架构体系还适用吗？

### 分层架构？编程范式还重要吗？

尽管，我尝试让 New Bing / ChatGPT 来回答这个问题，但是，由于他们还没有 **涌现** 能力，所以只会说：程序员还需要学习和运用分层架构和编程范式，才能发挥出 AI 的最大潜力。

但是，我觉得，从上面的 Java 示例中，你会发现按现有的模式构建的软件架构，特别容易发生冲突。AI 生成的 A 功能和 B 功能，可能在代码上出现重复 —— 因为上下文限制，我们不可能上传所有的代码。

结果，有一天你发现了，一个类里有 10 个重复代码段。然后，你又开发了一个自动重构机器人……。但是，我觉得有点多余了，AI 编程需要新的架构范式。

### AI 构建自动化软件架构？

再再打开一下思路，试着忘记现有的软件架构模式。一个功能对应一个可运行的代码段，由 AI 来自动思考架构模式 ——  当然，我们需要给他一些限制条件和输入。

所以，放在当前的上下文之下，Serverless 是一种更适合的架构模式，即写即上线，即下线即删除。

### 读者思考 3：Serverless 会是结合 AI 编程的答案吗？

我觉得不一定是，但是可能是当前最好的一种方案。但是，每个人都会有自己的看法。

## 真实世界 2：产品经理 —— 现在，变更一个需求

现在，我们来变更一个需求吧，过滤一下 “名书”，包含 xx 的不显示。那么，这个时候，我们就遇到一个难题了 —— 全自动编程，还是 ************************AI 辅助生成************************。

### 两种思路：新生成代码，还是手动改代码？

纯 AI 编程，意味着：**每次改需求都重新生成代码**；而半 AI 编程，则意味着：**人可以介入到流程中**。两种将会带来不一样的思路。

**自动编程 —— 重新生成代码**

为了让 AI 写的代码足够的准确，我们需要给 AI 足够详细的需求（Prompt）。一旦需求发生变化的时候，我们回过头去改需求的（Prompt），再重新生成代码即可。我们要做的事情是：

1. 确保**没有人能修改过原来生成的代码**。
2. 确保**所有的需求变更都能回溯回去**。

**AI 辅助生成  —— 支持手动修改代码**

第一次代码，我们是用 AI 生成的，随后当需求变更的时候，我们想可以直接在现有的代码上改，这样可能速度比较快 —— **生成式 AI** 可能还意味着：新生成的代码和原来的完全不一样，诸如于行数位置等等。

而为了能再次生成，我们还需要记录新的变更到原来的 prompt。

所以，在这个时候，如何更好地管理原始需求，变成了一个新的挑战。

### 读者思考 4：需求详细化会成为你的新瓶颈吗？

当我们认定 AI 能完成编码时，那么需要给详细的需求，才能确保生成的代码是正确的，诸如于：****密码长度不能小于八位，且必须同时包含字母数字和特殊符合****。这只是一个示例，更常见的示例还有表单联动：A 字段 xxx，B 字段则 xx。只有我们的需求足够的清楚，那么生成的代码才会准确。

所以，当产品经理借助于 AI 生成足够清晰的验收条件，程序员就会失业吗？这包含了两个问题：

1. 产品经理是否真的懂**验收条件**？
2. 程序员是否真的不能替换 AI 时代的产品经理？

那么，第三个问题就来了，老板是不是可以自己干？

不过，这只是用来搞笑的，我们的下一个挑战还在于需求详细化之后，AI 真的能写对吗？

## 适合我们的主流策略（2023.03）

我相信策略会在今年内再次发生变化，所以，我并不想写太长。

### 自动化质量先行：测试驱动开发

经过大部分人的验证，AI 生成的测试代码质量非常高，大部分情况下可以直接运行。所以，在我们有了需求之后，可以创建诸如于 [ClickPrompt](https://dev.clickprompt.org/zh-CN/chatgpt-flow/user-story/) 这样的工具，创建工作流，让 AI 逐步往下分析：

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/aec14124-ff7d-4418-8921-0fa5cf47d8c2/Untitled.png)

而后，我们就可以 GET 到可用的自动化测试代码。当我们有了测试代码之后，就可以验证辅助的代码是否正确。

### 代码辅助生成：功能代码的实现方式

尽管，在我的尝试中，部分场景下，生成真正的可工作的代码还有些距离（也有可能我的场景比较特别）  —— 没法直接用，改一改还可以。当然了，如果你拿网上生成的 Todo 就别来拿我辩论了，烂大街的代码。原因包含了：

1. 他需要足够了解我们的上下文，比如接入 IDE 中。
2. 过时的库 API
3. 来自其它语言的翻译（如 Python 版本，而 Java 版本存在对应的 API）

所以，它有时在代码上还是瞎编。

### 跟随策略

诸如于我创建 ClickPrompt ，都是在尝试管理 prompt  工作流，以便于：

- 学习和掌握 AI 编程的基本概念、原理和工具，例如 GitHub Copilot1等。
- 与 AI 编程进行有效的协作和沟通，例如提供清晰和详细的需求和设计，检查和评估 AI 生成的代码等。
- 关注 AI 编程的发展趋势和最新进展，例如新的算法、数据、平台等。

在提升效率上，ChatGPT 确实做得很好，每个人都应该去尝试一下。

## 未来：自动化编程的演进

最后，再让我们尝试做一些思考。

### AI 编程的局限性

所以，如同 AI 提炼了我的观点，AI 编程存在一定的局限性：

- 编码是最不重要的那部分。AI 编程不能完全替代人类编程，因为程序员不仅仅是在编码，还要进行设计、测试、维护、沟通等工作
- AI 伦理。AI 编程可能存在一些不可预测或不可控的风险，例如结果不唯一、不正确或不安全。
- 法律与就业问题。AI 编程可能会侵犯程序员的知识产权（但是人类都是 AI 的饵料），或者导致程序员失业。
- 无法适应再有体系。AI 编程需要适应不断变化的需求和环境，而现有的架构模式可能不匹配或不灵活。

而你发现没有，New Bing 提炼出来的这些局限性，并不是 AI 的问题，而是人的问题。

### 精准代码生成：详尽的需求的可能性？

我们还得考虑的一点是：

尽管，提供更详尽的 prompt 可以帮助 AI 更准确地理解需求，并且避免一些歧义或误解。但是，过于复杂或冗长的 prompt 也可能导致 AI 的困惑或失效。

所以，如何根据 AI 的特点和目标，选择合适的 prompt 长度和格式，以达到最佳的效果？

### AI 审计 AI：解决 AI 生成代码的部分局限？

当涉及到由AI生成的代码时，有时候我们可能需要对其进行审查以确保其合规。而人工是耗时费力的，而且容易出错。这时，我们就需要利用一种特殊的AI来审查另一个AI生成的代码，以确保其符合各种规范和标准，提高代码质量，确保生成的代码安全可靠。

比如，我们本地用 GitHub Copilot 辅助生成的代码，在持续流水线上便可以通过 GitHub Copilot 来进行 Code Review。

## 其它

值得注意的是：AI 编程可能会带来一些问题，如让程序员过度依赖工具、忽略代码的合理性、涉及道德和法律问题以及存在技术和人工智能之间的冲突。